brcm2708: update to latest patches from RPi foundation
authorÁlvaro Fernández Rojas <noltari@gmail.com>
Tue, 4 Feb 2020 18:02:53 +0000 (19:02 +0100)
committerÁlvaro Fernández Rojas <noltari@gmail.com>
Tue, 4 Feb 2020 18:14:13 +0000 (19:14 +0100)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
1197 files changed:
target/linux/brcm2708/modules/sound.mk
target/linux/brcm2708/patches-4.19/950-0202-staging-bcm2835-camera-Move-module-info-to-the-end.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0203-staging-bcm2835-camera-Move-module-info-to-the-end.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0203-staging-vchiq_arm-Fix-platform-device-unregistration.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0204-staging-vchiq_arm-Fix-camera-device-registration.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0204-staging-vchiq_arm-Fix-platform-device-unregistration.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0205-staging-bcm2835-camera-Provide-more-specific-probe-e.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0205-staging-vchiq_arm-Fix-camera-device-registration.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0206-staging-bcm2835-camera-Add-hint-about-possible-fault.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0206-staging-bcm2835-camera-Provide-more-specific-probe-e.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0207-staging-bcm2835-camera-Add-hint-about-possible-fault.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0207-staging-vchiq_arm-Improve-error-handling-on-loading-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0208-staging-bcm2835-camera-Do-not-bulk-receive-from-serv.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0209-staging-bcm2835-camera-Ensure-H264-header-bytes-get-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0209-staging-vchiq_arm-Improve-error-handling-on-loading-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0210-staging-bcm2835-camera-Correctly-denote-key-frames-i.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0210-staging-bcm2835-camera-Do-not-bulk-receive-from-serv.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0211-staging-bcm2835-camera-Ensure-H264-header-bytes-get-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0211-staging-bcm2835-camera-Return-early-on-errors.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0212-staging-bcm2835-camera-Correctly-denote-key-frames-i.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0212-staging-bcm2835-camera-Remove-dead-email-addresses.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0213-staging-bcm2835-camera-Fix-comment-style-violations.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0213-staging-bcm2835-camera-Return-early-on-errors.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0214-staging-bcm2835-camera-Fix-spacing-around-operators.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0214-staging-bcm2835-camera-Remove-dead-email-addresses.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0215-staging-bcm2835-camera-Fix-comment-style-violations.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0215-staging-bcm2835-camera-Reduce-length-of-enum-names.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0216-staging-bcm2835-camera-Fix-multiple-line-dereference.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0216-staging-bcm2835-camera-Fix-spacing-around-operators.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0217-staging-bcm2835-camera-Fix-brace-style-issues.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0217-staging-bcm2835-camera-Reduce-length-of-enum-names.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0218-staging-bcm2835-camera-Fix-missing-lines-between-ite.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0218-staging-bcm2835-camera-Fix-multiple-line-dereference.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0219-staging-bcm2835-camera-Fix-brace-style-issues.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0219-staging-bcm2835-camera-Fix-logical-continuation-spli.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0220-staging-bcm2835-camera-Fix-missing-lines-between-ite.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0220-staging-bcm2835-camera-Fix-open-parenthesis-alignmen.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0221-staging-bcm2835-camera-Fix-logical-continuation-spli.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0221-staging-bcm2835-camera-Set-sequence-number-correctly.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0222-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0222-staging-bcm2835-camera-Fix-open-parenthesis-alignmen.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0223-staging-bcm2835-camera-Avoid-unneeded-internal-decla.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0223-staging-bcm2835-camera-Set-sequence-number-correctly.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0224-staging-bcm2835-camera-Add-multiple-inclusion-protec.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0224-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0225-staging-bcm2835-camera-Avoid-unneeded-internal-decla.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0225-staging-bcm2835-camera-Unify-header-inclusion-define.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0226-staging-bcm2835-camera-Add-multiple-inclusion-protec.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0226-staging-bcm2835-camera-Fix-alignment-should-match-op.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0227-staging-bcm2835-camera-Fix-multiple-assignments-shou.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0227-staging-bcm2835-camera-Unify-header-inclusion-define.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0228-staging-bcm2835-camera-Fix-alignment-should-match-op.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0228-staging-bcm2835-camera-Fix-up-all-formatting-in-mmal.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0229-staging-bcm2835-camera-Fix-multiple-assignments-shou.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0229-staging-bcm2835-camera-Use-enums-for-max-value-in-co.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0230-staging-bcm2835-camera-Correct-V4L2_CID_COLORFX_CBCR.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0230-staging-bcm2835-camera-Fix-up-all-formatting-in-mmal.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0231-staging-bcm2835-camera-Remove-amend-some-obsolete-co.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0231-staging-bcm2835-camera-Use-enums-for-max-value-in-co.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0232-staging-bcm2835-camera-Correct-V4L2_CID_COLORFX_CBCR.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0232-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0233-staging-bcm2835-camera-Remove-amend-some-obsolete-co.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0233-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0234-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0234-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0235-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0235-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0236-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0236-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0237-staging-mmal-vchiq-Add-support-for-event-callbacks.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0237-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0238-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0238-staging-vc04_services-Support-sending-data-to-MMAL-p.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0239-staging-mmal-vchiq-Add-support-for-event-callbacks.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0239-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0240-staging-vc04_services-Add-new-vc-sm-cma-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0240-staging-vc04_services-Support-sending-data-to-MMAL-p.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0241-staging-vc-sm-cma-Fixup-driver-for-older-VCHI-APIs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0241-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0242-staging-vc04_services-Add-new-vc-sm-cma-driver.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0242-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0243-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0243-staging-vc-sm-cma-Fixup-driver-for-older-VCHI-APIs.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0244-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0244-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0245-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0245-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0246-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0246-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0247-staging-bcm2835-camera-Fix-stride-on-RGB3-BGR3-forma.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0247-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0248-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0248-tpm-Make-SECURITYFS-a-weak-dependency.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0249-Add-overlay-for-SLB9760-Iridium-LetsTrust-TPM.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0249-staging-bcm2835-camera-Fix-stride-on-RGB3-BGR3-forma.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0250-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0250-tpm-Make-SECURITYFS-a-weak-dependency.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0251-Add-overlay-for-SLB9760-Iridium-LetsTrust-TPM.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0251-overlays-Update-README-with-removal-of-lirc-rpi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0252-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0252-staging-bcm2835-camera-Check-the-error-for-REPEAT_SE.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0253-gpio-ir-change-default-pull-configuration-to-up.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0253-overlays-Update-README-with-removal-of-lirc-rpi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0254-firmware-raspberrypi-Report-the-fw-variant-during-pr.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0254-staging-bcm2835-camera-Check-the-error-for-REPEAT_SE.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0255-firmware-raspberrypi-Report-the-fw-git-hash-during-p.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0255-gpio-ir-change-default-pull-configuration-to-up.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0256-arm64-dts-broadcom-Enable-fixups-for-overlays.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0256-firmware-raspberrypi-Report-the-fw-variant-during-pr.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0257-dtoverlays-fe-pi-audio-fix-sgtl5000-compatible-strin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0257-firmware-raspberrypi-Report-the-fw-git-hash-during-p.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0258-arm64-dts-broadcom-Enable-fixups-for-overlays.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0258-bcm2835_smi-re-add-dereference-to-fix-DMA-transfers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0259-dtoverlays-fe-pi-audio-fix-sgtl5000-compatible-strin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0259-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0260-ASoC-Add-support-for-AudioSense-Pi-add-on-soundcard.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0260-bcm2835_smi-re-add-dereference-to-fix-DMA-transfers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0261-BCM270X-Adding-device-tree-support-for-AudioSense-Pi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0261-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0262-ASoC-Add-support-for-AudioSense-Pi-add-on-soundcard.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0262-overlays-sdio-Add-enhanced-1-bit-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0263-BCM270X-Adding-device-tree-support-for-AudioSense-Pi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0263-dwc_otg-fix-bug-with-port_addr-assignment-for-single.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0264-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0264-overlays-sdio-Add-enhanced-1-bit-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0265-dwc_otg-fix-bug-with-port_addr-assignment-for-single.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0265-pwm-Send-a-uevent-on-the-pwmchip-device-upon-channel.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0266-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0266-overlays-Add-ssd1306-overlay-for-OLED-display.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0267-overlays-mcp23017-Support-the-MCP23008.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0267-pwm-Send-a-uevent-on-the-pwmchip-device-upon-channel.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0268-overlays-Add-mcp342x-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0268-overlays-Add-ssd1306-overlay-for-OLED-display.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0269-char-vcio-Add-compat-ioctl-handling.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0269-overlays-mcp23017-Support-the-MCP23008.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0270-char-vcio-Fail-probe-if-rpi_firmware-is-not-found.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0270-overlays-Add-mcp342x-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0271-char-vcio-Add-compat-ioctl-handling.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0271-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0272-char-vcio-Fail-probe-if-rpi_firmware-is-not-found.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0272-staging-bcm2835-camera-Add-sanity-checks-for-queue_s.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0273-staging-bcm2835-camera-Set-the-field-value-within-ea.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0273-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0274-char-vc_mem-Fix-up-compat-ioctls-for-64bit-kernel.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0274-staging-bcm2835-camera-Add-sanity-checks-for-queue_s.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0275-char-vc_mem-Fix-all-coding-style-issues.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0275-staging-bcm2835-camera-Set-the-field-value-within-ea.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0276-char-vc_mem-Fix-up-compat-ioctls-for-64bit-kernel.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0276-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0277-char-vc_mem-Fix-all-coding-style-issues.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0277-mfd-Add-rpi_sense_core-of-compatible-string.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0278-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0278-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0279-input-rpi-ft5406-Clear-build-warning-on-64-bit-build.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0279-mfd-Add-rpi_sense_core-of-compatible-string.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0280-dtoverlays-Correct-DT-handling-camera-GPIOs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0280-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0281-input-rpi-ft5406-Clear-build-warning-on-64-bit-build.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0281-media-ov5647-Use-gpiod_set_value_cansleep.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0282-dtoverlays-Correct-DT-handling-camera-GPIOs.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0282-media-bcm2835-unicam-Power-on-subdev-on-open-release.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0283-audioinjector-octo-revert-to-dummy-supplies.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0283-media-ov5647-Use-gpiod_set_value_cansleep.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0284-media-bcm2835-unicam-Power-on-subdev-on-open-release.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0284-staging-bcm2835-camera-Correct-ctrl-min-max-step-def.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0285-audioinjector-octo-revert-to-dummy-supplies.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0285-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0286-staging-bcm2835-camera-Correct-ctrl-min-max-step-def.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0286-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0287-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0287-video-bcm2708_fb-Add-compat_ioctl-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0288-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0288-video-bcm2708_fb-Fix-warnings-on-64-bit-builds.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Add-compat_ioctl-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Clean-up-coding-style-issues.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0290-bcm2835-dma-Add-support-for-per-channel-flags.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0290-video-bcm2708_fb-Fix-warnings-on-64-bit-builds.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0291-bcm283x-Set-the-DISDEBUG-flag-for-SD-transfers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0291-video-bcm2708_fb-Clean-up-coding-style-issues.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0292-ASoC-pcm512x-Implement-the-digital_mute-interface.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0292-bcm2835-dma-Add-support-for-per-channel-flags.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0293-ASoC-pcm512x-Fix-a-double-unlock-in-pcm512x_digital_.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0293-bcm283x-Set-the-DISDEBUG-flag-for-SD-transfers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0294-ASoC-pcm512x-Implement-the-digital_mute-interface.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0294-usb-dwc_otg-Clean-up-build-warnings-on-64bit-kernels.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0295-ASoC-pcm512x-Fix-a-double-unlock-in-pcm512x_digital_.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0295-usb-dwc_otg-Use-dma-allocation-for-mphi-dummy_send-b.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0296-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0296-usb-dwc_otg-Clean-up-build-warnings-on-64bit-kernels.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0297-staging-vc-sm-cma-Correct-DMA-configuration.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0297-usb-dwc_otg-Use-dma-allocation-for-mphi-dummy_send-b.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0298-staging-vc-sm-cma-Use-a-void-pointer-as-the-handle-w.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0298-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0299-staging-vc-sm-cma-Correct-DMA-configuration.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0299-staging-vc-sm-cma-Fix-up-for-64bit-builds.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0300-configs-Enable-the-AD193x-codecs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0300-staging-vc-sm-cma-Use-a-void-pointer-as-the-handle-w.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0301-overlays-balenaFin-v1.1.0-carrier-board-update.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0301-staging-vc-sm-cma-Fix-up-for-64bit-builds.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0302-configs-Enable-the-AD193x-codecs.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0302-gpu-vc4-fkms-Update-driver-to-not-use-plane-crtc.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0303-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0303-overlays-balenaFin-v1.1.0-carrier-board-update.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0304-gpu-vc4-fkms-Update-driver-to-not-use-plane-crtc.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0304-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0305-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0305-staging-mmal-vchiq-Always-return-the-param-size-from.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0306-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0306-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0307-staging-bcm2835_codec-Query-supported-formats-from-t.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0307-staging-mmal-vchiq-Always-return-the-param-size-from.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0308-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0308-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0309-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0309-staging-bcm2835_codec-Query-supported-formats-from-t.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0310-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0310-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0311-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0311-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0312-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0312-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0313-drm-vc4-Don-t-wait-for-vblank-on-fkms-cursor-updates.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0313-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0314-Fix-for-Pisound-kernel-module-in-Real-Time-kernel-co.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0314-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0315-Added-mute-stream-func.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0315-drm-vc4-Don-t-wait-for-vblank-on-fkms-cursor-updates.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0316-Fix-for-Pisound-kernel-module-in-Real-Time-kernel-co.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0316-lan78xx-EEE-support-is-now-a-PHY-property.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0317-Added-mute-stream-func.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0317-staging-vc_sm_cma-Remove-erroneous-misc_deregister.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0318-lan78xx-EEE-support-is-now-a-PHY-property.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0318-vcsm-Fix-makefile-include-on-out-of-tree-builds.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0319-staging-vc_sm_cma-Remove-erroneous-misc_deregister.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0319-vcsm-Remove-set-but-unused-variable.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0320-vcsm-Fix-makefile-include-on-out-of-tree-builds.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0320-vcsm-Reduce-scope-of-local-functions.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0321-staging-bcm2835-codec-NULL-component-handle-on-queue.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0321-vcsm-Remove-set-but-unused-variable.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0322-staging-vc-sm-cma-Remove-the-debugfs-directory-on-re.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0322-vcsm-Reduce-scope-of-local-functions.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0323-staging-bcm2835-codec-NULL-component-handle-on-queue.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0323-staging-vc-sm-cma-Use-devm_-allocs-for-sm_state.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0324-staging-vc-sm-cma-Don-t-fail-if-debugfs-calls-fail.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0324-staging-vc-sm-cma-Remove-the-debugfs-directory-on-re.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0325-staging-vc-sm-cma-Ensure-mutex-and-idr-are-destroyed.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0325-staging-vc-sm-cma-Use-devm_-allocs-for-sm_state.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0326-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0326-staging-vc-sm-cma-Don-t-fail-if-debugfs-calls-fail.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0327-bcm2835-sdhost-Allow-for-sg-entries-that-cross-pages.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0327-staging-vc-sm-cma-Ensure-mutex-and-idr-are-destroyed.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0328-overlays-sdio-Added-4-bit-support-on-GPIOs-34-39.-29.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0328-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0329-bcm2835-sdhost-Allow-for-sg-entries-that-cross-pages.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0329-overlays-Fix-multiple-instantiation-of-sc16is7xx.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0330-bcm2835-mmc-Fix-DMA-channel-leak.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0330-overlays-sdio-Added-4-bit-support-on-GPIOs-34-39.-29.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0331-bcm2835-mmc-Fix-struct-mmc_host-leak-on-probe.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0331-overlays-Fix-multiple-instantiation-of-sc16is7xx.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0332-bcm2835-mmc-Fix-DMA-channel-leak.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0332-bcm2835-mmc-Fix-duplicate-free_irq-on-remove.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0333-bcm2835-mmc-Fix-struct-mmc_host-leak-on-probe.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0333-bcm2835-mmc-Handle-mmc_add_host-errors.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0334-bcm2835-mmc-Deduplicate-reset-of-driver-data-on-remo.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0334-bcm2835-mmc-Fix-duplicate-free_irq-on-remove.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0335-bcm2835-mmc-Handle-mmc_add_host-errors.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0335-overlays-Add-max17040-support-to-i2c-sensor.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0336-bcm2835-mmc-Deduplicate-reset-of-driver-data-on-remo.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0336-media-bcm2835-unicam-Add-support-for-enum-framesizes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0337-overlays-Add-max17040-support-to-i2c-sensor.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0337-staging-bcm2835-codec-Refactor-default-resolution-co.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0338-media-bcm2835-unicam-Add-support-for-enum-framesizes.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0338-nvmem-add-type-attribute.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0339-rtc-rv3028-add-new-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0339-staging-bcm2835-codec-Refactor-default-resolution-co.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0340-nvmem-add-type-attribute.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0340-overlays-Add-rv3028-to-i2c-rtc.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0341-ASoC-tlv320aic32x4-SND_SOC_DAPM_MICBIAS-is-deprecate.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0341-rtc-rv3028-add-new-driver.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0342-ASoC-tlv320aic32x4-Break-out-clock-setting-into-sepa.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0342-overlays-Add-rv3028-to-i2c-rtc.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0343-ASoC-tlv320aic32x4-Properly-Set-Processing-Blocks.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0343-ASoC-tlv320aic32x4-SND_SOC_DAPM_MICBIAS-is-deprecate.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0344-ASoC-tlv320aic32x4-Break-out-clock-setting-into-sepa.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0344-ASoC-tlv320aic32x4-Model-PLL-in-CCF.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0345-ASoC-tlv320aic32x4-Model-CODEC_CLKIN-in-CCF.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0345-ASoC-tlv320aic32x4-Properly-Set-Processing-Blocks.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0346-ASoC-tlv320aic32x4-Model-DAC-ADC-dividers-in-CCF.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0346-ASoC-tlv320aic32x4-Model-PLL-in-CCF.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0347-ASoC-tlv320aic32x4-Model-BDIV-divider-in-CCF.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0347-ASoC-tlv320aic32x4-Model-CODEC_CLKIN-in-CCF.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0348-ASoC-tlv320aic32x4-Control-clock-gating-with-CCF.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0348-ASoC-tlv320aic32x4-Model-DAC-ADC-dividers-in-CCF.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0349-ASoC-tlv320aic32x4-Model-BDIV-divider-in-CCF.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0349-ASoC-tlv320aic32x4-Move-aosr-and-dosr-setting-to-sep.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0350-ASoC-tlv320aic32x4-Control-clock-gating-with-CCF.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0350-ASoC-tlv320aic32x4-Dynamically-Determine-Clocking.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0351-ASoC-tlv320aic32x4-Move-aosr-and-dosr-setting-to-sep.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0351-ASoC-tlv320aic32x4-Restructure-set_dai_sysclk.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0352-ASoC-tlv320aic32x4-Dynamically-Determine-Clocking.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0352-ASoC-tlv320aic32x4-Remove-mclk-references.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0353-ASoC-tlv320aic32x4-Allow-192000-Sample-Rate.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0353-ASoC-tlv320aic32x4-Restructure-set_dai_sysclk.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0354-ASoC-tlv320aic32x4-Only-enable-with-common-clock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0354-ASoC-tlv320aic32x4-Remove-mclk-references.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0355-ASoC-tlv320aic32x4-Allow-192000-Sample-Rate.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0355-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0356-ASoC-tlv320aic32x4-Change-author-s-name.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0356-ASoC-tlv320aic32x4-Only-enable-with-common-clock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0357-ASoC-tlv320aic32x4-Update-copyright-and-use-SPDX-ide.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0357-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0358-ASoC-tlv320aic32x4-Add-Switch-for-Setting-Common-Mod.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0358-ASoC-tlv320aic32x4-Change-author-s-name.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0359-ASoC-tlv320aic32x4-Add-Playback-PowerTune-Controls.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0359-ASoC-tlv320aic32x4-Update-copyright-and-use-SPDX-ide.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0360-ASoC-tlv320aic32x4-Add-Switch-for-Setting-Common-Mod.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0360-dtoverlays-Add-Support-for-the-UDRC-DRAWS.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0361-ASoC-tlv320aic32x4-Add-Playback-PowerTune-Controls.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0361-dwc_otg-only-do_split-when-we-actually-need-to-do-a-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0362-dtoverlays-Add-Support-for-the-UDRC-DRAWS.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0363-Input-ili210x-add-DT-binding-document.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0363-dwc_otg-only-do_split-when-we-actually-need-to-do-a-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0364-BCM2708-Add-core-Device-Tree-support-ilitek251x.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0364-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0365-Input-ili210x-add-DT-binding-document.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0365-dwc_otg-fix-locking-around-dequeueing-and-killing-UR.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0366-BCM2708-Add-core-Device-Tree-support-ilitek251x.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0366-rtc-rv3028-Add-backup-switchover-mode-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0367-dt-bindings-rv3028-backup-switchover-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0367-dwc_otg-fix-locking-around-dequeueing-and-killing-UR.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0368-overlays-Add-rv3028-backup-switchover-support-to-i2c.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0368-rtc-rv3028-Add-backup-switchover-mode-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0369-Maxim-MAX98357A-I2S-DAC-overlay-2935.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0369-dt-bindings-rv3028-backup-switchover-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0370-overlays-Add-rv3028-backup-switchover-support-to-i2c.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0370-sound-Fixes-for-audioinjector-octo-under-4.19.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0371-Maxim-MAX98357A-I2S-DAC-overlay-2935.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0371-overlays-Add-PiGlow-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0372-sound-Fixes-for-audioinjector-octo-under-4.19.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0372-staging-bcm2835-audio-Clean-up-mutex-locks.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0373-overlays-Add-PiGlow-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0373-staging-bcm2835-audio-Remove-redundant-spdif-stream-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0374-staging-bcm2835-audio-Clean-up-include-files-in-bcm2.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0374-staging-bcm2835-audio-Clean-up-mutex-locks.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0375-staging-bcm2835-audio-Remove-redundant-spdif-stream-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0375-staging-bcm2835-audio-Remove-redundant-substream-mas.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0376-staging-bcm2835-audio-Clean-up-include-files-in-bcm2.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0376-staging-bcm2835-audio-Fix-mute-controls-volume-handl.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0377-staging-bcm2835-audio-Remove-redundant-function-call.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0377-staging-bcm2835-audio-Remove-redundant-substream-mas.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0378-staging-bcm2835-audio-Fix-mute-controls-volume-handl.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0378-staging-bcm2835-audio-Remove-superfluous-open-flag.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0379-staging-bcm2835-audio-Drop-useless-running-flag-and-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0379-staging-bcm2835-audio-Remove-redundant-function-call.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0380-staging-bcm2835-audio-Fix-incorrect-draining-handlin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0380-staging-bcm2835-audio-Remove-superfluous-open-flag.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0381-staging-bcm2835-audio-Drop-useless-running-flag-and-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0381-staging-bcm2835-audio-Kill-unused-spinlock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0382-staging-bcm2835-audio-Fix-incorrect-draining-handlin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0382-staging-bcm2835-audio-Use-PCM-runtime-values-instead.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0383-staging-bcm2835-audio-Drop-unnecessary-pcm-indirect-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0383-staging-bcm2835-audio-Kill-unused-spinlock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0384-staging-bcm2835-audio-Drop-useless-NULL-check.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0384-staging-bcm2835-audio-Use-PCM-runtime-values-instead.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0385-staging-bcm2835-audio-Drop-unnecessary-pcm-indirect-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0385-staging-bcm2835-audio-Propagate-parameter-setup-erro.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0386-staging-bcm2835-audio-Drop-debug-messages-in-bcm2835.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0386-staging-bcm2835-audio-Drop-useless-NULL-check.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0387-staging-bcm2835-audio-Drop-superfluous-mutex-lock-du.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0387-staging-bcm2835-audio-Propagate-parameter-setup-erro.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0388-staging-bcm2835-audio-Add-10ms-period-constraint.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0388-staging-bcm2835-audio-Drop-debug-messages-in-bcm2835.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0389-staging-bcm2835-audio-Drop-superfluous-mutex-lock-du.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0389-staging-bcm2835-audio-Make-single-vchi-handle.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0390-staging-bcm2835-audio-Add-10ms-period-constraint.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0390-staging-bcm2835-audio-Code-refactoring-of-vchiq-acce.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0391-staging-bcm2835-audio-Make-single-vchi-handle.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0391-staging-bcm2835-audio-Operate-non-atomic-PCM-ops.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0392-staging-bcm2835-audio-Code-refactoring-of-vchiq-acce.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0392-staging-bcm2835-audio-Use-card-private_data.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0393-staging-bcm2835-audio-Operate-non-atomic-PCM-ops.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0393-staging-bcm2835-audio-Use-standard-error-print-helpe.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0394-staging-bcm2835-audio-Remove-unnecessary-header-file.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0394-staging-bcm2835-audio-Use-card-private_data.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0395-staging-bcm2835-audio-Move-module-parameter-descript.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0395-staging-bcm2835-audio-Use-standard-error-print-helpe.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0396-staging-bcm2835-audio-Remove-unnecessary-header-file.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0396-staging-bcm2835-audio-Use-coherent-device-buffers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0397-staging-bcm2835-audio-Move-module-parameter-descript.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0397-staging-bcm2835-audio-Set-SNDRV_PCM_INFO_SYNC_APPLPT.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0398-staging-bcm2835-audio-Simplify-PCM-creation-helpers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0398-staging-bcm2835-audio-Use-coherent-device-buffers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0399-staging-bcm2835-audio-Set-SNDRV_PCM_INFO_SYNC_APPLPT.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0399-staging-bcm2835-audio-Simplify-kctl-creation-helpers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0400-staging-bcm2835-audio-Simplify-PCM-creation-helpers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0400-staging-bcm2835-audio-Simplify-card-object-managemen.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0401-staging-bcm2835-audio-Simplify-kctl-creation-helpers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0401-staging-bcm2835-audio-unify-FOURCC-command-definitio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0402-staging-bcm2835-audio-Simplify-card-object-managemen.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0402-staging-bcm2835-audio-don-t-initialize-memory-twice.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0403-staging-bcm2835-audio-reorder-variable-declarations-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0403-staging-bcm2835-audio-unify-FOURCC-command-definitio.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0404-staging-bcm2835-audio-don-t-initialize-memory-twice.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0404-staging-bcm2835-audio-use-anonymous-union-in-struct-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0405-staging-bcm2835-audio-more-generic-probe-function-na.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0405-staging-bcm2835-audio-reorder-variable-declarations-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0406-staging-bcm2835-audio-rename-platform_driver-structu.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0406-staging-bcm2835-audio-use-anonymous-union-in-struct-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0407-staging-bcm2835-audio-more-generic-probe-function-na.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0407-staging-bcm2835-audio-update-TODO.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0408-staging-bcm2835-audio-interpolate-audio-delay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0408-staging-bcm2835-audio-rename-platform_driver-structu.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0409-staging-bcm2835-audio-Enable-compile-test.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0409-staging-bcm2835-audio-update-TODO.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0410-staging-bcm2835-audio-interpolate-audio-delay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0410-staging-bcm2835-audio-use-module_platform_driver-mac.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0411-staging-bcm2835-audio-Enable-compile-test.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0411-staging-bcm2835-audio-double-free-in-init-error-path.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0412-dts-Increase-default-coherent-pool-size.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0412-staging-bcm2835-audio-use-module_platform_driver-mac.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0413-lan78xx-use-default-alignment-for-rx-buffers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0413-staging-bcm2835-audio-double-free-in-init-error-path.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0414-dts-Increase-default-coherent-pool-size.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0414-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0415-lan78xx-use-default-alignment-for-rx-buffers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0415-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0416-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0416-staging-mmal-vchiq-Free-the-event-context-for-contro.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0417-BCM270X_DT-Also-set-coherent_pool-1M-for-BT-Pis.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0417-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0418-arm-dts-overlays-rpi-sense-add-upstream-humidity-com.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0418-staging-mmal-vchiq-Free-the-event-context-for-contro.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0419-BCM270X_DT-Also-set-coherent_pool-1M-for-BT-Pis.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0419-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0420-arm-dts-overlays-rpi-sense-add-upstream-humidity-com.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0420-staging-vchiq-mmal-Fix-memory-leak-of-vchiq-instance.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0421-Added-IQaudIO-Pi-Codec-board-support-2969.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0421-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0422-staging-vchiq-mmal-Fix-memory-leak-of-vchiq-instance.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0422-w1-ds2408-reset-on-output_write-retry-with-readback.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0423-Added-IQaudIO-Pi-Codec-board-support-2969.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0423-w1-ds2482-cosmetic-fixes-after-54865314f5a1.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0424-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0424-w1-ds2408-reset-on-output_write-retry-with-readback.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0425-ASoC-decommissioning-driver-for-3Dlab-Nano-soundcard.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0425-w1-ds2482-cosmetic-fixes-after-54865314f5a1.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0426-.gitignore-Add-.dtbo-explicitly.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0426-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0427-ASoC-decommissioning-driver-for-3Dlab-Nano-soundcard.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0427-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0428-.gitignore-Add-.dtbo-explicitly.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0428-usb-dwc_otg-Clean-up-interrupt-claiming-code.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0429-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0429-overlays-Delete-the-deprecated-sdio-1bit-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0430-overlays-Remove-upstream-aux-interrupt-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0430-usb-dwc_otg-Clean-up-interrupt-claiming-code.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0431-overlays-Delete-the-deprecated-sdio-1bit-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0431-overlays-Standardise-on-compatible-brcm-bcm2835.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0432-overlays-Remove-upstream-aux-interrupt-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0432-vc4-Remove-interrupt-and-DMA-trampling.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0433-BCM270X_DT-Add-non-removable-clone-of-mmc-node.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0433-overlays-Standardise-on-compatible-brcm-bcm2835.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0434-BCM270X_DT-usb-Refactor-DTS-and-overlays.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0434-vc4-Remove-interrupt-and-DMA-trampling.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0435-BCM270X_DT-Add-non-removable-clone-of-mmc-node.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0435-overlays-Update-upstream-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0436-BCM270X_DT-usb-Refactor-DTS-and-overlays.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0436-w1-ds2408-Fix-typo-after-49695ac46861-reset-on-outpu.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0437-BCM270X_DT-Rename-Pi-Zero-W-DT-files.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0437-overlays-Update-upstream-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0438-BCM270X_DT-Create-bcm2708-rpi-zero.dts.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0438-w1-ds2408-Fix-typo-after-49695ac46861-reset-on-outpu.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0439-BCM270X_DT-Rename-Pi-Zero-W-DT-files.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0439-overlays-Fix-mmc-related-overlays-after-refactor.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0440-BCM270X_DT-Create-bcm2708-rpi-zero.dts.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0440-Fixed-48k-timing-issue.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0441-overlays-Fix-mmc-related-overlays-after-refactor.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0441-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0442-Fixed-48k-timing-issue.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0442-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0443-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0443-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0444-overlays-Update-w1-gpio-and-w1-gpio-pullup.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0444-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0445-bcm2835-sdhost-Fix-DMA-channel-leak-on-error-remove.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0445-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0446-i2c-bcm2835-Model-Divider-in-CCF.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0446-overlays-Update-w1-gpio-and-w1-gpio-pullup.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0447-bcm2835-sdhost-Fix-DMA-channel-leak-on-error-remove.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0447-staging-vc04_services-Use-correct-cache-line-size.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0448-i2c-bcm2835-Model-Divider-in-CCF.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0448-tty-amba-pl011-allow-shared-interrupt.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0449-ARM-bcm283x-Reduce-register-ranges-for-UART-SPI-and-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0449-staging-vc04_services-Use-correct-cache-line-size.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0450-ARM-bcm283x-Extend-the-WDT-DT-node-out-to-cover-the-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0450-tty-amba-pl011-allow-shared-interrupt.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0451-ARM-bcm283x-Reduce-register-ranges-for-UART-SPI-and-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0451-ARM-dts-Add-label-to-bcm2835-RNG.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0452-ARM-bcm283x-Extend-the-WDT-DT-node-out-to-cover-the-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0452-dts-Use-fb-rather-than-leds-for-dpi-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0453-ARM-dts-Add-label-to-bcm2835-RNG.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0453-BCM270X_DT-Minor-tidy-up.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0454-arm-bcm2835-Fix-FIQ-early-ioremap.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0454-dts-Use-fb-rather-than-leds-for-dpi-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0455-BCM270X_DT-Minor-tidy-up.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0455-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0456-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0456-arm-bcm2835-Fix-FIQ-early-ioremap.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0457-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0457-PCI-brcmstb-Add-dma-range-mapping-for-inbound-traffi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0458-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0458-PCI-brcmstb-Add-MSI-capability.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0459-PCI-brcmstb-Add-dma-range-mapping-for-inbound-traffi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0459-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0460-PCI-brcmstb-Add-MSI-capability.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0460-pcie-brcmstb-Changes-for-BCM2711.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0461-arm-bcm2835-DMA-can-only-address-1GB.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0461-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0462-mmc-bcm2835-sdhost-Support-64-bit-physical-addresses.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0462-pcie-brcmstb-Changes-for-BCM2711.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0463-arm-bcm2835-DMA-can-only-address-1GB.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0463-mmc-sdhci-Mask-spurious-interrupts.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0464-mmc-bcm2835-sdhost-Support-64-bit-physical-addresses.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0464-mmc-sdhci-iproc-Add-support-for-emmc2-of-the-BCM2838.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0465-hwrng-iproc-rng200-Add-BCM2838-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0465-mmc-sdhci-Mask-spurious-interrupts.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0466-mmc-sdhci-iproc-Add-support-for-emmc2-of-the-BCM2838.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0466-thermal-brcmstb_thermal-Add-BCM2838-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0467-hwrng-iproc-rng200-Add-BCM2838-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0467-vchiq-Add-36-bit-address-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0468-bcm2835-pcm.c-Support-multichannel-audio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0468-thermal-brcmstb_thermal-Add-BCM2838-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0469-bcmgenet-constrain-max-DMA-burst-length.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0469-vchiq-Add-36-bit-address-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0470-bcm2835-pcm.c-Support-multichannel-audio.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0470-bcmgenet-Better-coalescing-parameter-defaults.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0471-bcmgenet-constrain-max-DMA-burst-length.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0471-net-genet-enable-link-energy-detect-powerdown-for-ex.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0472-bcmgenet-Better-coalescing-parameter-defaults.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0472-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0473-net-genet-enable-link-energy-detect-powerdown-for-ex.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0473-phy-bcm54213pe-configure-the-LED-outputs-to-be-more-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0474-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0474-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0475-phy-bcm54213pe-configure-the-LED-outputs-to-be-more-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0475-usb-xhci-Disable-the-XHCI-5-second-timeout.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0476-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0476-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0477-spi-bcm2835-enable-shared-interrupt-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0477-usb-xhci-Disable-the-XHCI-5-second-timeout.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0478-drivers-char-add-chardev-for-mmap-ing-Argon-control-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0478-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0479-clk-bcm2835-Don-t-wait-for-pllh-lock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0479-spi-bcm2835-enable-shared-interrupt-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0480-bcm2835-pm-Move-bcm2835-watchdog-s-DT-probe-to-an-MF.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0480-drivers-char-add-chardev-for-mmap-ing-Argon-control-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0481-clk-bcm2835-Don-t-wait-for-pllh-lock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0481-soc-bcm-bcm2835-pm-Add-support-for-power-domains-und.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0482-bcm2835-pm-Move-bcm2835-watchdog-s-DT-probe-to-an-MF.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0482-soc-bcm-bcm2835-pm-Fix-PM_IMAGE_PERI-power-domain-su.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0483-soc-bcm-bcm2835-pm-Add-support-for-power-domains-und.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0483-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0484-soc-bcm-bcm2835-pm-Add-support-for-2711.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0484-soc-bcm-bcm2835-pm-Fix-PM_IMAGE_PERI-power-domain-su.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0485-drm-expand-drm_syncobj_find_fence-to-support-timelin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0485-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0486-drm-v3d-Fix-a-use-after-free-race-accessing-the-sche.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0486-soc-bcm-bcm2835-pm-Add-support-for-2711.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0487-drm-expand-drm_syncobj_find_fence-to-support-timelin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0487-drm-v3d-Add-a-little-debugfs-entry-for-measuring-the.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0488-drm-v3d-Fix-a-use-after-free-race-accessing-the-sche.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0488-drm-v3d-Update-a-comment-about-what-uses-v3d_job_dep.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0489-drm-v3d-Add-a-little-debugfs-entry-for-measuring-the.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0489-drm-v3d-Clean-up-the-reservation-object-setup.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0490-drm-v3d-Add-support-for-submitting-jobs-to-the-TFU.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0490-drm-v3d-Update-a-comment-about-what-uses-v3d_job_dep.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0491-drm-v3d-Clean-up-the-reservation-object-setup.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0491-drm-v3d-Drop-the-dev-argument-to-lock-unlock-of-BO-r.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0492-drm-v3d-Add-missing-fence-timeline-name-for-TFU.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0492-drm-v3d-Add-support-for-submitting-jobs-to-the-TFU.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0493-drm-v3d-Add-more-tracepoints-for-V3D-GPU-rendering.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0493-drm-v3d-Drop-the-dev-argument-to-lock-unlock-of-BO-r.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0494-drm-v3d-Add-missing-fence-timeline-name-for-TFU.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0494-drm-v3d-Drop-unused-v3d_flush_caches.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0495-drm-v3d-Add-more-tracepoints-for-V3D-GPU-rendering.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0495-drm-v3d-Don-t-bother-flushing-L1TD-at-job-start.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0496-drm-v3d-Drop-the-wait-for-L2T-flush-to-complete.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0496-drm-v3d-Drop-unused-v3d_flush_caches.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0497-drm-v3d-Don-t-bother-flushing-L1TD-at-job-start.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0497-drm-v3d-Stop-trying-to-flush-L2C-on-V3D-3.3.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0498-drm-v3d-Drop-the-wait-for-L2T-flush-to-complete.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0498-drm-v3d-Invalidate-the-caches-from-the-outside-in.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0499-drm-v3d-Fix-BO-stats-accounting-for-dma-buf-imported.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0499-drm-v3d-Stop-trying-to-flush-L2C-on-V3D-3.3.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0500-drm-v3d-Invalidate-the-caches-from-the-outside-in.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0500-drm-v3d-Update-top-level-kerneldoc-for-the-addition-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0501-drm-v3d-Fix-BO-stats-accounting-for-dma-buf-imported.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0501-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0502-drm-v3d-Add-support-for-V3D-v4.2.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0502-drm-v3d-Update-top-level-kerneldoc-for-the-addition-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0503-drm-v3d-Don-t-try-to-set-OVRTMUOUT-on-V3D-4.x.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0503-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0504-drm-v3d-Add-support-for-V3D-v4.2.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0504-drm-v3d-Make-sure-the-GPU-is-on-when-measuring-clock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0505-drm-v3d-Add-support-for-2711.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0505-drm-v3d-Don-t-try-to-set-OVRTMUOUT-on-V3D-4.x.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0506-drm-v3d-Make-sure-the-GPU-is-on-when-measuring-clock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0506-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0507-drm-v3d-Add-support-for-2711.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0507-drm-v3d-Hook-up-the-runtime-PM-ops.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0508-drm-v3d-HACK-gut-runtime-pm-for-now.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0508-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0509-drm-v3d-Hook-up-the-runtime-PM-ops.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0509-drm-v3d-Update-to-upstream-IRQ-code.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0510-drm-v3d-HACK-gut-runtime-pm-for-now.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0510-drm-v3d-Rename-the-fence-signaled-from-IRQs-to-irq_f.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0511-drm-v3d-Refactor-job-management.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0511-drm-v3d-Update-to-upstream-IRQ-code.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0512-drm-v3d-Add-missing-implicit-synchronization.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0512-drm-v3d-Rename-the-fence-signaled-from-IRQs-to-irq_f.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0513-drm-v3d-Refactor-job-management.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0513-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0514-drm-v3d-Add-missing-implicit-synchronization.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0514-drm-vc4-Make-sure-that-vblank-waits-work-without-v3d.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0515-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0515-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0516-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0516-drm-vc4-Make-sure-that-vblank-waits-work-without-v3d.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0517-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0517-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0518-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0518-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0519-drm-vc4-Increase-max-screen-size-to-4096x4096.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0519-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0520-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0520-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0521-drm-vc4-Fix-build-warning.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0521-drm-vc4-Increase-max-screen-size-to-4096x4096.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0522-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0522-drm-vc4-Select-display-to-blank-during-initialisatio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0523-drm-vc4-Fix-build-warning.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0523-drm-vc4-Remove-now-unused-structure.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0524-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0524-drm-vc4-Select-display-to-blank-during-initialisatio.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0525-drm-vc4-Remove-now-unused-structure.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0525-drm-vc4-Set-the-display-number-when-querying-the-dis.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0526-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0526-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0527-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0527-drm-vc4-Set-the-display-number-when-querying-the-dis.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0528-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0528-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0529-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0529-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0530-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0530-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0531-drm-vc4-Increase-max_width-height-to-7680.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0531-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0532-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0532-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0533-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0533-drm-vc4-Increase-max_width-height-to-7680.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0534-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0534-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0535-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0535-drm-v3d-Add-support-for-compute-shader-dispatch.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0536-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0536-drm-v3d-Clock-V3D-down-when-not-in-use.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0537-drm-v3d-Add-support-for-compute-shader-dispatch.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0537-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0538-drm-v3d-Clock-V3D-down-when-not-in-use.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0538-drm-vc4-Log-flags-in-fkms-mode-set.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0539-drm-vc4-firmware-kms-Fix-DSI-display-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0539-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0540-drm-vc4-Log-flags-in-fkms-mode-set.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0540-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0541-drm-vc4-firmware-kms-Fix-DSI-display-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0541-drm-vc4-handle-the-case-where-there-are-no-available.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0542-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0542-drm-vc4-Support-the-VEC-in-FKMS.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0543-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0543-drm-vc4-handle-the-case-where-there-are-no-available.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0544-drm-vc4-Correct-SAND-support-for-FKMS.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0544-drm-vc4-Support-the-VEC-in-FKMS.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0546-drm-vc4-Correct-SAND-support-for-FKMS.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0546-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0547-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0547-staging-vc-sm-cma-Remove-obsolete-comment-and-make-f.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0548-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0548-staging-vc-sm-cma-Add-in-allocation-for-VPU-requests.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0549-staging-vc-sm-cma-Remove-obsolete-comment-and-make-f.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0549-staging-vc-sm-cma-Update-TODO.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-allocation-for-VPU-requests.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0551-staging-vc-sm-cma-Update-TODO.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0551-staging-vcsm-cma-Add-cache-control-ioctls.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0552-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0552-staging-vcsm-cma-Alter-dev-node-permissions-to-0666.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0553-staging-vcsm-cma-Add-cache-control-ioctls.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0553-staging-vcsm-cma-Drop-logging-level-on-messages-in-v.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0554-staging-vcsm-cma-Alter-dev-node-permissions-to-0666.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0554-staging-vcsm-cma-Fixup-the-alloc-code-handling-of-ke.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0555-Pulled-in-the-multi-frame-buffer-support-from-the-Pi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0555-staging-vcsm-cma-Drop-logging-level-on-messages-in-v.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0556-ARM-dts-bcm283x-Move-BCM2835-6-7-specific-to-bcm2835.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0556-staging-vcsm-cma-Fixup-the-alloc-code-handling-of-ke.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0557-ARM-dts-Add-bcm2711-rpi-4-b.dts-and-components.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0557-Pulled-in-the-multi-frame-buffer-support-from-the-Pi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0558-ARM-dts-bcm283x-Move-BCM2835-6-7-specific-to-bcm2835.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0558-overlays-Add-i2c3-6-and-uart2-5-overlays.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0559-ARM-dts-Add-bcm2711-rpi-4-b.dts-and-components.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0559-spi-devicetree-add-overlays-for-spi-3-to-6.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0560-overlays-Add-i2c3-6-and-uart2-5-overlays.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0560-overlays-Add-the-spi-gpio40-45-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0561-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0561-spi-devicetree-add-overlays-for-spi-3-to-6.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0562-2711-Add-basic-64-bit-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0562-overlays-Add-the-spi-gpio40-45-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0563-ARM-dts-bcm283x-Correct-vchiq-compatible-string-2840.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0563-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0564-2711-Add-basic-64-bit-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0564-arm-dts-Change-downstream-vchiq-compatible-string.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0565-ARM-dts-bcm283x-Correct-vchiq-compatible-string-2840.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0565-bcm2835-dma-Add-proper-40-bit-DMA-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0566-BCM270X_DT-Leave-bulk-channel-in-dma-channel-mask.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0566-arm-dts-Change-downstream-vchiq-compatible-string.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0567-SQUASH-bcm2835-dma-Remove-debugging.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0567-bcm2835-dma-Add-proper-40-bit-DMA-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0568-BCM270X_DT-Leave-bulk-channel-in-dma-channel-mask.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0568-dts-Include-CSI-lane-config-for-csi1.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0569-SQUASH-bcm2835-dma-Remove-debugging.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0569-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0570-bcm2711-dts-Disable-the-v3d-node-by-default.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0570-dts-Include-CSI-lane-config-for-csi1.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0571-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0571-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0572-bcm2711-dts-Disable-the-v3d-node-by-default.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0572-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0573-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0573-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0574-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0574-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0575-drm-vc4-Add-status-of-which-display-is-updated-throu.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0575-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0576-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0576-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0577-arm-dts-Fix-Pi4-PWR-LED-configuration.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0577-drm-vc4-Add-status-of-which-display-is-updated-throu.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0578-bcm2838.dtsi-Correct-gic400-memory-address-ranges.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0578-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0579-arm-dts-Fix-Pi4-PWR-LED-configuration.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0579-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0580-bcm2838.dtsi-Correct-gic400-memory-address-ranges.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0580-drm-vc4-Limit-fkms-to-modes-85Hz.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0581-arm-bcm2835-Add-bcm2838-compatible-string.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0581-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0582-arm-dts-Improve-the-bcm27xx-inclusion-hierarchy.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0582-drm-vc4-Limit-fkms-to-modes-85Hz.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0583-arm-bcm2835-Add-bcm2838-compatible-string.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0583-arm-dts-First-draft-of-upstream-Pi4-DTS.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0584-arm-dts-Improve-the-bcm27xx-inclusion-hierarchy.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0584-overlays-Fix-compatible-string-for-ds1307-RTC.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0585-arm-dts-First-draft-of-upstream-Pi4-DTS.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0585-overlays-Fix-further-maxim-ds1307-references.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0586-overlays-Cosmetic-change-to-upstream-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0586-overlays-Fix-compatible-string-for-ds1307-RTC.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0587-overlays-Fix-further-maxim-ds1307-references.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0587-w1-ds2805-rename-w1_family-struct-fixing-c-p-typo.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0588-overlays-Cosmetic-change-to-upstream-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0588-w1-ds2413-output_write-cosmetic-fixes-simplify.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0589-w1-ds2413-add-retry-support-to-state_read.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0589-w1-ds2805-rename-w1_family-struct-fixing-c-p-typo.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0590-w1-ds2413-output_write-cosmetic-fixes-simplify.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0590-w1-ds2413-when-the-slave-is-not-responding-during-re.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0591-w1-ds2413-add-retry-support-to-state_read.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0591-w1-ds2413-fix-state-byte-comparision.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0592-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0592-w1-ds2413-when-the-slave-is-not-responding-during-re.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0593-video-bcm2708_fb-Revert-cma-allocation-attempt.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0593-w1-ds2413-fix-state-byte-comparision.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0594-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0594-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0595-arm-dts-Add-coherent_pool-1M-to-Pi-4-bootargs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0595-video-bcm2708_fb-Revert-cma-allocation-attempt.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0596-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0596-overlays-Correct-gpio-fan-gpio-flags-for-4.19.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0597-arm-dts-Add-coherent_pool-1M-to-Pi-4-bootargs.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0597-staging-vcsm-cma-Remove-cache-manipulation-ioctl-fro.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0598-overlays-Correct-gpio-fan-gpio-flags-for-4.19.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0598-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0599-staging-vc-sm-cma-Fix-the-few-remaining-coding-style.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0599-staging-vcsm-cma-Remove-cache-manipulation-ioctl-fro.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0600-media-videodev2.h-add-new-capabilities-for-buffer-ty.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0600-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0601-media-vb2-set-reqbufs-create_bufs-capabilities.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0601-staging-vc-sm-cma-Fix-the-few-remaining-coding-style.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0602-media-vb2-Allow-reqbufs-0-with-in-use-MMAP-buffers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0602-media-videodev2.h-add-new-capabilities-for-buffer-ty.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0603-media-vb2-set-reqbufs-create_bufs-capabilities.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0603-overlays-Add-real-parameters-to-the-rpi-poe-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0604-media-vb2-Allow-reqbufs-0-with-in-use-MMAP-buffers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0604-overlays-Rename-pi3-overlays-to-be-less-model-specif.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0605-i2c-bcm2835-Move-IRQ-request-after-clock-code-in-pro.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0605-overlays-Add-real-parameters-to-the-rpi-poe-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0606-i2c-bcm2835-Ensure-clock-exists-when-probing.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0606-overlays-Rename-pi3-overlays-to-be-less-model-specif.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0607-i2c-bcm2835-Move-IRQ-request-after-clock-code-in-pro.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0607-overlays-i2c-gpio-Fix-the-bus-parameter.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0608-i2c-bcm2835-Ensure-clock-exists-when-probing.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0608-tty-amba-pl011-Make-TX-optimisation-conditional.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0609-overlays-i2c-gpio-Fix-the-bus-parameter.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0609-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0610-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0610-tty-amba-pl011-Make-TX-optimisation-conditional.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0611-arm64-bcm2835-Add-missing-dependency-on-MFD_CORE.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0611-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0612-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0612-overlays-Add-PCF2129-RTC.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0613-arm64-bcm2835-Add-missing-dependency-on-MFD_CORE.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0613-overlays-dpi18-and-dpi24-vc4-compatibility.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0614-overlays-Add-PCF2129-RTC.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0614-overlays-Add-i2c0-and-i2c1-for-regularity.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0615-Pisound-Remove-spinlock-usage-around-spi_sync.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0615-overlays-dpi18-and-dpi24-vc4-compatibility.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0616-arm64-mm-Limit-the-DMA-zone-for-arm64.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0616-overlays-Add-i2c0-and-i2c1-for-regularity.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0617-Pisound-Remove-spinlock-usage-around-spi_sync.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0617-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0618-arm64-mm-Limit-the-DMA-zone-for-arm64.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0618-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0619-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0619-overlays-audremap-Support-GPIOs-18-19.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0620-drm-connector-Fix-drm_mode_create_tv_properties-doc.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0620-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0621-drm-connector-Clarify-the-unit-of-TV-margins.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0621-overlays-audremap-Support-GPIOs-18-19.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0622-drm-connector-Allow-creation-of-margin-props-alone.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0622-drm-connector-Fix-drm_mode_create_tv_properties-doc.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0623-drm-connector-Clarify-the-unit-of-TV-margins.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0623-drm-vc4-Take-margin-setup-into-account-when-updating.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0624-drm-connector-Allow-creation-of-margin-props-alone.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0624-drm-vc4-Attach-margin-props-to-the-HDMI-connector.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0625-drm-vc4-Add-support-for-margins-to-fkms.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0625-drm-vc4-Take-margin-setup-into-account-when-updating.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0626-drm-vc4-Attach-margin-props-to-the-HDMI-connector.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0626-drm-vc4-Ensure-zpos-is-always-initialised.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0627-drm-vc4-Add-support-for-margins-to-fkms.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0627-dts-bcm2838-add-missing-properties-for-pmu-and-gic-n.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0628-adds-the-Hifiberry-DAC-ADC-PRO-version.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0628-drm-vc4-Ensure-zpos-is-always-initialised.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0629-codecs-Correct-Katana-minimum-volume.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0629-dts-bcm2838-add-missing-properties-for-pmu-and-gic-n.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0630-adds-the-Hifiberry-DAC-ADC-PRO-version.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0630-drm-vc4-A-present-but-empty-dmas-disables-audio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0631-codecs-Correct-Katana-minimum-volume.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0631-overlays-Add-audio-parameter-to-vc4-kms-v3d.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0632-drm-vc4-A-present-but-empty-dmas-disables-audio.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0632-overlays-Update-the-upstream-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0633-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0633-overlays-Add-audio-parameter-to-vc4-kms-v3d.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0634-drivers-char-Use-correct-name-for-the-Raspberry-Pi-v.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0634-overlays-Update-the-upstream-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0635-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0635-driver-char-rpivid-also-support-legacy-name.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0636-drivers-char-Use-correct-name-for-the-Raspberry-Pi-v.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0636-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0637-driver-char-rpivid-also-support-legacy-name.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0637-drm-vc4-Add-Broadcast-RGB-connector-property.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0638-drm-connector-Add-documentation-for-drm_cmdline_mode.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0638-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0639-drm-modes-Rewrite-the-command-line-parser.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0639-drm-vc4-Add-Broadcast-RGB-connector-property.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0640-drm-connector-Add-documentation-for-drm_cmdline_mode.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0640-drm-modes-Support-modes-names-on-the-command-line.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0641-drm-modes-Allow-to-specify-rotation-and-reflection-o.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0641-drm-modes-Rewrite-the-command-line-parser.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0642-drm-connector-Introduce-a-TV-margins-structure.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0642-drm-modes-Support-modes-names-on-the-command-line.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0643-drm-modes-Allow-to-specify-rotation-and-reflection-o.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0643-drm-modes-Parse-overscan-properties.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0644-drm-atomic-Add-a-function-to-reset-connector-TV-prop.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0644-drm-connector-Introduce-a-TV-margins-structure.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0645-drm-modes-Parse-overscan-properties.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0645-drm-vc4-hdmi-Set-default-state-margin-at-reset.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0646-drm-atomic-Add-a-function-to-reset-connector-TV-prop.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0646-drm-vc4-fkms-Set-default-state-margin-at-reset.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0647-drm-modes-Don-t-apply-cmdline-s-rotation-if-it-wasn-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0647-drm-vc4-hdmi-Set-default-state-margin-at-reset.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0648-drm-vc4-fkms-Set-default-state-margin-at-reset.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0649-drm-modes-Don-t-apply-cmdline-s-rotation-if-it-wasn-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0649-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0650-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0650-staging-bcm2835-codec-switch-to-multi-planar-API.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0651-Add-HDMI1-facility-to-the-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0651-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0652-overlays-Add-baudrate-parameter-to-i2c3-i2c6.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0652-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0653-Add-HDMI1-facility-to-the-driver.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0653-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0654-drm-vc4-Remove-unused-mode-variable.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0654-overlays-Add-baudrate-parameter-to-i2c3-i2c6.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0655-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0655-staging-bcm2835-codec-Expand-logging-on-format-setti.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0656-drm-vc4-Remove-unused-mode-variable.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0656-staging-bcm2835-codec-Correct-bytesperline-on-format.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0657-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0657-staging-bcm2835-codec-Expand-logging-on-format-setti.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0658-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0658-staging-bcm2835-codec-Correct-bytesperline-on-format.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0659-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0659-drm-vc4-Fix-TILE_Y_OFFSET-definitions.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0660-drm-vc4-Define-missing-PITCH0_SINK_PIX-field.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0660-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0661-drm-vc4-Fix-TILE_Y_OFFSET-definitions.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0661-drm-vc4-Use-drm_atomic_helper_check_plane_state-to-s.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0662-drm-vc4-Define-missing-PITCH0_SINK_PIX-field.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0662-drm-vc4-Move-offsets-adjustment-out-of-setup_clippin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0663-drm-vc4-Fix-X-Y-positioning-of-planes-using-T_TILES-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0663-drm-vc4-Use-drm_atomic_helper_check_plane_state-to-s.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0664-drm-vc4-Fix-NULL-pointer-dereference-in-the-async-up.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0664-drm-vc4-Move-offsets-adjustment-out-of-setup_clippin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0665-ARM-dts-bcm2711-rpi-4-b-I2C-aliases-and-pulls.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0665-drm-vc4-Fix-X-Y-positioning-of-planes-using-T_TILES-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0666-drm-vc4-Fix-NULL-pointer-dereference-in-the-async-up.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0666-xhci-Use-more-event-ring-segment-table-entries.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0667-ARM-dts-bcm2711-rpi-4-b-I2C-aliases-and-pulls.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0667-dwc_otg-use-align_buf-for-small-IN-control-transfers.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0668-Ported-pcie-brcmstb-bounce-buffer-implementation-to-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0668-xhci-Use-more-event-ring-segment-table-entries.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0669-configs-arm64-vcm2711-Enable-V3D.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0669-dwc_otg-use-align_buf-for-small-IN-control-transfers.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0670-Ported-pcie-brcmstb-bounce-buffer-implementation-to-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0670-overlays-sc16ic752-i2c-Fix-xtal-parameter.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0671-configs-arm64-vcm2711-Enable-V3D.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0671-vc-sm-cma-Fix-compatibility-ioctl.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0672-overlays-sc16ic752-i2c-Fix-xtal-parameter.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0672-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0673-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0673-vc-sm-cma-Fix-compatibility-ioctl.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0674-arm-dts-add-missing-Raspberry-Pi-model-names.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0674-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0675-arch-arm-Add-model-string-to-cpuinfo.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0675-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0676-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0676-arm-dts-add-missing-Raspberry-Pi-model-names.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0677-arch-arm-Add-model-string-to-cpuinfo.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0677-media-dt-bindings-Add-binding-for-the-Sony-IMX219-se.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0678-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0678-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0679-dtoverlays-Add-overlay-for-the-Sony-IMX219-image-sen.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0679-media-dt-bindings-Add-binding-for-the-Sony-IMX219-se.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0680-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0680-staging-bcm2835-codec-Fix-non-documentation-comment-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0681-dtoverlays-Add-overlay-for-the-Sony-IMX219-image-sen.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0681-staging-bcm2835-codec-Fix-declaration-of-roles.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0682-staging-bcm2835-codec-Add-role-to-device-name.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0682-staging-bcm2835-codec-Fix-non-documentation-comment-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0683-staging-bcm2835-codec-Fix-declaration-of-roles.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0683-staging-bcm2835-codec-Pass-driver-context-to-create-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0684-staging-bcm2835-codec-Add-role-to-device-name.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0684-staging-bcm2835-codec-add-media-controller-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0685-media-bcm2835-unicam-Reduce-scope-of-local-function.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0685-staging-bcm2835-codec-Pass-driver-context-to-create-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0686-media-bcm2835-unicam-add-media-controller-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0686-staging-bcm2835-codec-add-media-controller-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0687-Limit-max_req_size-under-arm64-or-any-other-platform.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0687-media-bcm2835-unicam-Reduce-scope-of-local-function.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0688-Add-missing-dma_unmap_sg-calls-to-free-relevant-swio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0688-media-bcm2835-unicam-add-media-controller-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0689-Limit-max_req_size-under-arm64-or-any-other-platform.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0689-overlays-mcp23017-rename-the-GPIO-pins-node-with-the.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0690-Add-missing-dma_unmap_sg-calls-to-free-relevant-swio.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0690-overlays-mcp23017-Add-option-for-not-connecting-the-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0691-overlays-mcp23017-rename-the-GPIO-pins-node-with-the.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0691-v4l2-Add-a-Greyworld-AWB-mode.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0692-overlays-mcp23017-Add-option-for-not-connecting-the-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0692-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0693-PCI-brcmstb-Fix-compilation-warning.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0693-v4l2-Add-a-Greyworld-AWB-mode.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0694-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0694-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0695-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0695-PCI-brcmstb-Fix-compilation-warning.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0696-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0696-staging-bcm2835-codec-Allow-height-of-1920.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0697-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0697-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0698-regulator-gpio-Allow-nonexclusive-GPIO-access.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0698-staging-bcm2835-codec-Allow-height-of-1920.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0699-gpio-Enable-nonexclusive-gpiods-from-DT-nodes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0699-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0700-Fix-poll-rate-on-touchscreen-3238.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0700-regulator-gpio-Allow-nonexclusive-GPIO-access.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0701-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0701-gpio-Enable-nonexclusive-gpiods-from-DT-nodes.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0702-Fix-poll-rate-on-touchscreen-3238.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0702-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0703-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0703-staging-bcm2835-audio-Fix-draining-behavior-regressi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0704-bcm2708_fb-Fix-layout-of-struct-vc4_display_settings.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0704-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0705-ARM-dts-bcm283x-Fix-DTC-warning-for-memory-node.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0705-staging-bcm2835-audio-Fix-draining-behavior-regressi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0706-ARM-dts-bcm27xx-Fix-DTC-warning-for-memory-node.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0706-bcm2708_fb-Fix-layout-of-struct-vc4_display_settings.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0707-ARM-bcm283x-Enable-DMA-support-for-SPI-controller.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0707-ARM-dts-bcm283x-Fix-DTC-warning-for-memory-node.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0708-ARM-dts-bcm27xx-Fix-DTC-warning-for-memory-node.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0708-ARM-dts-bcm2835-rpi-Drop-unnecessary-address-cells-s.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0709-ARM-bcm283x-Enable-DMA-support-for-SPI-controller.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0709-ARM-dts-bcm2708-rpi-Define-the-downstream-MMC-interf.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0710-ARM-dts-bcm2835-rpi-Drop-unnecessary-address-cells-s.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0710-ARM-dts-bcm283x-Define-MMC-interfaces-at-board-level.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0711-ARM-dts-bcm2708-rpi-Define-the-downstream-MMC-interf.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0711-ARM-dts-bcm2835-rpi-zero-w-Fix-bus-width-of-sdhci.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0712-ARM-dts-bcm2708-rpi-Define-the-downstream-HDMI-power.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0712-ARM-dts-bcm283x-Define-MMC-interfaces-at-board-level.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0713-ARM-dts-bcm2835-rpi-zero-w-Fix-bus-width-of-sdhci.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0713-ARM-dts-bcm283x-Enable-HDMI-at-board-level.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0714-ARM-dts-bcm2708-rpi-Define-the-downstream-HDMI-power.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0714-clk-bcm2835-Introduce-SoC-specific-clock-registratio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0715-ARM-dts-bcm283x-Enable-HDMI-at-board-level.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0715-clk-bcm2835-Add-BCM2711_CLOCK_EMMC2-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0716-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0716-clk-bcm2835-Introduce-SoC-specific-clock-registratio.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0717-clk-bcm2835-Add-BCM2711_CLOCK_EMMC2-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0717-pinctrl-bcm2835-Switch-to-SPDX-identifier.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0718-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0718-pinctrl-bcm2835-declare-pin-config-as-generic.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0719-pinctrl-bcm2835-Direct-GPIO-config-changes-to-generi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0719-pinctrl-bcm2835-Switch-to-SPDX-identifier.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0720-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0720-pinctrl-bcm2835-declare-pin-config-as-generic.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0721-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0721-pinctrl-bcm2835-Direct-GPIO-config-changes-to-generi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0722-pcie-brcmstb-bounce64.c-dev_err-dev_info-for-info-me.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0722-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0723-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0723-overlays-gpio-shutdown-Add-debounce-parameter.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0724-overlays-fix-compatible-for-RPi4.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0724-pcie-brcmstb-bounce64.c-dev_err-dev_info-for-info-me.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0725-bcm2711-Retain-support-for-old-dtbs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0725-overlays-gpio-shutdown-Add-debounce-parameter.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0726-media-bcm2835-unicam-Add-support-for-raw14-formats.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0726-overlays-fix-compatible-for-RPi4.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0727-bcm2711-Retain-support-for-old-dtbs.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0727-media-bcm2835-unicam-Rework-to-not-cache-the-list-of.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0728-media-bcm2835-unicam-Add-support-for-raw14-formats.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0728-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0729-media-bcm2835-unicam-Add-support-for-luma-greyscale-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0729-media-bcm2835-unicam-Rework-to-not-cache-the-list-of.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0730-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0730-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0731-drm-vc4-Fix-negative-X-Y-positioning-on-SAND-planes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0731-media-bcm2835-unicam-Add-support-for-luma-greyscale-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0732-drm-vc4-Add-support-for-H-V-flips.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0732-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0733-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0733-drm-vc4-Fix-negative-X-Y-positioning-on-SAND-planes.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0734-drm-vc4-Add-support-for-H-V-flips.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0734-overlays-Add-w5500-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0735-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0735-media-bcm2835-unicam-Replace-hard-coded-loop-limit-w.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0736-media-bcm2835-unicam-Fix-one-to-many-mapping-for-YUY.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0736-overlays-Add-w5500-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0737-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0737-media-bcm2835-unicam-Replace-hard-coded-loop-limit-w.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0738-media-bcm2835-unicam-Fix-one-to-many-mapping-for-YUY.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0738-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0739-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0739-dtoverlays-Add-an-overlay-for-the-Infineon-IRS1125.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0740-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0740-rpi-wm8804-soundcard-Fixed-MCLKDIV-for-Allo-Digione.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0741-dtoverlays-Add-an-overlay-for-the-Infineon-IRS1125.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0741-dts-bcm2838-Disable-DWC-OTG-block-by-default.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0742-rpi-wm8804-soundcard-Fixed-MCLKDIV-for-Allo-Digione.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0742-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0743-dts-bcm2838-Disable-DWC-OTG-block-by-default.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0743-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0744-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0744-staging-bcm2835-codec-Set-default-and-error-check-ti.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0745-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0745-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0746-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0746-staging-bcm2835-codec-Set-default-and-error-check-ti.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0747-rpi-poe-fan-fix-def_pwm1-writes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0747-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0748-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0748-net-phy-bcm54xx-Encode-link-speed-and-activity-into-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0749-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0749-rpi-poe-fan-fix-def_pwm1-writes.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0750-net-phy-bcm54xx-Encode-link-speed-and-activity-into-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0750-overlays-smi-fix-typo-in-comment-3320.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0751-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0751-net-phy-2711-Change-the-default-ethernet-LED-actions.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0752-overlays-README-Remove-trailing-whitespace.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0752-overlays-smi-fix-typo-in-comment-3320.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0753-net-phy-2711-Change-the-default-ethernet-LED-actions.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0753-overlays-Add-apds9960-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0754-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0754-overlays-README-Remove-trailing-whitespace.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0755-clk-bcm2835-Avoid-null-pointer-exception.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0755-overlays-Add-apds9960-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0756-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0756-v3d_drv-Handle-missing-clock-more-gracefully.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0757-clk-bcm2835-Avoid-null-pointer-exception.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0758-clk-bcm283x-add-driver-interfacing-with-Raspberry-Pi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0758-v3d_drv-Handle-missing-clock-more-gracefully.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0759-cpufreq-add-driver-for-Raspberry-Pi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0759-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0760-clk-bcm283x-add-driver-interfacing-with-Raspberry-Pi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0760-firmware-raspberrypi-register-clk-device.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0761-clk-raspberrypi-register-platform-device-for-raspber.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0761-cpufreq-add-driver-for-Raspberry-Pi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0762-clk-bcm2835-remove-pllb.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0762-firmware-raspberrypi-register-clk-device.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0763-clk-raspberrypi-register-platform-device-for-raspber.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0763-v3d_drv-Allow-clock-retrieval-by-name.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0764-clk-bcm2835-remove-pllb.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0764-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0765-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0765-v3d_drv-Allow-clock-retrieval-by-name.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0766-clk-raspberrypi-Also-support-v3d-clock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0766-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0767-clk-bcm2835-Disable-v3d-clock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0767-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0768-clk-raspberrypi-Also-support-v3d-clock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0768-fixup-clk-raspberrypi-Also-support-v3d-clock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0769-clk-bcm2835-Disable-v3d-clock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0769-fixup-clk-raspberrypi-Also-support-v3d-clock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0770-fixup-clk-raspberrypi-Also-support-v3d-clock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0770-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0771-fixup-clk-raspberrypi-Also-support-v3d-clock.patch
target/linux/brcm2708/patches-4.19/950-0772-arm-dts-Correct-Pi-4B-LED-values.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0772-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0773-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0773-fixup-clk-raspberrypi-Also-support-v3d-clock.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0774-arm-dts-2711-Add-pcie0-alias.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0774-arm-dts-Correct-Pi-4B-LED-values.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0775-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0775-spidev-Completely-disable-the-DT-warning.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0776-arm-dts-2711-Add-pcie0-alias.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0776-drm-vc4-Disable-V3D-interactions-if-the-v3d-componen.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0777-sound-soc-only-first-codec-is-master-in-multicodec-s.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0777-spidev-Completely-disable-the-DT-warning.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0778-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0778-drm-vc4-Disable-V3D-interactions-if-the-v3d-componen.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0779-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0779-sound-soc-only-first-codec-is-master-in-multicodec-s.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0780-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0780-overlays-Make-mcp342x-run-time-compatible.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0781-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0781-overlays-dht11-Allow-multiple-instantiation.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0782-overlays-Make-mcp342x-run-time-compatible.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0782-overlays-i2c-rtc-Add-pcf85363-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0783-overlays-dht11-Allow-multiple-instantiation.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0783-pinctrl-bcm2835-Remove-gpiochip-on-error.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0784-overlays-i2c-rtc-Add-pcf85363-support.patch [deleted file]
target/linux/brcm2708/patches-4.19/950-0784-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0785-Pisound-MIDI-communication-fixes-for-scaled-down-CPU.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0786-leds-pca963x-Fix-open-drain-initialization.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0787-add-BME680-to-i2c-sensor-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0788-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0789-dwc_otg-fiq_fsm-pause-when-cancelling-split-transact.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0790-dwc_otg-fiq_fsm-add-a-barrier-on-entry-into-FIQ-hand.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0791-Add-universal-device-tree-overlay-for-SPI-devices.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0792-sound-Add-the-HiFiBerry-DAC-HD-version.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0793-Initialise-rpi-firmware-before-clk-bcm2835.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0794-Fix-master-mode-settings-of-HiFiBerry-DAC-ADC-PRO-ca.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0795-overlays-Use-preferred-compatible-strings.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0796-tty-amba-pl011-Add-un-throttle-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0797-Fix-i2c-pwm-pca9685a-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0798-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-PRO-sound-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0799-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-sound-card.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0800-adds-LED-OFF-feature-to-HiFiBerry-DAC-DAC-PRO-sound-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0801-pisound-Added-reading-Pisound-board-hardware-revisio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0802-mmc-sdhci-iproc-Fix-vmmc-regulators-on-iProc.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0803-ARM-dts-Declare-RPi-4B-SD-card-power-regulator.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0804-pcie-brcmstb-Bounce-buffer-support-is-for-BCM2711B0.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0805-bcm2838.dtsi-Use-BCM2711-PCIe-compatible-string.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0806-ARM-dts-Remove-bcm2838-rpi-4-b.dts.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0807-tty-amba-pl011-Avoid-rare-write-when-full-error.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0808-usb-xhci-Raspberry-Pi-FW-loader-for-VIA-VL805.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0809-overlays-Correct-the-eth_led-colour-assignments.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0810-overlays-Remove-hack-from-uart0-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0811-ARM-dts-Add-sd_poll_once-dtparam-to-bcm283x-2711.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0812-overlays-Add-ssd1306-spi-overlay-3440.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0813-overlays-Add-sh1106-spi-and-ssd1351-spi-overlays-344.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0814-overlays-dwc2-Increase-RX-FIFO-size.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0815-overlays-Fix-mcp23017-s-addr-parameter.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0816-overlays-fix-sh1106-spi-ssd1306-spi-and-ssd1351-spi-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.19/950-0817-Fix-a-sh1106-spi-ssd1306-spi-ssd1351-spi-overlays.patch [new file with mode: 0644]

index 16764d369df792ed26c1f9a2ad8463644e6d31df..b7da77b854f0ef5a3714a1e6e381d708547445da 100644 (file)
@@ -532,6 +532,33 @@ endef
 $(eval $(call KernelPackage,sound-soc-hifiberry-dacplusdsp))
 
 
+define KernelPackage/sound-soc-hifiberry-dacplushd
+  TITLE:=Support for HifiBerry DAC+HD
+  KCONFIG:= \
+    CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD \
+    CONFIG_SND_SOC_PCM179X \
+    CONFIG_SND_SOC_PCM179X_I2C
+  FILES:= \
+    $(LINUX_DIR)/drivers/clk/clk-hifiberry-dachd.ko \
+    $(LINUX_DIR)/sound/soc/bcm/snd-soc-hifiberry-dacplushd.ko \
+    $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm179x-codec.ko \
+    $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm179x-i2c.ko
+  AUTOLOAD:=$(call AutoLoad,68,clk-hifiberry-dachd snd-soc-pcm179x-codec \
+    snd-soc-pcm179x-i2c snd-soc-hifiberry-dacplushd)
+  DEPENDS:= \
+    kmod-sound-soc-bcm2835-i2s \
+    +kmod-i2c-bcm2835 \
+    +kmod-regmap-i2c
+  $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-soc-hifiberry-dacplushd/description
+  This package contains support for HifiBerry DAC+HD
+endef
+
+$(eval $(call KernelPackage,sound-soc-hifiberry-dacplushd))
+
+
 define KernelPackage/sound-soc-hifiberry-dacplusadc-pro
   TITLE:=Support for HifiBerry DAC+ADC PRO
   KCONFIG:= \
@@ -704,6 +731,32 @@ endef
 $(eval $(call KernelPackage,sound-soc-i-sabe-q2m))
 
 
+define KernelPackage/sound-soc-justboom-both
+  TITLE:=Support for JustBoom DAC and Digi
+  KCONFIG:= \
+    CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH \
+    CONFIG_SND_SOC_PCM512x \
+    CONFIG_SND_SOC_WM8804
+  FILES:= \
+    $(LINUX_DIR)/sound/soc/bcm/snd-soc-justboom-both.ko \
+    $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm512x.ko \
+    $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8804.ko
+  AUTOLOAD:=$(call AutoLoad,68,snd-soc-pcm512x snd-soc-wm8804 \
+    snd-soc-justboom-both)
+  DEPENDS:= \
+    kmod-sound-soc-bcm2835-i2s \
+    +kmod-sound-soc-rpi-wm8804-soundcard \
+    +kmod-i2c-bcm2835
+  $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-soc-justboom-both/description
+  This package contains support for JustBoom DAC and Digi
+endef
+
+$(eval $(call KernelPackage,sound-soc-justboom-both))
+
+
 define KernelPackage/sound-soc-justboom-dac
   TITLE:=Support for JustBoom DAC
   KCONFIG:= \
diff --git a/target/linux/brcm2708/patches-4.19/950-0202-staging-bcm2835-camera-Move-module-info-to-the-end.patch b/target/linux/brcm2708/patches-4.19/950-0202-staging-bcm2835-camera-Move-module-info-to-the-end.patch
new file mode 100644 (file)
index 0000000..f97a88b
--- /dev/null
@@ -0,0 +1,38 @@
+From 3e8dfb23cfab3003ff83f4d32568ae4e38536572 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sat, 20 Oct 2018 19:31:00 +0200
+Subject: [PATCH] staging: bcm2835-camera: Move module info to the end
+
+In order to have this more consistent between the vc04 services move
+the module information to the end of the file.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ .../vc04_services/bcm2835-camera/bcm2835-camera.c    | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -43,12 +43,6 @@
+ #define MAX_BCM2835_CAMERAS 2
+-MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
+-MODULE_AUTHOR("Vincent Sanders");
+-MODULE_LICENSE("GPL");
+-MODULE_VERSION(BM2835_MMAL_VERSION);
+-MODULE_ALIAS("platform:bcm2835-camera");
+-
+ int bcm2835_v4l2_debug;
+ module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
+ MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");
+@@ -1989,3 +1983,9 @@ static struct platform_driver bcm2835_ca
+ };
+ module_platform_driver(bcm2835_camera_driver)
++
++MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
++MODULE_AUTHOR("Vincent Sanders");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(BM2835_MMAL_VERSION);
++MODULE_ALIAS("platform:bcm2835-camera");
diff --git a/target/linux/brcm2708/patches-4.19/950-0203-staging-bcm2835-camera-Move-module-info-to-the-end.patch b/target/linux/brcm2708/patches-4.19/950-0203-staging-bcm2835-camera-Move-module-info-to-the-end.patch
deleted file mode 100644 (file)
index f97a88b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 3e8dfb23cfab3003ff83f4d32568ae4e38536572 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sat, 20 Oct 2018 19:31:00 +0200
-Subject: [PATCH] staging: bcm2835-camera: Move module info to the end
-
-In order to have this more consistent between the vc04 services move
-the module information to the end of the file.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- .../vc04_services/bcm2835-camera/bcm2835-camera.c    | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -43,12 +43,6 @@
- #define MAX_BCM2835_CAMERAS 2
--MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
--MODULE_AUTHOR("Vincent Sanders");
--MODULE_LICENSE("GPL");
--MODULE_VERSION(BM2835_MMAL_VERSION);
--MODULE_ALIAS("platform:bcm2835-camera");
--
- int bcm2835_v4l2_debug;
- module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
- MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");
-@@ -1989,3 +1983,9 @@ static struct platform_driver bcm2835_ca
- };
- module_platform_driver(bcm2835_camera_driver)
-+
-+MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
-+MODULE_AUTHOR("Vincent Sanders");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(BM2835_MMAL_VERSION);
-+MODULE_ALIAS("platform:bcm2835-camera");
diff --git a/target/linux/brcm2708/patches-4.19/950-0203-staging-vchiq_arm-Fix-platform-device-unregistration.patch b/target/linux/brcm2708/patches-4.19/950-0203-staging-vchiq_arm-Fix-platform-device-unregistration.patch
new file mode 100644 (file)
index 0000000..b32699d
--- /dev/null
@@ -0,0 +1,27 @@
+From 1ada615db1b97faec9c4625ccfd2cc35d54d850a Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sat, 13 Oct 2018 20:51:23 +0200
+Subject: [PATCH] staging: vchiq_arm: Fix platform device
+ unregistration
+
+In error case platform_device_register_data would return an ERR_PTR
+instead of NULL. So we better check this before unregistration.
+
+Fixes: 37b7b3087a2f ("staging/vc04_services: Register a platform device for the camera driver.")
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3656,7 +3656,8 @@ failed_platform_init:
+ static int vchiq_remove(struct platform_device *pdev)
+ {
+-      platform_device_unregister(bcm2835_camera);
++      if (!IS_ERR(bcm2835_camera))
++              platform_device_unregister(bcm2835_camera);
+       vchiq_debugfs_deinit();
+       device_destroy(vchiq_class, vchiq_devid);
+       class_destroy(vchiq_class);
diff --git a/target/linux/brcm2708/patches-4.19/950-0204-staging-vchiq_arm-Fix-camera-device-registration.patch b/target/linux/brcm2708/patches-4.19/950-0204-staging-vchiq_arm-Fix-camera-device-registration.patch
new file mode 100644 (file)
index 0000000..9cf02e9
--- /dev/null
@@ -0,0 +1,56 @@
+From 58ed78a70c3c3ef1ae99aefdd2c28ac81f66df85 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Mon, 22 Oct 2018 15:16:51 +0200
+Subject: [PATCH] staging: vchiq_arm: Fix camera device registration
+
+Since the camera driver isn't probed via DT, we need to properly setup DMA.
+
+Fixes: 37b7b3087a2f ("staging/vc04_services: Register a platform device for the camera driver.")
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ .../interface/vchiq_arm/vchiq_arm.c           | 20 ++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -49,6 +49,7 @@
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/compat.h>
++#include <linux/dma-mapping.h>
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+ #include "vchiq_core.h"
+@@ -3578,6 +3579,21 @@ void vchiq_platform_conn_state_changed(V
+       }
+ }
++static struct platform_device *
++vchiq_register_child(struct platform_device *pdev, const char *name)
++{
++      struct platform_device_info pdevinfo;
++
++      memset(&pdevinfo, 0, sizeof(pdevinfo));
++
++      pdevinfo.parent = &pdev->dev;
++      pdevinfo.name = name;
++      pdevinfo.id = PLATFORM_DEVID_NONE;
++      pdevinfo.dma_mask = DMA_BIT_MASK(32);
++
++      return platform_device_register_full(&pdevinfo);
++}
++
+ static int vchiq_probe(struct platform_device *pdev)
+ {
+       struct device_node *fw_node;
+@@ -3637,9 +3653,7 @@ static int vchiq_probe(struct platform_d
+               VCHIQ_VERSION, VCHIQ_VERSION_MIN,
+               MAJOR(vchiq_devid), MINOR(vchiq_devid));
+-      bcm2835_camera = platform_device_register_data(&pdev->dev,
+-                                                     "bcm2835-camera", -1,
+-                                                     NULL, 0);
++      bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0204-staging-vchiq_arm-Fix-platform-device-unregistration.patch b/target/linux/brcm2708/patches-4.19/950-0204-staging-vchiq_arm-Fix-platform-device-unregistration.patch
deleted file mode 100644 (file)
index b32699d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 1ada615db1b97faec9c4625ccfd2cc35d54d850a Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sat, 13 Oct 2018 20:51:23 +0200
-Subject: [PATCH] staging: vchiq_arm: Fix platform device
- unregistration
-
-In error case platform_device_register_data would return an ERR_PTR
-instead of NULL. So we better check this before unregistration.
-
-Fixes: 37b7b3087a2f ("staging/vc04_services: Register a platform device for the camera driver.")
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -3656,7 +3656,8 @@ failed_platform_init:
- static int vchiq_remove(struct platform_device *pdev)
- {
--      platform_device_unregister(bcm2835_camera);
-+      if (!IS_ERR(bcm2835_camera))
-+              platform_device_unregister(bcm2835_camera);
-       vchiq_debugfs_deinit();
-       device_destroy(vchiq_class, vchiq_devid);
-       class_destroy(vchiq_class);
diff --git a/target/linux/brcm2708/patches-4.19/950-0205-staging-bcm2835-camera-Provide-more-specific-probe-e.patch b/target/linux/brcm2708/patches-4.19/950-0205-staging-bcm2835-camera-Provide-more-specific-probe-e.patch
new file mode 100644 (file)
index 0000000..e7566d1
--- /dev/null
@@ -0,0 +1,166 @@
+From 94a174095f29c77574548eea17aacaed5c540757 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sun, 21 Oct 2018 18:40:07 +0200
+Subject: [PATCH] staging: bcm2835-camera: Provide more specific probe
+ error messages
+
+Currently there is only a catch-all info message which print the
+relevant error code without any context. So add more specific error
+messages in order to narrow down possible issues.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 58 +++++++++++++------
+ 1 file changed, 39 insertions(+), 19 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -1552,8 +1552,11 @@ static int mmal_init(struct bm2835_mmal_
+       struct vchiq_mmal_component  *camera;
+       ret = vchiq_mmal_init(&dev->instance);
+-      if (ret < 0)
++      if (ret < 0) {
++              v4l2_err(&dev->v4l2_dev, "%s: vchiq mmal init failed %d\n",
++                       __func__, ret);
+               return ret;
++      }
+       /* get the camera component ready */
+       ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
+@@ -1562,7 +1565,9 @@ static int mmal_init(struct bm2835_mmal_
+               goto unreg_mmal;
+       camera = dev->component[MMAL_COMPONENT_CAMERA];
+-      if (camera->outputs <  MMAL_CAMERA_PORT_COUNT) {
++      if (camera->outputs < MMAL_CAMERA_PORT_COUNT) {
++              v4l2_err(&dev->v4l2_dev, "%s: too few camera outputs %d needed %d\n",
++                       __func__, camera->outputs, MMAL_CAMERA_PORT_COUNT);
+               ret = -EINVAL;
+               goto unreg_camera;
+       }
+@@ -1570,8 +1575,11 @@ static int mmal_init(struct bm2835_mmal_
+       ret = set_camera_parameters(dev->instance,
+                                   camera,
+                                   dev);
+-      if (ret < 0)
++      if (ret < 0) {
++              v4l2_err(&dev->v4l2_dev, "%s: unable to set camera parameters: %d\n",
++                       __func__, ret);
+               goto unreg_camera;
++      }
+       /* There was an error in the firmware that meant the camera component
+        * produced BGR instead of RGB.
+@@ -1660,8 +1668,8 @@ static int mmal_init(struct bm2835_mmal_
+       if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
+               ret = -EINVAL;
+-              pr_debug("too few input ports %d needed %d\n",
+-                       dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
++              v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
++                       __func__, dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
+               goto unreg_preview;
+       }
+@@ -1674,8 +1682,8 @@ static int mmal_init(struct bm2835_mmal_
+       if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
+               ret = -EINVAL;
+-              v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
+-                       dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
++              v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
++                       __func__, dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
+                        1);
+               goto unreg_image_encoder;
+       }
+@@ -1689,8 +1697,8 @@ static int mmal_init(struct bm2835_mmal_
+       if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
+               ret = -EINVAL;
+-              v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
+-                       dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
++              v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
++                       __func__, dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
+                        1);
+               goto unreg_vid_encoder;
+       }
+@@ -1719,8 +1727,11 @@ static int mmal_init(struct bm2835_mmal_
+                                             sizeof(enable));
+       }
+       ret = bm2835_mmal_set_all_camera_controls(dev);
+-      if (ret < 0)
++      if (ret < 0) {
++              v4l2_err(&dev->v4l2_dev, "%s: failed to set all camera controls: %d\n",
++                       __func__, ret);
+               goto unreg_vid_encoder;
++      }
+       return 0;
+@@ -1886,21 +1897,29 @@ static int bcm2835_mmal_probe(struct pla
+               snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
+                        "%s", BM2835_MMAL_MODULE_NAME);
+               ret = v4l2_device_register(NULL, &dev->v4l2_dev);
+-              if (ret)
++              if (ret) {
++                      dev_err(&pdev->dev, "%s: could not register V4L2 device: %d\n",
++                              __func__, ret);
+                       goto free_dev;
++              }
+               /* setup v4l controls */
+               ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
+-              if (ret < 0)
++              if (ret < 0) {
++                      v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n",
++                              __func__, ret);
+                       goto unreg_dev;
++              }
+               dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
+               /* mmal init */
+               dev->instance = instance;
+               ret = mmal_init(dev);
+-              if (ret < 0)
++              if (ret < 0) {
++                      v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n",
++                              __func__, ret);
+                       goto unreg_dev;
+-
++              }
+               /* initialize queue */
+               q = &dev->capture.vb_vidq;
+               memset(q, 0, sizeof(*q));
+@@ -1918,16 +1937,19 @@ static int bcm2835_mmal_probe(struct pla
+               /* initialise video devices */
+               ret = bm2835_mmal_init_device(dev, &dev->vdev);
+-              if (ret < 0)
++              if (ret < 0) {
++                      v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n",
++                              __func__, ret);
+                       goto unreg_dev;
++              }
+               /* Really want to call vidioc_s_fmt_vid_cap with the default
+                * format, but currently the APIs don't join up.
+                */
+               ret = mmal_setup_components(dev, &default_v4l2_format);
+               if (ret < 0) {
+-                      v4l2_err(&dev->v4l2_dev,
+-                               "%s: could not setup components\n", __func__);
++                      v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n",
++                              __func__, ret);
+                       goto unreg_dev;
+               }
+@@ -1951,8 +1973,6 @@ cleanup_gdev:
+               bcm2835_cleanup_instance(gdev[i]);
+               gdev[i] = NULL;
+       }
+-      pr_info("%s: error %d while loading driver\n",
+-              BM2835_MMAL_MODULE_NAME, ret);
+ cleanup_mmal:
+       vchiq_mmal_finalise(instance);
diff --git a/target/linux/brcm2708/patches-4.19/950-0205-staging-vchiq_arm-Fix-camera-device-registration.patch b/target/linux/brcm2708/patches-4.19/950-0205-staging-vchiq_arm-Fix-camera-device-registration.patch
deleted file mode 100644 (file)
index 9cf02e9..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 58ed78a70c3c3ef1ae99aefdd2c28ac81f66df85 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Mon, 22 Oct 2018 15:16:51 +0200
-Subject: [PATCH] staging: vchiq_arm: Fix camera device registration
-
-Since the camera driver isn't probed via DT, we need to properly setup DMA.
-
-Fixes: 37b7b3087a2f ("staging/vc04_services: Register a platform device for the camera driver.")
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- .../interface/vchiq_arm/vchiq_arm.c           | 20 ++++++++++++++++---
- 1 file changed, 17 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -49,6 +49,7 @@
- #include <linux/of.h>
- #include <linux/platform_device.h>
- #include <linux/compat.h>
-+#include <linux/dma-mapping.h>
- #include <soc/bcm2835/raspberrypi-firmware.h>
- #include "vchiq_core.h"
-@@ -3578,6 +3579,21 @@ void vchiq_platform_conn_state_changed(V
-       }
- }
-+static struct platform_device *
-+vchiq_register_child(struct platform_device *pdev, const char *name)
-+{
-+      struct platform_device_info pdevinfo;
-+
-+      memset(&pdevinfo, 0, sizeof(pdevinfo));
-+
-+      pdevinfo.parent = &pdev->dev;
-+      pdevinfo.name = name;
-+      pdevinfo.id = PLATFORM_DEVID_NONE;
-+      pdevinfo.dma_mask = DMA_BIT_MASK(32);
-+
-+      return platform_device_register_full(&pdevinfo);
-+}
-+
- static int vchiq_probe(struct platform_device *pdev)
- {
-       struct device_node *fw_node;
-@@ -3637,9 +3653,7 @@ static int vchiq_probe(struct platform_d
-               VCHIQ_VERSION, VCHIQ_VERSION_MIN,
-               MAJOR(vchiq_devid), MINOR(vchiq_devid));
--      bcm2835_camera = platform_device_register_data(&pdev->dev,
--                                                     "bcm2835-camera", -1,
--                                                     NULL, 0);
-+      bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0206-staging-bcm2835-camera-Add-hint-about-possible-fault.patch b/target/linux/brcm2708/patches-4.19/950-0206-staging-bcm2835-camera-Add-hint-about-possible-fault.patch
new file mode 100644 (file)
index 0000000..38409de
--- /dev/null
@@ -0,0 +1,31 @@
+From 17eaf7c6e8dfcd76b4ed28587b07892e2a5a4ff5 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sun, 21 Oct 2018 19:08:29 +0200
+Subject: [PATCH] staging: bcm2835-camera: Add hint about possible
+ faulty GPU mem config
+
+As per default the GPU memory config of the Raspberry Pi isn't sufficient
+for the camera usage. Even worse the bcm2835 camera doesn't provide a
+helpful error message in this case. So let's add a hint to point the user
+to the likely cause.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -1620,8 +1620,11 @@ int vchiq_mmal_component_init(struct vch
+       component = &instance->component[instance->component_idx];
+       ret = create_component(instance, component, name);
+-      if (ret < 0)
++      if (ret < 0) {
++              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
++                     __func__, ret);
+               goto unlock;
++      }
+       /* ports info needs gathering */
+       component->control.type = MMAL_PORT_TYPE_CONTROL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0206-staging-bcm2835-camera-Provide-more-specific-probe-e.patch b/target/linux/brcm2708/patches-4.19/950-0206-staging-bcm2835-camera-Provide-more-specific-probe-e.patch
deleted file mode 100644 (file)
index e7566d1..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-From 94a174095f29c77574548eea17aacaed5c540757 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sun, 21 Oct 2018 18:40:07 +0200
-Subject: [PATCH] staging: bcm2835-camera: Provide more specific probe
- error messages
-
-Currently there is only a catch-all info message which print the
-relevant error code without any context. So add more specific error
-messages in order to narrow down possible issues.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- .../bcm2835-camera/bcm2835-camera.c           | 58 +++++++++++++------
- 1 file changed, 39 insertions(+), 19 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -1552,8 +1552,11 @@ static int mmal_init(struct bm2835_mmal_
-       struct vchiq_mmal_component  *camera;
-       ret = vchiq_mmal_init(&dev->instance);
--      if (ret < 0)
-+      if (ret < 0) {
-+              v4l2_err(&dev->v4l2_dev, "%s: vchiq mmal init failed %d\n",
-+                       __func__, ret);
-               return ret;
-+      }
-       /* get the camera component ready */
-       ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
-@@ -1562,7 +1565,9 @@ static int mmal_init(struct bm2835_mmal_
-               goto unreg_mmal;
-       camera = dev->component[MMAL_COMPONENT_CAMERA];
--      if (camera->outputs <  MMAL_CAMERA_PORT_COUNT) {
-+      if (camera->outputs < MMAL_CAMERA_PORT_COUNT) {
-+              v4l2_err(&dev->v4l2_dev, "%s: too few camera outputs %d needed %d\n",
-+                       __func__, camera->outputs, MMAL_CAMERA_PORT_COUNT);
-               ret = -EINVAL;
-               goto unreg_camera;
-       }
-@@ -1570,8 +1575,11 @@ static int mmal_init(struct bm2835_mmal_
-       ret = set_camera_parameters(dev->instance,
-                                   camera,
-                                   dev);
--      if (ret < 0)
-+      if (ret < 0) {
-+              v4l2_err(&dev->v4l2_dev, "%s: unable to set camera parameters: %d\n",
-+                       __func__, ret);
-               goto unreg_camera;
-+      }
-       /* There was an error in the firmware that meant the camera component
-        * produced BGR instead of RGB.
-@@ -1660,8 +1668,8 @@ static int mmal_init(struct bm2835_mmal_
-       if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
-               ret = -EINVAL;
--              pr_debug("too few input ports %d needed %d\n",
--                       dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
-+              v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
-+                       __func__, dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
-               goto unreg_preview;
-       }
-@@ -1674,8 +1682,8 @@ static int mmal_init(struct bm2835_mmal_
-       if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
-               ret = -EINVAL;
--              v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
--                       dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
-+              v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
-+                       __func__, dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
-                        1);
-               goto unreg_image_encoder;
-       }
-@@ -1689,8 +1697,8 @@ static int mmal_init(struct bm2835_mmal_
-       if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
-               ret = -EINVAL;
--              v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
--                       dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
-+              v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
-+                       __func__, dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
-                        1);
-               goto unreg_vid_encoder;
-       }
-@@ -1719,8 +1727,11 @@ static int mmal_init(struct bm2835_mmal_
-                                             sizeof(enable));
-       }
-       ret = bm2835_mmal_set_all_camera_controls(dev);
--      if (ret < 0)
-+      if (ret < 0) {
-+              v4l2_err(&dev->v4l2_dev, "%s: failed to set all camera controls: %d\n",
-+                       __func__, ret);
-               goto unreg_vid_encoder;
-+      }
-       return 0;
-@@ -1886,21 +1897,29 @@ static int bcm2835_mmal_probe(struct pla
-               snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
-                        "%s", BM2835_MMAL_MODULE_NAME);
-               ret = v4l2_device_register(NULL, &dev->v4l2_dev);
--              if (ret)
-+              if (ret) {
-+                      dev_err(&pdev->dev, "%s: could not register V4L2 device: %d\n",
-+                              __func__, ret);
-                       goto free_dev;
-+              }
-               /* setup v4l controls */
-               ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
--              if (ret < 0)
-+              if (ret < 0) {
-+                      v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n",
-+                              __func__, ret);
-                       goto unreg_dev;
-+              }
-               dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
-               /* mmal init */
-               dev->instance = instance;
-               ret = mmal_init(dev);
--              if (ret < 0)
-+              if (ret < 0) {
-+                      v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n",
-+                              __func__, ret);
-                       goto unreg_dev;
--
-+              }
-               /* initialize queue */
-               q = &dev->capture.vb_vidq;
-               memset(q, 0, sizeof(*q));
-@@ -1918,16 +1937,19 @@ static int bcm2835_mmal_probe(struct pla
-               /* initialise video devices */
-               ret = bm2835_mmal_init_device(dev, &dev->vdev);
--              if (ret < 0)
-+              if (ret < 0) {
-+                      v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n",
-+                              __func__, ret);
-                       goto unreg_dev;
-+              }
-               /* Really want to call vidioc_s_fmt_vid_cap with the default
-                * format, but currently the APIs don't join up.
-                */
-               ret = mmal_setup_components(dev, &default_v4l2_format);
-               if (ret < 0) {
--                      v4l2_err(&dev->v4l2_dev,
--                               "%s: could not setup components\n", __func__);
-+                      v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n",
-+                              __func__, ret);
-                       goto unreg_dev;
-               }
-@@ -1951,8 +1973,6 @@ cleanup_gdev:
-               bcm2835_cleanup_instance(gdev[i]);
-               gdev[i] = NULL;
-       }
--      pr_info("%s: error %d while loading driver\n",
--              BM2835_MMAL_MODULE_NAME, ret);
- cleanup_mmal:
-       vchiq_mmal_finalise(instance);
diff --git a/target/linux/brcm2708/patches-4.19/950-0207-staging-bcm2835-camera-Add-hint-about-possible-fault.patch b/target/linux/brcm2708/patches-4.19/950-0207-staging-bcm2835-camera-Add-hint-about-possible-fault.patch
deleted file mode 100644 (file)
index 38409de..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 17eaf7c6e8dfcd76b4ed28587b07892e2a5a4ff5 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sun, 21 Oct 2018 19:08:29 +0200
-Subject: [PATCH] staging: bcm2835-camera: Add hint about possible
- faulty GPU mem config
-
-As per default the GPU memory config of the Raspberry Pi isn't sufficient
-for the camera usage. Even worse the bcm2835 camera doesn't provide a
-helpful error message in this case. So let's add a hint to point the user
-to the likely cause.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-@@ -1620,8 +1620,11 @@ int vchiq_mmal_component_init(struct vch
-       component = &instance->component[instance->component_idx];
-       ret = create_component(instance, component, name);
--      if (ret < 0)
-+      if (ret < 0) {
-+              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
-+                     __func__, ret);
-               goto unlock;
-+      }
-       /* ports info needs gathering */
-       component->control.type = MMAL_PORT_TYPE_CONTROL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0207-staging-vchiq_arm-Improve-error-handling-on-loading-.patch b/target/linux/brcm2708/patches-4.19/950-0207-staging-vchiq_arm-Improve-error-handling-on-loading-.patch
new file mode 100644 (file)
index 0000000..087e3e5
--- /dev/null
@@ -0,0 +1,39 @@
+From 73979b06255c3b7b536a53d09ea095aec8ed37aa Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 3 Dec 2018 12:50:38 +0000
+Subject: [PATCH] staging: vchiq_arm: Improve error handling on loading
+ drivers
+
+The handling of loading platform drivers requires checking IS_ERR
+for the pointer on unload.
+If the driver fails to load, NULL the pointer during probe as
+platform_device_unregister already checks for NULL.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/interface/vchiq_arm/vchiq_arm.c    | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3654,6 +3654,8 @@ static int vchiq_probe(struct platform_d
+               MAJOR(vchiq_devid), MINOR(vchiq_devid));
+       bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
++      if (IS_ERR(bcm2835_camera))
++              bcm2835_camera = NULL;
+       return 0;
+@@ -3670,8 +3672,9 @@ failed_platform_init:
+ static int vchiq_remove(struct platform_device *pdev)
+ {
+-      if (!IS_ERR(bcm2835_camera))
+-              platform_device_unregister(bcm2835_camera);
++      platform_device_unregister(bcm2835_codec);
++      platform_device_unregister(bcm2835_camera);
++      platform_device_unregister(vcsm_cma);
+       vchiq_debugfs_deinit();
+       device_destroy(vchiq_class, vchiq_devid);
+       class_destroy(vchiq_class);
diff --git a/target/linux/brcm2708/patches-4.19/950-0208-staging-bcm2835-camera-Do-not-bulk-receive-from-serv.patch b/target/linux/brcm2708/patches-4.19/950-0208-staging-bcm2835-camera-Do-not-bulk-receive-from-serv.patch
new file mode 100644 (file)
index 0000000..9d2ae1b
--- /dev/null
@@ -0,0 +1,197 @@
+From 522f1499310d389e663a4e8dd0ccbb916b768766 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 14 Feb 2018 17:04:26 +0000
+Subject: [PATCH] staging: bcm2835-camera: Do not bulk receive from
+ service thread
+
+vchi_bulk_queue_receive will queue up to a default of 4
+bulk receives on a connection before blocking.
+If called from the VCHI service_callback thread, then
+that thread is unable to service the VCHI_CALLBACK_BULK_RECEIVED
+events that would enable the queue call to succeed.
+
+Add a workqueue to schedule the call vchi_bulk_queue_receive
+in an alternate context to avoid the lock up.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/mmal-vchiq.c | 101 ++++++++++--------
+ 1 file changed, 59 insertions(+), 42 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -118,8 +118,10 @@ struct mmal_msg_context {
+       union {
+               struct {
+-                      /* work struct for defered callback - must come first */
++                      /* work struct for buffer_cb callback */
+                       struct work_struct work;
++                      /* work struct for deferred callback */
++                      struct work_struct buffer_to_host_work;
+                       /* mmal instance */
+                       struct vchiq_mmal_instance *instance;
+                       /* mmal port */
+@@ -168,6 +170,9 @@ struct vchiq_mmal_instance {
+       /* component to use next */
+       int component_idx;
+       struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
++
++      /* ordered workqueue to process all bulk operations */
++      struct workqueue_struct *bulk_wq;
+ };
+ static struct mmal_msg_context *
+@@ -251,7 +256,44 @@ static void buffer_work_cb(struct work_s
+                                           msg_context->u.bulk.mmal_flags,
+                                           msg_context->u.bulk.dts,
+                                           msg_context->u.bulk.pts);
++}
++/* workqueue scheduled callback to handle receiving buffers
++ *
++ * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
++ * If we block in the service_callback context then we can't process the
++ * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
++ * vchi_bulk_queue_receive() call to complete.
++ */
++static void buffer_to_host_work_cb(struct work_struct *work)
++{
++      struct mmal_msg_context *msg_context =
++              container_of(work, struct mmal_msg_context,
++                           u.bulk.buffer_to_host_work);
++      struct vchiq_mmal_instance *instance = msg_context->instance;
++      unsigned long len = msg_context->u.bulk.buffer_used;
++      int ret;
++
++      if (!len)
++              /* Dummy receive to ensure the buffers remain in order */
++              len = 8;
++      /* queue the bulk submission */
++      vchi_service_use(instance->handle);
++      ret = vchi_bulk_queue_receive(instance->handle,
++                                    msg_context->u.bulk.buffer->buffer,
++                                    /* Actual receive needs to be a multiple
++                                     * of 4 bytes
++                                     */
++                                    (len + 3) & ~3,
++                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
++                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
++                                    msg_context);
++
++      vchi_service_release(instance->handle);
++
++      if (ret != 0)
++              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
++                     __func__, msg_context, ret);
+ }
+ /* enqueue a bulk receive for a given message context */
+@@ -260,7 +302,6 @@ static int bulk_receive(struct vchiq_mma
+                       struct mmal_msg_context *msg_context)
+ {
+       unsigned long rd_len;
+-      int ret;
+       rd_len = msg->u.buffer_from_host.buffer_header.length;
+@@ -294,45 +335,10 @@ static int bulk_receive(struct vchiq_mma
+       msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
+       msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
+-      /* queue the bulk submission */
+-      vchi_service_use(instance->handle);
+-      ret = vchi_bulk_queue_receive(instance->handle,
+-                                    msg_context->u.bulk.buffer->buffer,
+-                                    /* Actual receive needs to be a multiple
+-                                     * of 4 bytes
+-                                     */
+-                                    (rd_len + 3) & ~3,
+-                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
+-                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
+-                                    msg_context);
+-
+-      vchi_service_release(instance->handle);
++      queue_work(msg_context->instance->bulk_wq,
++                 &msg_context->u.bulk.buffer_to_host_work);
+-      return ret;
+-}
+-
+-/* enque a dummy bulk receive for a given message context */
+-static int dummy_bulk_receive(struct vchiq_mmal_instance *instance,
+-                            struct mmal_msg_context *msg_context)
+-{
+-      int ret;
+-
+-      /* zero length indicates this was a dummy transfer */
+-      msg_context->u.bulk.buffer_used = 0;
+-
+-      /* queue the bulk submission */
+-      vchi_service_use(instance->handle);
+-
+-      ret = vchi_bulk_queue_receive(instance->handle,
+-                                    instance->bulk_scratch,
+-                                    8,
+-                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
+-                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
+-                                    msg_context);
+-
+-      vchi_service_release(instance->handle);
+-
+-      return ret;
++      return 0;
+ }
+ /* data in message, memcpy from packet into output buffer */
+@@ -380,6 +386,8 @@ buffer_from_host(struct vchiq_mmal_insta
+       /* initialise work structure ready to schedule callback */
+       INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
++      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
++                buffer_to_host_work_cb);
+       atomic_inc(&port->buffers_with_vpu);
+@@ -465,7 +473,7 @@ static void buffer_to_host_cb(struct vch
+               if (msg->u.buffer_from_host.buffer_header.flags &
+                   MMAL_BUFFER_HEADER_FLAG_EOS) {
+                       msg_context->u.bulk.status =
+-                          dummy_bulk_receive(instance, msg_context);
++                          bulk_receive(instance, msg, msg_context);
+                       if (msg_context->u.bulk.status == 0)
+                               return; /* successful bulk submission, bulk
+                                        * completion will trigger callback
+@@ -1789,6 +1797,9 @@ int vchiq_mmal_finalise(struct vchiq_mma
+       mutex_unlock(&instance->vchiq_mutex);
++      flush_workqueue(instance->bulk_wq);
++      destroy_workqueue(instance->bulk_wq);
++
+       vfree(instance->bulk_scratch);
+       idr_destroy(&instance->context_map);
+@@ -1858,6 +1869,11 @@ int vchiq_mmal_init(struct vchiq_mmal_in
+       params.callback_param = instance;
++      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
++                                                  WQ_MEM_RECLAIM);
++      if (!instance->bulk_wq)
++              goto err_free;
++
+       status = vchi_service_open(vchi_instance, &params, &instance->handle);
+       if (status) {
+               pr_err("Failed to open VCHI service connection (status=%d)\n",
+@@ -1872,8 +1888,9 @@ int vchiq_mmal_init(struct vchiq_mmal_in
+       return 0;
+ err_close_services:
+-
+       vchi_service_close(instance->handle);
++      destroy_workqueue(instance->bulk_wq);
++err_free:
+       vfree(instance->bulk_scratch);
+       kfree(instance);
+       return -ENODEV;
diff --git a/target/linux/brcm2708/patches-4.19/950-0209-staging-bcm2835-camera-Ensure-H264-header-bytes-get-.patch b/target/linux/brcm2708/patches-4.19/950-0209-staging-bcm2835-camera-Ensure-H264-header-bytes-get-.patch
new file mode 100644 (file)
index 0000000..12afc4a
--- /dev/null
@@ -0,0 +1,87 @@
+From bf5bbfec3cb99c469eb59f2b19411146c47feb73 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 14:21:04 +0000
+Subject: [PATCH] staging: bcm2835-camera: Ensure H264 header bytes get
+ a sensible timestamp
+
+H264 header come from VC with 0 timestamps, which means they get a
+strange timestamp when processed with VC/kernel start times,
+particularly if used with the inline header option.
+Remember the last frame timestamp and use that if set, or otherwise
+use the kernel start time.
+
+https://github.com/raspberrypi/linux/issues/1836
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 30 +++++++++++++++++--
+ .../bcm2835-camera/bcm2835-camera.h           |  2 ++
+ 2 files changed, 29 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -363,8 +363,13 @@ static void buffer_cb(struct vchiq_mmal_
+               }
+       } else {
+               if (dev->capture.frame_count) {
+-                      if (dev->capture.vc_start_timestamp != -1 &&
+-                          pts != 0) {
++                      if (dev->capture.vc_start_timestamp == -1) {
++                              buf->vb.vb2_buf.timestamp = ktime_get_ns();
++                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                                       "Buffer time set as current time - %lld",
++                                       buf->vb.vb2_buf.timestamp);
++
++                      } else if (pts != 0) {
+                               ktime_t timestamp;
+                               s64 runtime_us = pts -
+                                   dev->capture.vc_start_timestamp;
+@@ -377,10 +382,28 @@ static void buffer_cb(struct vchiq_mmal_
+                                        ktime_to_ns(timestamp));
+                               buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
+                       } else {
+-                              buf->vb.vb2_buf.timestamp = ktime_get_ns();
++                              if (dev->capture.last_timestamp) {
++                                      buf->vb.vb2_buf.timestamp =
++                                              dev->capture.last_timestamp;
++                                      v4l2_dbg(1, bcm2835_v4l2_debug,
++                                               &dev->v4l2_dev,
++                                               "Buffer time set as last timestamp - %lld",
++                                               buf->vb.vb2_buf.timestamp);
++                              } else {
++                                      buf->vb.vb2_buf.timestamp =
++                                              ktime_to_ns(dev->capture.kernel_start_ts);
++                                      v4l2_dbg(1, bcm2835_v4l2_debug,
++                                               &dev->v4l2_dev,
++                                               "Buffer time set as start timestamp - %lld",
++                                               buf->vb.vb2_buf.timestamp);
++                              }
+                       }
++                      dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
+                       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
++                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                               "Buffer has ts %llu",
++                               dev->capture.last_timestamp);
+                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+                       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
+@@ -546,6 +569,7 @@ static int start_streaming(struct vb2_qu
+                        dev->capture.vc_start_timestamp, parameter_size);
+       dev->capture.kernel_start_ts = ktime_get();
++      dev->capture.last_timestamp = 0;
+       /* enable the camera port */
+       dev->capture.port->cb_ctx = dev;
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
+@@ -90,6 +90,8 @@ struct bm2835_mmal_dev {
+               s64         vc_start_timestamp;
+               /* Kernel start timestamp for streaming */
+               ktime_t kernel_start_ts;
++              /* Timestamp of last frame */
++              u64             last_timestamp;
+               struct vchiq_mmal_port  *port; /* port being used for capture */
+               /* camera port being used for capture */
diff --git a/target/linux/brcm2708/patches-4.19/950-0209-staging-vchiq_arm-Improve-error-handling-on-loading-.patch b/target/linux/brcm2708/patches-4.19/950-0209-staging-vchiq_arm-Improve-error-handling-on-loading-.patch
deleted file mode 100644 (file)
index 087e3e5..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From 73979b06255c3b7b536a53d09ea095aec8ed37aa Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 3 Dec 2018 12:50:38 +0000
-Subject: [PATCH] staging: vchiq_arm: Improve error handling on loading
- drivers
-
-The handling of loading platform drivers requires checking IS_ERR
-for the pointer on unload.
-If the driver fails to load, NULL the pointer during probe as
-platform_device_unregister already checks for NULL.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/interface/vchiq_arm/vchiq_arm.c    | 12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -3654,6 +3654,8 @@ static int vchiq_probe(struct platform_d
-               MAJOR(vchiq_devid), MINOR(vchiq_devid));
-       bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
-+      if (IS_ERR(bcm2835_camera))
-+              bcm2835_camera = NULL;
-       return 0;
-@@ -3670,8 +3672,9 @@ failed_platform_init:
- static int vchiq_remove(struct platform_device *pdev)
- {
--      if (!IS_ERR(bcm2835_camera))
--              platform_device_unregister(bcm2835_camera);
-+      platform_device_unregister(bcm2835_codec);
-+      platform_device_unregister(bcm2835_camera);
-+      platform_device_unregister(vcsm_cma);
-       vchiq_debugfs_deinit();
-       device_destroy(vchiq_class, vchiq_devid);
-       class_destroy(vchiq_class);
diff --git a/target/linux/brcm2708/patches-4.19/950-0210-staging-bcm2835-camera-Correctly-denote-key-frames-i.patch b/target/linux/brcm2708/patches-4.19/950-0210-staging-bcm2835-camera-Correctly-denote-key-frames-i.patch
new file mode 100644 (file)
index 0000000..96116cb
--- /dev/null
@@ -0,0 +1,25 @@
+From 6c70a89ac19b1ead96be68002affcd1821014d52 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 13 Feb 2017 13:11:41 +0000
+Subject: [PATCH] staging: bcm2835-camera: Correctly denote key frames
+ in encoded data
+
+Forward MMAL key frame flags to the V4L2 buffers.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -401,6 +401,9 @@ static void buffer_cb(struct vchiq_mmal_
+                       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
+                       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
++                      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
++                              buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
++
+                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                                "Buffer has ts %llu",
+                                dev->capture.last_timestamp);
diff --git a/target/linux/brcm2708/patches-4.19/950-0210-staging-bcm2835-camera-Do-not-bulk-receive-from-serv.patch b/target/linux/brcm2708/patches-4.19/950-0210-staging-bcm2835-camera-Do-not-bulk-receive-from-serv.patch
deleted file mode 100644 (file)
index 9d2ae1b..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-From 522f1499310d389e663a4e8dd0ccbb916b768766 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 14 Feb 2018 17:04:26 +0000
-Subject: [PATCH] staging: bcm2835-camera: Do not bulk receive from
- service thread
-
-vchi_bulk_queue_receive will queue up to a default of 4
-bulk receives on a connection before blocking.
-If called from the VCHI service_callback thread, then
-that thread is unable to service the VCHI_CALLBACK_BULK_RECEIVED
-events that would enable the queue call to succeed.
-
-Add a workqueue to schedule the call vchi_bulk_queue_receive
-in an alternate context to avoid the lock up.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/mmal-vchiq.c | 101 ++++++++++--------
- 1 file changed, 59 insertions(+), 42 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-@@ -118,8 +118,10 @@ struct mmal_msg_context {
-       union {
-               struct {
--                      /* work struct for defered callback - must come first */
-+                      /* work struct for buffer_cb callback */
-                       struct work_struct work;
-+                      /* work struct for deferred callback */
-+                      struct work_struct buffer_to_host_work;
-                       /* mmal instance */
-                       struct vchiq_mmal_instance *instance;
-                       /* mmal port */
-@@ -168,6 +170,9 @@ struct vchiq_mmal_instance {
-       /* component to use next */
-       int component_idx;
-       struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
-+
-+      /* ordered workqueue to process all bulk operations */
-+      struct workqueue_struct *bulk_wq;
- };
- static struct mmal_msg_context *
-@@ -251,7 +256,44 @@ static void buffer_work_cb(struct work_s
-                                           msg_context->u.bulk.mmal_flags,
-                                           msg_context->u.bulk.dts,
-                                           msg_context->u.bulk.pts);
-+}
-+/* workqueue scheduled callback to handle receiving buffers
-+ *
-+ * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
-+ * If we block in the service_callback context then we can't process the
-+ * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
-+ * vchi_bulk_queue_receive() call to complete.
-+ */
-+static void buffer_to_host_work_cb(struct work_struct *work)
-+{
-+      struct mmal_msg_context *msg_context =
-+              container_of(work, struct mmal_msg_context,
-+                           u.bulk.buffer_to_host_work);
-+      struct vchiq_mmal_instance *instance = msg_context->instance;
-+      unsigned long len = msg_context->u.bulk.buffer_used;
-+      int ret;
-+
-+      if (!len)
-+              /* Dummy receive to ensure the buffers remain in order */
-+              len = 8;
-+      /* queue the bulk submission */
-+      vchi_service_use(instance->handle);
-+      ret = vchi_bulk_queue_receive(instance->handle,
-+                                    msg_context->u.bulk.buffer->buffer,
-+                                    /* Actual receive needs to be a multiple
-+                                     * of 4 bytes
-+                                     */
-+                                    (len + 3) & ~3,
-+                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
-+                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
-+                                    msg_context);
-+
-+      vchi_service_release(instance->handle);
-+
-+      if (ret != 0)
-+              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
-+                     __func__, msg_context, ret);
- }
- /* enqueue a bulk receive for a given message context */
-@@ -260,7 +302,6 @@ static int bulk_receive(struct vchiq_mma
-                       struct mmal_msg_context *msg_context)
- {
-       unsigned long rd_len;
--      int ret;
-       rd_len = msg->u.buffer_from_host.buffer_header.length;
-@@ -294,45 +335,10 @@ static int bulk_receive(struct vchiq_mma
-       msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
-       msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
--      /* queue the bulk submission */
--      vchi_service_use(instance->handle);
--      ret = vchi_bulk_queue_receive(instance->handle,
--                                    msg_context->u.bulk.buffer->buffer,
--                                    /* Actual receive needs to be a multiple
--                                     * of 4 bytes
--                                     */
--                                    (rd_len + 3) & ~3,
--                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
--                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
--                                    msg_context);
--
--      vchi_service_release(instance->handle);
-+      queue_work(msg_context->instance->bulk_wq,
-+                 &msg_context->u.bulk.buffer_to_host_work);
--      return ret;
--}
--
--/* enque a dummy bulk receive for a given message context */
--static int dummy_bulk_receive(struct vchiq_mmal_instance *instance,
--                            struct mmal_msg_context *msg_context)
--{
--      int ret;
--
--      /* zero length indicates this was a dummy transfer */
--      msg_context->u.bulk.buffer_used = 0;
--
--      /* queue the bulk submission */
--      vchi_service_use(instance->handle);
--
--      ret = vchi_bulk_queue_receive(instance->handle,
--                                    instance->bulk_scratch,
--                                    8,
--                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
--                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
--                                    msg_context);
--
--      vchi_service_release(instance->handle);
--
--      return ret;
-+      return 0;
- }
- /* data in message, memcpy from packet into output buffer */
-@@ -380,6 +386,8 @@ buffer_from_host(struct vchiq_mmal_insta
-       /* initialise work structure ready to schedule callback */
-       INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
-+      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
-+                buffer_to_host_work_cb);
-       atomic_inc(&port->buffers_with_vpu);
-@@ -465,7 +473,7 @@ static void buffer_to_host_cb(struct vch
-               if (msg->u.buffer_from_host.buffer_header.flags &
-                   MMAL_BUFFER_HEADER_FLAG_EOS) {
-                       msg_context->u.bulk.status =
--                          dummy_bulk_receive(instance, msg_context);
-+                          bulk_receive(instance, msg, msg_context);
-                       if (msg_context->u.bulk.status == 0)
-                               return; /* successful bulk submission, bulk
-                                        * completion will trigger callback
-@@ -1789,6 +1797,9 @@ int vchiq_mmal_finalise(struct vchiq_mma
-       mutex_unlock(&instance->vchiq_mutex);
-+      flush_workqueue(instance->bulk_wq);
-+      destroy_workqueue(instance->bulk_wq);
-+
-       vfree(instance->bulk_scratch);
-       idr_destroy(&instance->context_map);
-@@ -1858,6 +1869,11 @@ int vchiq_mmal_init(struct vchiq_mmal_in
-       params.callback_param = instance;
-+      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
-+                                                  WQ_MEM_RECLAIM);
-+      if (!instance->bulk_wq)
-+              goto err_free;
-+
-       status = vchi_service_open(vchi_instance, &params, &instance->handle);
-       if (status) {
-               pr_err("Failed to open VCHI service connection (status=%d)\n",
-@@ -1872,8 +1888,9 @@ int vchiq_mmal_init(struct vchiq_mmal_in
-       return 0;
- err_close_services:
--
-       vchi_service_close(instance->handle);
-+      destroy_workqueue(instance->bulk_wq);
-+err_free:
-       vfree(instance->bulk_scratch);
-       kfree(instance);
-       return -ENODEV;
diff --git a/target/linux/brcm2708/patches-4.19/950-0211-staging-bcm2835-camera-Ensure-H264-header-bytes-get-.patch b/target/linux/brcm2708/patches-4.19/950-0211-staging-bcm2835-camera-Ensure-H264-header-bytes-get-.patch
deleted file mode 100644 (file)
index 12afc4a..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-From bf5bbfec3cb99c469eb59f2b19411146c47feb73 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 14:21:04 +0000
-Subject: [PATCH] staging: bcm2835-camera: Ensure H264 header bytes get
- a sensible timestamp
-
-H264 header come from VC with 0 timestamps, which means they get a
-strange timestamp when processed with VC/kernel start times,
-particularly if used with the inline header option.
-Remember the last frame timestamp and use that if set, or otherwise
-use the kernel start time.
-
-https://github.com/raspberrypi/linux/issues/1836
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c           | 30 +++++++++++++++++--
- .../bcm2835-camera/bcm2835-camera.h           |  2 ++
- 2 files changed, 29 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -363,8 +363,13 @@ static void buffer_cb(struct vchiq_mmal_
-               }
-       } else {
-               if (dev->capture.frame_count) {
--                      if (dev->capture.vc_start_timestamp != -1 &&
--                          pts != 0) {
-+                      if (dev->capture.vc_start_timestamp == -1) {
-+                              buf->vb.vb2_buf.timestamp = ktime_get_ns();
-+                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                                       "Buffer time set as current time - %lld",
-+                                       buf->vb.vb2_buf.timestamp);
-+
-+                      } else if (pts != 0) {
-                               ktime_t timestamp;
-                               s64 runtime_us = pts -
-                                   dev->capture.vc_start_timestamp;
-@@ -377,10 +382,28 @@ static void buffer_cb(struct vchiq_mmal_
-                                        ktime_to_ns(timestamp));
-                               buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
-                       } else {
--                              buf->vb.vb2_buf.timestamp = ktime_get_ns();
-+                              if (dev->capture.last_timestamp) {
-+                                      buf->vb.vb2_buf.timestamp =
-+                                              dev->capture.last_timestamp;
-+                                      v4l2_dbg(1, bcm2835_v4l2_debug,
-+                                               &dev->v4l2_dev,
-+                                               "Buffer time set as last timestamp - %lld",
-+                                               buf->vb.vb2_buf.timestamp);
-+                              } else {
-+                                      buf->vb.vb2_buf.timestamp =
-+                                              ktime_to_ns(dev->capture.kernel_start_ts);
-+                                      v4l2_dbg(1, bcm2835_v4l2_debug,
-+                                               &dev->v4l2_dev,
-+                                               "Buffer time set as start timestamp - %lld",
-+                                               buf->vb.vb2_buf.timestamp);
-+                              }
-                       }
-+                      dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-                       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
-+                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                               "Buffer has ts %llu",
-+                               dev->capture.last_timestamp);
-                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
-                       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
-@@ -546,6 +569,7 @@ static int start_streaming(struct vb2_qu
-                        dev->capture.vc_start_timestamp, parameter_size);
-       dev->capture.kernel_start_ts = ktime_get();
-+      dev->capture.last_timestamp = 0;
-       /* enable the camera port */
-       dev->capture.port->cb_ctx = dev;
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-@@ -90,6 +90,8 @@ struct bm2835_mmal_dev {
-               s64         vc_start_timestamp;
-               /* Kernel start timestamp for streaming */
-               ktime_t kernel_start_ts;
-+              /* Timestamp of last frame */
-+              u64             last_timestamp;
-               struct vchiq_mmal_port  *port; /* port being used for capture */
-               /* camera port being used for capture */
diff --git a/target/linux/brcm2708/patches-4.19/950-0211-staging-bcm2835-camera-Return-early-on-errors.patch b/target/linux/brcm2708/patches-4.19/950-0211-staging-bcm2835-camera-Return-early-on-errors.patch
new file mode 100644 (file)
index 0000000..616cace
--- /dev/null
@@ -0,0 +1,196 @@
+From 3cb19cb6b4d6dc86582abef6200c0fc663ae3f2a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 10 Mar 2017 17:27:56 +0000
+Subject: [PATCH] staging: bcm2835-camera: Return early on errors
+
+Fix several instances where it is easier to return
+early on error conditions than handle it as an else
+clause.
+As requested by Mauro.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 137 +++++++++---------
+ 1 file changed, 71 insertions(+), 66 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -335,7 +335,9 @@ static void buffer_cb(struct vchiq_mmal_
+                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+               }
+               return;
+-      } else if (length == 0) {
++      }
++
++      if (length == 0) {
+               /* stream ended */
+               if (dev->capture.frame_count) {
+                       /* empty buffer whilst capturing - expected to be an
+@@ -361,71 +363,72 @@ static void buffer_cb(struct vchiq_mmal_
+                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+                       complete(&dev->capture.frame_cmplt);
+               }
+-      } else {
+-              if (dev->capture.frame_count) {
+-                      if (dev->capture.vc_start_timestamp == -1) {
+-                              buf->vb.vb2_buf.timestamp = ktime_get_ns();
+-                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+-                                       "Buffer time set as current time - %lld",
+-                                       buf->vb.vb2_buf.timestamp);
+-
+-                      } else if (pts != 0) {
+-                              ktime_t timestamp;
+-                              s64 runtime_us = pts -
+-                                  dev->capture.vc_start_timestamp;
+-                              timestamp = ktime_add_us(dev->capture.kernel_start_ts,
+-                                                       runtime_us);
+-                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+-                                       "Convert start time %llu and %llu with offset %llu to %llu\n",
+-                                       ktime_to_ns(dev->capture.kernel_start_ts),
+-                                       dev->capture.vc_start_timestamp, pts,
+-                                       ktime_to_ns(timestamp));
+-                              buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
+-                      } else {
+-                              if (dev->capture.last_timestamp) {
+-                                      buf->vb.vb2_buf.timestamp =
+-                                              dev->capture.last_timestamp;
+-                                      v4l2_dbg(1, bcm2835_v4l2_debug,
+-                                               &dev->v4l2_dev,
+-                                               "Buffer time set as last timestamp - %lld",
+-                                               buf->vb.vb2_buf.timestamp);
+-                              } else {
+-                                      buf->vb.vb2_buf.timestamp =
+-                                              ktime_to_ns(dev->capture.kernel_start_ts);
+-                                      v4l2_dbg(1, bcm2835_v4l2_debug,
+-                                               &dev->v4l2_dev,
+-                                               "Buffer time set as start timestamp - %lld",
+-                                               buf->vb.vb2_buf.timestamp);
+-                              }
+-                      }
+-                      dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
++              return;
++      }
+-                      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
+-                      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+-                              buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
++      if (!dev->capture.frame_count) {
++              /* signal frame completion */
++              vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
++              complete(&dev->capture.frame_cmplt);
++              return;
++      }
++      if (dev->capture.vc_start_timestamp == -1) {
++              /*
++               * VPU doesn't support MMAL_PARAMETER_SYSTEM_TIME, rely on
++               * kernel time, and have no latency compensation.
++               */
++              buf->vb.vb2_buf.timestamp = ktime_get_ns();
++              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                       "Buffer time set as current time - %lld",
++                       buf->vb.vb2_buf.timestamp);
++      } else if (pts != 0) {
++              ktime_t timestamp;
++              s64 runtime_us = pts -
++                  dev->capture.vc_start_timestamp;
++              timestamp = ktime_add_us(dev->capture.kernel_start_ts,
++                                       runtime_us);
++              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                       "Convert start time %llu and %llu with offset %llu to %llu\n",
++                       ktime_to_ns(dev->capture.kernel_start_ts),
++                       dev->capture.vc_start_timestamp, pts,
++                       ktime_to_ns(timestamp));
++              buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
++      } else {
++              if (dev->capture.last_timestamp) {
++                      buf->vb.vb2_buf.timestamp = dev->capture.last_timestamp;
+                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+-                               "Buffer has ts %llu",
+-                               dev->capture.last_timestamp);
+-                      vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+-
+-                      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
+-                          is_capturing(dev)) {
+-                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+-                                       "Grab another frame as buffer has EOS");
+-                              vchiq_mmal_port_parameter_set(
+-                                      instance,
+-                                      dev->capture.camera_port,
+-                                      MMAL_PARAMETER_CAPTURE,
+-                                      &dev->capture.frame_count,
+-                                      sizeof(dev->capture.frame_count));
+-                      }
++                               "Buffer time set as last timestamp - %lld",
++                               buf->vb.vb2_buf.timestamp);
+               } else {
+-                      /* signal frame completion */
+-                      vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+-                      complete(&dev->capture.frame_cmplt);
++                      buf->vb.vb2_buf.timestamp =
++                              ktime_to_ns(dev->capture.kernel_start_ts);
++                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                               "Buffer time set as start timestamp - %lld",
++                               buf->vb.vb2_buf.timestamp);
+               }
+       }
++      dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
++
++      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
++      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
++              buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
++
++      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++               "Buffer has ts %llu",
++               dev->capture.last_timestamp);
++      vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
++
++      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
++          is_capturing(dev)) {
++              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                       "Grab another frame as buffer has EOS");
++              vchiq_mmal_port_parameter_set(instance,
++                                            dev->capture.camera_port,
++                                            MMAL_PARAMETER_CAPTURE,
++                                            &dev->capture.frame_count,
++                                            sizeof(dev->capture.frame_count));
++      }
+ }
+ static int enable_camera(struct bm2835_mmal_dev *dev)
+@@ -815,27 +818,29 @@ static int vidioc_overlay(struct file *f
+       ret = vchiq_mmal_port_set_format(dev->instance, src);
+       if (ret < 0)
+-              goto error;
++              return ret;
+       ret = set_overlay_params(dev, dst);
+       if (ret < 0)
+-              goto error;
++              return ret;
+-      if (enable_camera(dev) < 0)
+-              goto error;
++      if (enable_camera(dev) < 0) {
++              ret = -EINVAL;
++              return ret;
++      }
+       ret = vchiq_mmal_component_enable(
+                       dev->instance,
+                       dev->component[MMAL_COMPONENT_PREVIEW]);
+       if (ret < 0)
+-              goto error;
++              return ret;
+       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n",
+                src, dst);
+       ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst);
+       if (!ret)
+               ret = vchiq_mmal_port_enable(dev->instance, src, NULL);
+-error:
++
+       return ret;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0212-staging-bcm2835-camera-Correctly-denote-key-frames-i.patch b/target/linux/brcm2708/patches-4.19/950-0212-staging-bcm2835-camera-Correctly-denote-key-frames-i.patch
deleted file mode 100644 (file)
index 96116cb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 6c70a89ac19b1ead96be68002affcd1821014d52 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 13 Feb 2017 13:11:41 +0000
-Subject: [PATCH] staging: bcm2835-camera: Correctly denote key frames
- in encoded data
-
-Forward MMAL key frame flags to the V4L2 buffers.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -401,6 +401,9 @@ static void buffer_cb(struct vchiq_mmal_
-                       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-                       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
-+                      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-+                              buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-+
-                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                                "Buffer has ts %llu",
-                                dev->capture.last_timestamp);
diff --git a/target/linux/brcm2708/patches-4.19/950-0212-staging-bcm2835-camera-Remove-dead-email-addresses.patch b/target/linux/brcm2708/patches-4.19/950-0212-staging-bcm2835-camera-Remove-dead-email-addresses.patch
new file mode 100644 (file)
index 0000000..2041ebb
--- /dev/null
@@ -0,0 +1,241 @@
+From b1d4e377b4a8c73396d50c45106f3d3a710b11f5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 10 Mar 2017 17:35:38 +0000
+Subject: [PATCH] staging: bcm2835-camera: Remove dead email addresses
+
+None of the listed author email addresses were valid.
+Keep list of authors and the companies they represented.
+Update my email address.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/bcm2835-camera.c        | 9 +++++----
+ .../vc04_services/bcm2835-camera/bcm2835-camera.h        | 9 +++++----
+ drivers/staging/vc04_services/bcm2835-camera/controls.c  | 9 +++++----
+ .../staging/vc04_services/bcm2835-camera/mmal-common.h   | 9 +++++----
+ .../vc04_services/bcm2835-camera/mmal-encodings.h        | 9 +++++----
+ .../vc04_services/bcm2835-camera/mmal-msg-common.h       | 9 +++++----
+ .../vc04_services/bcm2835-camera/mmal-msg-format.h       | 9 +++++----
+ .../staging/vc04_services/bcm2835-camera/mmal-msg-port.h | 9 +++++----
+ drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h  | 9 +++++----
+ .../vc04_services/bcm2835-camera/mmal-parameters.h       | 9 +++++----
+ .../staging/vc04_services/bcm2835-camera/mmal-vchiq.c    | 9 +++++----
+ .../staging/vc04_services/bcm2835-camera/mmal-vchiq.h    | 9 +++++----
+ 12 files changed, 60 insertions(+), 48 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ #include <linux/errno.h>
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  *
+  * core driver device
+  */
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ #include <linux/errno.h>
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  *
+  * MMAL structures
+  *
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ #ifndef MMAL_ENCODINGS_H
+ #define MMAL_ENCODINGS_H
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ #ifndef MMAL_MSG_COMMON_H
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ #ifndef MMAL_MSG_FORMAT_H
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ /* MMAL_PORT_TYPE_T */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ /* all the data structures which serialise the MMAL protocol. note
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  */
+ /* common parameters */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  *
+  * V4L2 driver MMAL vchiq interface code
+  */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
+@@ -4,10 +4,11 @@
+  *
+  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+  *
+- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
+- *          Dave Stevenson <dsteve@broadcom.com>
+- *          Simon Mellor <simellor@broadcom.com>
+- *          Luke Diamand <luked@broadcom.com>
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
+  *
+  * MMAL interface to VCHIQ message passing
+  */
diff --git a/target/linux/brcm2708/patches-4.19/950-0213-staging-bcm2835-camera-Fix-comment-style-violations.patch b/target/linux/brcm2708/patches-4.19/950-0213-staging-bcm2835-camera-Fix-comment-style-violations.patch
new file mode 100644 (file)
index 0000000..4788eeb
--- /dev/null
@@ -0,0 +1,617 @@
+From 4fb0df1b29feafacc244ca512b152dd3b96c224c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 13:49:32 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix comment style
+ violations.
+
+Fix comment style violations in the header files.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/mmal-msg-format.h          |  95 ++++++------
+ .../bcm2835-camera/mmal-msg-port.h            | 124 ++++++++--------
+ .../vc04_services/bcm2835-camera/mmal-msg.h   | 135 +++++++++---------
+ 3 files changed, 185 insertions(+), 169 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
+@@ -19,22 +19,23 @@
+ /* MMAL_ES_FORMAT_T */
+ struct mmal_audio_format {
+-      u32 channels;           /**< Number of audio channels */
+-      u32 sample_rate;        /**< Sample rate */
++      u32 channels;           /* Number of audio channels */
++      u32 sample_rate;        /* Sample rate */
+-      u32 bits_per_sample;    /**< Bits per sample */
+-      u32 block_align;        /**< Size of a block of data */
++      u32 bits_per_sample;    /* Bits per sample */
++      u32 block_align;        /* Size of a block of data */
+ };
+ struct mmal_video_format {
+-      u32 width;        /**< Width of frame in pixels */
+-      u32 height;       /**< Height of frame in rows of pixels */
+-      struct mmal_rect crop;         /**< Visible region of the frame */
+-      struct mmal_rational frame_rate;   /**< Frame rate */
+-      struct mmal_rational par;          /**< Pixel aspect ratio */
+-
+-      /* FourCC specifying the color space of the video stream. See the
+-       * \ref MmalColorSpace "pre-defined color spaces" for some examples.
++      u32 width;              /* Width of frame in pixels */
++      u32 height;             /* Height of frame in rows of pixels */
++      struct mmal_rect crop;  /* Visible region of the frame */
++      struct mmal_rational frame_rate;        /* Frame rate */
++      struct mmal_rational par;               /* Pixel aspect ratio */
++
++      /*
++       * FourCC specifying the color space of the video stream. See the
++       * MmalColorSpace "pre-defined color spaces" for some examples.
+        */
+       u32 color_space;
+ };
+@@ -50,48 +51,56 @@ union mmal_es_specific_format {
+       struct mmal_subpicture_format subpicture;
+ };
+-/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
++/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
+ struct mmal_es_format_local {
+-      u32 type;      /* enum mmal_es_type */
+-
+-      u32 encoding;  /* FourCC specifying encoding of the elementary stream.*/
+-      u32 encoding_variant; /* FourCC specifying the specific
+-                             * encoding variant of the elementary
+-                             * stream.
+-                             */
+-
+-      union mmal_es_specific_format *es;  /* Type specific
+-                                           * information for the
+-                                           * elementary stream
+-                                           */
++      u32 type;       /* enum mmal_es_type */
+-      u32 bitrate;        /**< Bitrate in bits per second */
+-      u32 flags; /**< Flags describing properties of the elementary stream. */
++      u32 encoding;   /* FourCC specifying encoding of the elementary
++                       * stream.
++                       */
++      u32 encoding_variant;   /* FourCC specifying the specific
++                               * encoding variant of the elementary
++                               * stream.
++                               */
++
++      union mmal_es_specific_format *es;      /* Type specific
++                                               * information for the
++                                               * elementary stream
++                                               */
++
++      u32 bitrate;    /* Bitrate in bits per second */
++      u32 flags;      /* Flags describing properties of the elementary
++                       * stream.
++                       */
+-      u32 extradata_size;       /**< Size of the codec specific data */
+-      u8  *extradata;           /**< Codec specific data */
++      u32 extradata_size;     /* Size of the codec specific data */
++      u8  *extradata;         /* Codec specific data */
+ };
+-/** Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
++/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
+ struct mmal_es_format {
+-      u32 type;      /* enum mmal_es_type */
++      u32 type;       /* enum mmal_es_type */
+-      u32 encoding;  /* FourCC specifying encoding of the elementary stream.*/
+-      u32 encoding_variant; /* FourCC specifying the specific
+-                             * encoding variant of the elementary
+-                             * stream.
+-                             */
++      u32 encoding;   /* FourCC specifying encoding of the elementary
++                       * stream.
++                       */
++      u32 encoding_variant;   /* FourCC specifying the specific
++                               * encoding variant of the elementary
++                               * stream.
++                               */
+-      u32 es; /* Type specific
++      u32 es; /* Type specific
+                * information for the
+                * elementary stream
+                */
+-      u32 bitrate;        /**< Bitrate in bits per second */
+-      u32 flags; /**< Flags describing properties of the elementary stream. */
++      u32 bitrate;    /* Bitrate in bits per second */
++      u32 flags;      /* Flags describing properties of the elementary
++                       * stream.
++                       */
+-      u32 extradata_size;       /**< Size of the codec specific data */
+-      u32 extradata;           /**< Codec specific data */
++      u32 extradata_size;     /* Size of the codec specific data */
++      u32 extradata;          /* Codec specific data */
+ };
+ #endif /* MMAL_MSG_FORMAT_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
+@@ -13,28 +13,31 @@
+ /* MMAL_PORT_TYPE_T */
+ enum mmal_port_type {
+-      MMAL_PORT_TYPE_UNKNOWN = 0,  /**< Unknown port type */
+-      MMAL_PORT_TYPE_CONTROL,      /**< Control port */
+-      MMAL_PORT_TYPE_INPUT,        /**< Input port */
+-      MMAL_PORT_TYPE_OUTPUT,       /**< Output port */
+-      MMAL_PORT_TYPE_CLOCK,        /**< Clock port */
++      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
++      MMAL_PORT_TYPE_CONTROL,         /* Control port */
++      MMAL_PORT_TYPE_INPUT,           /* Input port */
++      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
++      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
+ };
+-/** The port is pass-through and doesn't need buffer headers allocated */
++/* The port is pass-through and doesn't need buffer headers allocated */
+ #define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
+-/** The port wants to allocate the buffer payloads.
++/*
++ *The port wants to allocate the buffer payloads.
+  * This signals a preference that payload allocation should be done
+  * on this port for efficiency reasons.
+  */
+ #define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
+-/** The port supports format change events.
++/*
++ * The port supports format change events.
+  * This applies to input ports and is used to let the client know
+  * whether the port supports being reconfigured via a format
+  * change event (i.e. without having to disable the port).
+  */
+ #define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
+-/* mmal port structure (MMAL_PORT_T)
++/*
++ * mmal port structure (MMAL_PORT_T)
+  *
+  * most elements are informational only, the pointer values for
+  * interogation messages are generally provided as additional
+@@ -42,50 +45,50 @@ enum mmal_port_type {
+  * buffer_num, buffer_size and userdata parameters are writable.
+  */
+ struct mmal_port {
+-      u32 priv; /* Private member used by the framework */
+-      u32 name; /* Port name. Used for debugging purposes (RO) */
++      u32 priv;       /* Private member used by the framework */
++      u32 name;       /* Port name. Used for debugging purposes (RO) */
+-      u32 type;      /* Type of the port (RO) enum mmal_port_type */
+-      u16 index;     /* Index of the port in its type list (RO) */
+-      u16 index_all; /* Index of the port in the list of all ports (RO) */
+-
+-      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
+-      u32 format; /* Format of the elementary stream */
+-
+-      u32 buffer_num_min; /* Minimum number of buffers the port
+-                           *   requires (RO).  This is set by the
+-                           *   component.
+-                           */
+-
+-      u32 buffer_size_min; /* Minimum size of buffers the port
+-                            * requires (RO).  This is set by the
+-                            * component.
+-                            */
+-
+-      u32 buffer_alignment_min; /* Minimum alignment requirement for
+-                                 * the buffers (RO).  A value of
+-                                 * zero means no special alignment
+-                                 * requirements.  This is set by the
+-                                 * component.
+-                                 */
+-
+-      u32 buffer_num_recommended;  /* Number of buffers the port
+-                                    * recommends for optimal
+-                                    * performance (RO).  A value of
+-                                    * zero means no special
+-                                    * recommendation.  This is set
+-                                    * by the component.
+-                                    */
+-
+-      u32 buffer_size_recommended; /* Size of buffers the port
+-                                    * recommends for optimal
+-                                    * performance (RO).  A value of
+-                                    * zero means no special
+-                                    * recommendation.  This is set
+-                                    * by the component.
+-                                    */
++      u32 type;       /* Type of the port (RO) enum mmal_port_type */
++      u16 index;      /* Index of the port in its type list (RO) */
++      u16 index_all;  /* Index of the port in the list of all ports (RO) */
++
++      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
++      u32 format;     /* Format of the elementary stream */
++
++      u32 buffer_num_min;     /* Minimum number of buffers the port
++                               *   requires (RO).  This is set by the
++                               *   component.
++                               */
++
++      u32 buffer_size_min;    /* Minimum size of buffers the port
++                               * requires (RO).  This is set by the
++                               * component.
++                               */
++
++      u32 buffer_alignment_min;/* Minimum alignment requirement for
++                                * the buffers (RO).  A value of
++                                * zero means no special alignment
++                                * requirements.  This is set by the
++                                * component.
++                                */
++
++      u32 buffer_num_recommended;     /* Number of buffers the port
++                                       * recommends for optimal
++                                       * performance (RO).  A value of
++                                       * zero means no special
++                                       * recommendation.  This is set
++                                       * by the component.
++                                       */
++
++      u32 buffer_size_recommended;    /* Size of buffers the port
++                                       * recommends for optimal
++                                       * performance (RO).  A value of
++                                       * zero means no special
++                                       * recommendation.  This is set
++                                       * by the component.
++                                       */
+-      u32 buffer_num; /* Actual number of buffers the port will use.
++      u32 buffer_num; /* Actual number of buffers the port will use.
+                        * This is set by the client.
+                        */
+@@ -94,14 +97,13 @@ struct mmal_port {
+                         * the client.
+                         */
+-      u32 component; /* Component this port belongs to (Read Only) */
++      u32 component;  /* Component this port belongs to (Read Only) */
+-      u32 userdata; /* Field reserved for use by the client */
+-
+-      u32 capabilities; /* Flags describing the capabilities of a
+-                         * port (RO).  Bitwise combination of \ref
+-                         * portcapabilities "Port capabilities"
+-                         * values.
+-                         */
++      u32 userdata;   /* Field reserved for use by the client */
++      u32 capabilities;       /* Flags describing the capabilities of a
++                               * port (RO).  Bitwise combination of \ref
++                               * portcapabilities "Port capabilities"
++                               * values.
++                               */
+ };
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
+@@ -11,7 +11,8 @@
+  *          Luke Diamand @ Broadcom
+  */
+-/* all the data structures which serialise the MMAL protocol. note
++/*
++ * all the data structures which serialise the MMAL protocol. note
+  * these are directly mapped onto the recived message data.
+  *
+  * BEWARE: They seem to *assume* pointers are u32 and that there is no
+@@ -41,51 +42,51 @@ enum mmal_msg_type {
+       MMAL_MSG_TYPE_SERVICE_CLOSED,
+       MMAL_MSG_TYPE_GET_VERSION,
+       MMAL_MSG_TYPE_COMPONENT_CREATE,
+-      MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */
++      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
+       MMAL_MSG_TYPE_COMPONENT_ENABLE,
+       MMAL_MSG_TYPE_COMPONENT_DISABLE,
+       MMAL_MSG_TYPE_PORT_INFO_GET,
+       MMAL_MSG_TYPE_PORT_INFO_SET,
+-      MMAL_MSG_TYPE_PORT_ACTION, /* 10 */
++      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
+       MMAL_MSG_TYPE_BUFFER_FROM_HOST,
+       MMAL_MSG_TYPE_BUFFER_TO_HOST,
+       MMAL_MSG_TYPE_GET_STATS,
+       MMAL_MSG_TYPE_PORT_PARAMETER_SET,
+-      MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */
++      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
+       MMAL_MSG_TYPE_EVENT_TO_HOST,
+       MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
+       MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
+       MMAL_MSG_TYPE_CONSUME_MEM,
+-      MMAL_MSG_TYPE_LMK, /* 20 */
++      MMAL_MSG_TYPE_LMK,                      /* 20 */
+       MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
+       MMAL_MSG_TYPE_DRM_GET_LHS32,
+       MMAL_MSG_TYPE_DRM_GET_TIME,
+       MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
+-      MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */
++      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
+       MMAL_MSG_TYPE_HOST_LOG,
+       MMAL_MSG_TYPE_MSG_LAST
+ };
+ /* port action request messages differ depending on the action type */
+ enum mmal_msg_port_action_type {
+-      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,      /* Unknown action */
+-      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,           /* Enable a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,          /* Disable a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,            /* Flush a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,          /* Connect ports */
+-      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,       /* Disconnect ports */
++      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
++      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
++      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
++      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
++      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
++      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
+       MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
+ };
+ struct mmal_msg_header {
+       u32 magic;
+-      u32 type; /** enum mmal_msg_type */
++      u32 type;       /* enum mmal_msg_type */
+       /* Opaque handle to the control service */
+       u32 control_service;
+-      u32 context; /** a u32 per message context */
+-      u32 status; /** The status of the vchiq operation */
++      u32 context;    /* a u32 per message context */
++      u32 status;     /* The status of the vchiq operation */
+       u32 padding;
+ };
+@@ -99,9 +100,9 @@ struct mmal_msg_version {
+ /* request to VC to create component */
+ struct mmal_msg_component_create {
+-      u32 client_component; /* component context */
++      u32 client_component;   /* component context */
+       char name[128];
+-      u32 pid;                /* For debug */
++      u32 pid;                /* For debug */
+ };
+ /* reply from VC to component creation request */
+@@ -121,7 +122,7 @@ struct mmal_msg_component_destroy {
+ };
+ struct mmal_msg_component_destroy_reply {
+-      u32 status; /** The component destruction status */
++      u32 status; /* The component destruction status */
+ };
+ /* request and reply to VC to enable a component */
+@@ -130,7 +131,7 @@ struct mmal_msg_component_enable {
+ };
+ struct mmal_msg_component_enable_reply {
+-      u32 status; /** The component enable status */
++      u32 status; /* The component enable status */
+ };
+ /* request and reply to VC to disable a component */
+@@ -139,7 +140,7 @@ struct mmal_msg_component_disable {
+ };
+ struct mmal_msg_component_disable_reply {
+-      u32 status; /** The component disable status */
++      u32 status; /* The component disable status */
+ };
+ /* request to VC to get port information */
+@@ -151,12 +152,12 @@ struct mmal_msg_port_info_get {
+ /* reply from VC to get port info request */
+ struct mmal_msg_port_info_get_reply {
+-      u32 status; /** enum mmal_msg_status */
+-      u32 component_handle;  /* component handle port is associated with */
+-      u32 port_type;         /* enum mmal_msg_port_type */
+-      u32 port_index;        /* port indexed in query */
+-      s32 found;             /* unused */
+-      u32 port_handle;               /**< Handle to use for this port */
++      u32 status;             /* enum mmal_msg_status */
++      u32 component_handle;   /* component handle port is associated with */
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 port_index;         /* port indexed in query */
++      s32 found;              /* unused */
++      u32 port_handle;        /* Handle to use for this port */
+       struct mmal_port port;
+       struct mmal_es_format format; /* elementary stream format */
+       union mmal_es_specific_format es; /* es type specific data */
+@@ -166,8 +167,8 @@ struct mmal_msg_port_info_get_reply {
+ /* request to VC to set port information */
+ struct mmal_msg_port_info_set {
+       u32 component_handle;
+-      u32 port_type;         /* enum mmal_msg_port_type */
+-      u32 port_index;           /* port indexed in query */
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 port_index;         /* port indexed in query */
+       struct mmal_port port;
+       struct mmal_es_format format;
+       union mmal_es_specific_format es;
+@@ -177,11 +178,11 @@ struct mmal_msg_port_info_set {
+ /* reply from VC to port info set request */
+ struct mmal_msg_port_info_set_reply {
+       u32 status;
+-      u32 component_handle;  /* component handle port is associated with */
+-      u32 port_type;         /* enum mmal_msg_port_type */
+-      u32 index;             /* port indexed in query */
+-      s32 found;             /* unused */
+-      u32 port_handle;               /**< Handle to use for this port */
++      u32 component_handle;   /* component handle port is associated with */
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 index;              /* port indexed in query */
++      s32 found;              /* unused */
++      u32 port_handle;        /* Handle to use for this port */
+       struct mmal_port port;
+       struct mmal_es_format format;
+       union mmal_es_specific_format es;
+@@ -192,7 +193,7 @@ struct mmal_msg_port_info_set_reply {
+ struct mmal_msg_port_action_port {
+       u32 component_handle;
+       u32 port_handle;
+-      u32 action; /* enum mmal_msg_port_action_type */
++      u32 action;             /* enum mmal_msg_port_action_type */
+       struct mmal_port port;
+ };
+@@ -200,50 +201,53 @@ struct mmal_msg_port_action_port {
+ struct mmal_msg_port_action_handle {
+       u32 component_handle;
+       u32 port_handle;
+-      u32 action; /* enum mmal_msg_port_action_type */
++      u32 action;             /* enum mmal_msg_port_action_type */
+       u32 connect_component_handle;
+       u32 connect_port_handle;
+ };
+ struct mmal_msg_port_action_reply {
+-      u32 status; /** The port action operation status */
++      u32 status;     /* The port action operation status */
+ };
+ /* MMAL buffer transfer */
+-/** Size of space reserved in a buffer message for short messages. */
++/* Size of space reserved in a buffer message for short messages. */
+ #define MMAL_VC_SHORT_DATA 128
+-/** Signals that the current payload is the end of the stream of data */
++/* Signals that the current payload is the end of the stream of data */
+ #define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
+-/** Signals that the start of the current payload starts a frame */
++/* Signals that the start of the current payload starts a frame */
+ #define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
+-/** Signals that the end of the current payload ends a frame */
++/* Signals that the end of the current payload ends a frame */
+ #define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
+-/** Signals that the current payload contains only complete frames (>1) */
++/* Signals that the current payload contains only complete frames (>1) */
+ #define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
+       (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
+-/** Signals that the current payload is a keyframe (i.e. self decodable) */
++/* Signals that the current payload is a keyframe (i.e. self decodable) */
+ #define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
+-/** Signals a discontinuity in the stream of data (e.g. after a seek).
++/*
++ * Signals a discontinuity in the stream of data (e.g. after a seek).
+  * Can be used for instance by a decoder to reset its state
+  */
+ #define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
+-/** Signals a buffer containing some kind of config data for the component
++/*
++ * Signals a buffer containing some kind of config data for the component
+  * (e.g. codec config data)
+  */
+ #define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
+-/** Signals an encrypted payload */
++/* Signals an encrypted payload */
+ #define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
+-/** Signals a buffer containing side information */
++/* Signals a buffer containing side information */
+ #define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
+-/** Signals a buffer which is the snapshot/postview image from a stills
++/*
++ * Signals a buffer which is the snapshot/postview image from a stills
+  * capture
+  */
+ #define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
+-/** Signals a buffer which contains data known to be corrupted */
++/* Signals a buffer which contains data known to be corrupted */
+ #define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
+-/** Signals that a buffer failed to be transmitted */
++/* Signals that a buffer failed to be transmitted */
+ #define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
+ struct mmal_driver_buffer {
+@@ -255,8 +259,8 @@ struct mmal_driver_buffer {
+ /* buffer header */
+ struct mmal_buffer_header {
+-      u32 next; /* next header */
+-      u32 priv; /* framework private data */
++      u32 next;       /* next header */
++      u32 priv;       /* framework private data */
+       u32 cmd;
+       u32 data;
+       u32 alloc_size;
+@@ -281,7 +285,8 @@ struct mmal_buffer_header_type_specific
+ };
+ struct mmal_msg_buffer_from_host {
+-      /* The front 32 bytes of the buffer header are copied
++      /*
++       *The front 32 bytes of the buffer header are copied
+        * back to us in the reply to allow for context. This
+        * area is used to store two mmal_driver_buffer structures to
+        * allow for multiple concurrent service users.
+@@ -296,7 +301,7 @@ struct mmal_msg_buffer_from_host {
+       s32 is_zero_copy;
+       s32 has_reference;
+-      /** allows short data to be xfered in control message */
++      /* allows short data to be xfered in control message */
+       u32 payload_in_message;
+       u8 short_data[MMAL_VC_SHORT_DATA];
+ };
+@@ -306,10 +311,10 @@ struct mmal_msg_buffer_from_host {
+ #define MMAL_WORKER_PORT_PARAMETER_SPACE      96
+ struct mmal_msg_port_parameter_set {
+-      u32 component_handle; /* component */
+-      u32 port_handle;      /* port */
+-      u32 id;     /* Parameter ID  */
+-      u32 size;      /* Parameter size */
++      u32 component_handle;   /* component */
++      u32 port_handle;        /* port */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
+       uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+ };
+@@ -322,16 +327,16 @@ struct mmal_msg_port_parameter_set_reply
+ /* port parameter getting */
+ struct mmal_msg_port_parameter_get {
+-      u32 component_handle; /* component */
+-      u32 port_handle;      /* port */
+-      u32 id;     /* Parameter ID  */
+-      u32 size;      /* Parameter size */
++      u32 component_handle;   /* component */
++      u32 port_handle;        /* port */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
+ };
+ struct mmal_msg_port_parameter_get_reply {
+-      u32 status;           /* Status of mmal_port_parameter_get call */
+-      u32 id;     /* Parameter ID  */
+-      u32 size;      /* Parameter size */
++      u32 status;             /* Status of mmal_port_parameter_get call */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
+       uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+ };
+@@ -339,7 +344,7 @@ struct mmal_msg_port_parameter_get_reply
+ #define MMAL_WORKER_EVENT_SPACE 256
+ struct mmal_msg_event_to_host {
+-      u32 client_component; /* component context */
++      u32 client_component;   /* component context */
+       u32 port_type;
+       u32 port_num;
diff --git a/target/linux/brcm2708/patches-4.19/950-0213-staging-bcm2835-camera-Return-early-on-errors.patch b/target/linux/brcm2708/patches-4.19/950-0213-staging-bcm2835-camera-Return-early-on-errors.patch
deleted file mode 100644 (file)
index 616cace..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-From 3cb19cb6b4d6dc86582abef6200c0fc663ae3f2a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 10 Mar 2017 17:27:56 +0000
-Subject: [PATCH] staging: bcm2835-camera: Return early on errors
-
-Fix several instances where it is easier to return
-early on error conditions than handle it as an else
-clause.
-As requested by Mauro.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c           | 137 +++++++++---------
- 1 file changed, 71 insertions(+), 66 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -335,7 +335,9 @@ static void buffer_cb(struct vchiq_mmal_
-                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-               }
-               return;
--      } else if (length == 0) {
-+      }
-+
-+      if (length == 0) {
-               /* stream ended */
-               if (dev->capture.frame_count) {
-                       /* empty buffer whilst capturing - expected to be an
-@@ -361,71 +363,72 @@ static void buffer_cb(struct vchiq_mmal_
-                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-                       complete(&dev->capture.frame_cmplt);
-               }
--      } else {
--              if (dev->capture.frame_count) {
--                      if (dev->capture.vc_start_timestamp == -1) {
--                              buf->vb.vb2_buf.timestamp = ktime_get_ns();
--                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
--                                       "Buffer time set as current time - %lld",
--                                       buf->vb.vb2_buf.timestamp);
--
--                      } else if (pts != 0) {
--                              ktime_t timestamp;
--                              s64 runtime_us = pts -
--                                  dev->capture.vc_start_timestamp;
--                              timestamp = ktime_add_us(dev->capture.kernel_start_ts,
--                                                       runtime_us);
--                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
--                                       "Convert start time %llu and %llu with offset %llu to %llu\n",
--                                       ktime_to_ns(dev->capture.kernel_start_ts),
--                                       dev->capture.vc_start_timestamp, pts,
--                                       ktime_to_ns(timestamp));
--                              buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
--                      } else {
--                              if (dev->capture.last_timestamp) {
--                                      buf->vb.vb2_buf.timestamp =
--                                              dev->capture.last_timestamp;
--                                      v4l2_dbg(1, bcm2835_v4l2_debug,
--                                               &dev->v4l2_dev,
--                                               "Buffer time set as last timestamp - %lld",
--                                               buf->vb.vb2_buf.timestamp);
--                              } else {
--                                      buf->vb.vb2_buf.timestamp =
--                                              ktime_to_ns(dev->capture.kernel_start_ts);
--                                      v4l2_dbg(1, bcm2835_v4l2_debug,
--                                               &dev->v4l2_dev,
--                                               "Buffer time set as start timestamp - %lld",
--                                               buf->vb.vb2_buf.timestamp);
--                              }
--                      }
--                      dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-+              return;
-+      }
--                      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
--                      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
--                              buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-+      if (!dev->capture.frame_count) {
-+              /* signal frame completion */
-+              vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-+              complete(&dev->capture.frame_cmplt);
-+              return;
-+      }
-+      if (dev->capture.vc_start_timestamp == -1) {
-+              /*
-+               * VPU doesn't support MMAL_PARAMETER_SYSTEM_TIME, rely on
-+               * kernel time, and have no latency compensation.
-+               */
-+              buf->vb.vb2_buf.timestamp = ktime_get_ns();
-+              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                       "Buffer time set as current time - %lld",
-+                       buf->vb.vb2_buf.timestamp);
-+      } else if (pts != 0) {
-+              ktime_t timestamp;
-+              s64 runtime_us = pts -
-+                  dev->capture.vc_start_timestamp;
-+              timestamp = ktime_add_us(dev->capture.kernel_start_ts,
-+                                       runtime_us);
-+              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                       "Convert start time %llu and %llu with offset %llu to %llu\n",
-+                       ktime_to_ns(dev->capture.kernel_start_ts),
-+                       dev->capture.vc_start_timestamp, pts,
-+                       ktime_to_ns(timestamp));
-+              buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
-+      } else {
-+              if (dev->capture.last_timestamp) {
-+                      buf->vb.vb2_buf.timestamp = dev->capture.last_timestamp;
-                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
--                               "Buffer has ts %llu",
--                               dev->capture.last_timestamp);
--                      vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
--
--                      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
--                          is_capturing(dev)) {
--                              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
--                                       "Grab another frame as buffer has EOS");
--                              vchiq_mmal_port_parameter_set(
--                                      instance,
--                                      dev->capture.camera_port,
--                                      MMAL_PARAMETER_CAPTURE,
--                                      &dev->capture.frame_count,
--                                      sizeof(dev->capture.frame_count));
--                      }
-+                               "Buffer time set as last timestamp - %lld",
-+                               buf->vb.vb2_buf.timestamp);
-               } else {
--                      /* signal frame completion */
--                      vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
--                      complete(&dev->capture.frame_cmplt);
-+                      buf->vb.vb2_buf.timestamp =
-+                              ktime_to_ns(dev->capture.kernel_start_ts);
-+                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                               "Buffer time set as start timestamp - %lld",
-+                               buf->vb.vb2_buf.timestamp);
-               }
-       }
-+      dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-+
-+      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
-+      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-+              buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-+
-+      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+               "Buffer has ts %llu",
-+               dev->capture.last_timestamp);
-+      vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
-+
-+      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
-+          is_capturing(dev)) {
-+              v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                       "Grab another frame as buffer has EOS");
-+              vchiq_mmal_port_parameter_set(instance,
-+                                            dev->capture.camera_port,
-+                                            MMAL_PARAMETER_CAPTURE,
-+                                            &dev->capture.frame_count,
-+                                            sizeof(dev->capture.frame_count));
-+      }
- }
- static int enable_camera(struct bm2835_mmal_dev *dev)
-@@ -815,27 +818,29 @@ static int vidioc_overlay(struct file *f
-       ret = vchiq_mmal_port_set_format(dev->instance, src);
-       if (ret < 0)
--              goto error;
-+              return ret;
-       ret = set_overlay_params(dev, dst);
-       if (ret < 0)
--              goto error;
-+              return ret;
--      if (enable_camera(dev) < 0)
--              goto error;
-+      if (enable_camera(dev) < 0) {
-+              ret = -EINVAL;
-+              return ret;
-+      }
-       ret = vchiq_mmal_component_enable(
-                       dev->instance,
-                       dev->component[MMAL_COMPONENT_PREVIEW]);
-       if (ret < 0)
--              goto error;
-+              return ret;
-       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n",
-                src, dst);
-       ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst);
-       if (!ret)
-               ret = vchiq_mmal_port_enable(dev->instance, src, NULL);
--error:
-+
-       return ret;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0214-staging-bcm2835-camera-Fix-spacing-around-operators.patch b/target/linux/brcm2708/patches-4.19/950-0214-staging-bcm2835-camera-Fix-spacing-around-operators.patch
new file mode 100644 (file)
index 0000000..38bcbbd
--- /dev/null
@@ -0,0 +1,102 @@
+From 54fde7601287891754bef85efbbc9b5648d043f4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 14:13:03 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix spacing around operators
+
+Fix checkpatch warnings over spaces around operators.
+Many were around operations that can be replaced with the
+BIT(x) macro, so replace with that where appropriate.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/controls.c   | 32 +++++++++----------
+ .../vc04_services/bcm2835-camera/mmal-msg.h   |  3 +-
+ .../bcm2835-camera/mmal-parameters.h          | 12 +++----
+ 3 files changed, 24 insertions(+), 23 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -1123,10 +1123,10 @@ static const struct bm2835_mmal_v4l2_ctr
+       {
+               V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               MMAL_CONTROL_TYPE_STD_MENU,
+-              ~((1<<V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
++              ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
++                BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
++                BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
++                BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
+               V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+               V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, 1, NULL,
+               MMAL_PARAMETER_PROFILE,
+@@ -1135,18 +1135,18 @@ static const struct bm2835_mmal_v4l2_ctr
+       },
+       {
+               V4L2_CID_MPEG_VIDEO_H264_LEVEL, MMAL_CONTROL_TYPE_STD_MENU,
+-              ~((1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+-                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
++              ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
++                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
+               V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
+               V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 1, NULL,
+               MMAL_PARAMETER_PROFILE,
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
+@@ -223,7 +223,8 @@ struct mmal_msg_port_action_reply {
+ #define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
+ /* Signals that the current payload contains only complete frames (>1) */
+ #define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
+-      (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
++      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
++       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
+ /* Signals that the current payload is a keyframe (i.e. self decodable) */
+ #define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
+ /*
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
+@@ -23,17 +23,17 @@
+ #define __MMAL_PARAMETERS_H
+ /** Common parameter ID group, used with many types of component. */
+-#define MMAL_PARAMETER_GROUP_COMMON            (0<<16)
++#define MMAL_PARAMETER_GROUP_COMMON            (0 << 16)
+ /** Camera-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CAMERA            (1<<16)
++#define MMAL_PARAMETER_GROUP_CAMERA            (1 << 16)
+ /** Video-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_VIDEO             (2<<16)
++#define MMAL_PARAMETER_GROUP_VIDEO             (2 << 16)
+ /** Audio-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_AUDIO             (3<<16)
++#define MMAL_PARAMETER_GROUP_AUDIO             (3 << 16)
+ /** Clock-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CLOCK             (4<<16)
++#define MMAL_PARAMETER_GROUP_CLOCK             (4 << 16)
+ /** Miracast-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_MIRACAST       (5<<16)
++#define MMAL_PARAMETER_GROUP_MIRACAST       (5 << 16)
+ /* Common parameters */
+ enum mmal_parameter_common_type {
diff --git a/target/linux/brcm2708/patches-4.19/950-0214-staging-bcm2835-camera-Remove-dead-email-addresses.patch b/target/linux/brcm2708/patches-4.19/950-0214-staging-bcm2835-camera-Remove-dead-email-addresses.patch
deleted file mode 100644 (file)
index 2041ebb..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-From b1d4e377b4a8c73396d50c45106f3d3a710b11f5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 10 Mar 2017 17:35:38 +0000
-Subject: [PATCH] staging: bcm2835-camera: Remove dead email addresses
-
-None of the listed author email addresses were valid.
-Keep list of authors and the companies they represented.
-Update my email address.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/bcm2835-camera.c        | 9 +++++----
- .../vc04_services/bcm2835-camera/bcm2835-camera.h        | 9 +++++----
- drivers/staging/vc04_services/bcm2835-camera/controls.c  | 9 +++++----
- .../staging/vc04_services/bcm2835-camera/mmal-common.h   | 9 +++++----
- .../vc04_services/bcm2835-camera/mmal-encodings.h        | 9 +++++----
- .../vc04_services/bcm2835-camera/mmal-msg-common.h       | 9 +++++----
- .../vc04_services/bcm2835-camera/mmal-msg-format.h       | 9 +++++----
- .../staging/vc04_services/bcm2835-camera/mmal-msg-port.h | 9 +++++----
- drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h  | 9 +++++----
- .../vc04_services/bcm2835-camera/mmal-parameters.h       | 9 +++++----
- .../staging/vc04_services/bcm2835-camera/mmal-vchiq.c    | 9 +++++----
- .../staging/vc04_services/bcm2835-camera/mmal-vchiq.h    | 9 +++++----
- 12 files changed, 60 insertions(+), 48 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- #include <linux/errno.h>
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  *
-  * core driver device
-  */
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- #include <linux/errno.h>
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  *
-  * MMAL structures
-  *
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- #ifndef MMAL_ENCODINGS_H
- #define MMAL_ENCODINGS_H
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- #ifndef MMAL_MSG_COMMON_H
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- #ifndef MMAL_MSG_FORMAT_H
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- /* MMAL_PORT_TYPE_T */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- /* all the data structures which serialise the MMAL protocol. note
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  */
- /* common parameters */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  *
-  * V4L2 driver MMAL vchiq interface code
-  */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
-@@ -4,10 +4,11 @@
-  *
-  * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-  *
-- * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
-- *          Dave Stevenson <dsteve@broadcom.com>
-- *          Simon Mellor <simellor@broadcom.com>
-- *          Luke Diamand <luked@broadcom.com>
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-  *
-  * MMAL interface to VCHIQ message passing
-  */
diff --git a/target/linux/brcm2708/patches-4.19/950-0215-staging-bcm2835-camera-Fix-comment-style-violations.patch b/target/linux/brcm2708/patches-4.19/950-0215-staging-bcm2835-camera-Fix-comment-style-violations.patch
deleted file mode 100644 (file)
index 4788eeb..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-From 4fb0df1b29feafacc244ca512b152dd3b96c224c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 13:49:32 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix comment style
- violations.
-
-Fix comment style violations in the header files.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/mmal-msg-format.h          |  95 ++++++------
- .../bcm2835-camera/mmal-msg-port.h            | 124 ++++++++--------
- .../vc04_services/bcm2835-camera/mmal-msg.h   | 135 +++++++++---------
- 3 files changed, 185 insertions(+), 169 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
-@@ -19,22 +19,23 @@
- /* MMAL_ES_FORMAT_T */
- struct mmal_audio_format {
--      u32 channels;           /**< Number of audio channels */
--      u32 sample_rate;        /**< Sample rate */
-+      u32 channels;           /* Number of audio channels */
-+      u32 sample_rate;        /* Sample rate */
--      u32 bits_per_sample;    /**< Bits per sample */
--      u32 block_align;        /**< Size of a block of data */
-+      u32 bits_per_sample;    /* Bits per sample */
-+      u32 block_align;        /* Size of a block of data */
- };
- struct mmal_video_format {
--      u32 width;        /**< Width of frame in pixels */
--      u32 height;       /**< Height of frame in rows of pixels */
--      struct mmal_rect crop;         /**< Visible region of the frame */
--      struct mmal_rational frame_rate;   /**< Frame rate */
--      struct mmal_rational par;          /**< Pixel aspect ratio */
--
--      /* FourCC specifying the color space of the video stream. See the
--       * \ref MmalColorSpace "pre-defined color spaces" for some examples.
-+      u32 width;              /* Width of frame in pixels */
-+      u32 height;             /* Height of frame in rows of pixels */
-+      struct mmal_rect crop;  /* Visible region of the frame */
-+      struct mmal_rational frame_rate;        /* Frame rate */
-+      struct mmal_rational par;               /* Pixel aspect ratio */
-+
-+      /*
-+       * FourCC specifying the color space of the video stream. See the
-+       * MmalColorSpace "pre-defined color spaces" for some examples.
-        */
-       u32 color_space;
- };
-@@ -50,48 +51,56 @@ union mmal_es_specific_format {
-       struct mmal_subpicture_format subpicture;
- };
--/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
-+/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
- struct mmal_es_format_local {
--      u32 type;      /* enum mmal_es_type */
--
--      u32 encoding;  /* FourCC specifying encoding of the elementary stream.*/
--      u32 encoding_variant; /* FourCC specifying the specific
--                             * encoding variant of the elementary
--                             * stream.
--                             */
--
--      union mmal_es_specific_format *es;  /* Type specific
--                                           * information for the
--                                           * elementary stream
--                                           */
-+      u32 type;       /* enum mmal_es_type */
--      u32 bitrate;        /**< Bitrate in bits per second */
--      u32 flags; /**< Flags describing properties of the elementary stream. */
-+      u32 encoding;   /* FourCC specifying encoding of the elementary
-+                       * stream.
-+                       */
-+      u32 encoding_variant;   /* FourCC specifying the specific
-+                               * encoding variant of the elementary
-+                               * stream.
-+                               */
-+
-+      union mmal_es_specific_format *es;      /* Type specific
-+                                               * information for the
-+                                               * elementary stream
-+                                               */
-+
-+      u32 bitrate;    /* Bitrate in bits per second */
-+      u32 flags;      /* Flags describing properties of the elementary
-+                       * stream.
-+                       */
--      u32 extradata_size;       /**< Size of the codec specific data */
--      u8  *extradata;           /**< Codec specific data */
-+      u32 extradata_size;     /* Size of the codec specific data */
-+      u8  *extradata;         /* Codec specific data */
- };
--/** Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
-+/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
- struct mmal_es_format {
--      u32 type;      /* enum mmal_es_type */
-+      u32 type;       /* enum mmal_es_type */
--      u32 encoding;  /* FourCC specifying encoding of the elementary stream.*/
--      u32 encoding_variant; /* FourCC specifying the specific
--                             * encoding variant of the elementary
--                             * stream.
--                             */
-+      u32 encoding;   /* FourCC specifying encoding of the elementary
-+                       * stream.
-+                       */
-+      u32 encoding_variant;   /* FourCC specifying the specific
-+                               * encoding variant of the elementary
-+                               * stream.
-+                               */
--      u32 es; /* Type specific
-+      u32 es; /* Type specific
-                * information for the
-                * elementary stream
-                */
--      u32 bitrate;        /**< Bitrate in bits per second */
--      u32 flags; /**< Flags describing properties of the elementary stream. */
-+      u32 bitrate;    /* Bitrate in bits per second */
-+      u32 flags;      /* Flags describing properties of the elementary
-+                       * stream.
-+                       */
--      u32 extradata_size;       /**< Size of the codec specific data */
--      u32 extradata;           /**< Codec specific data */
-+      u32 extradata_size;     /* Size of the codec specific data */
-+      u32 extradata;          /* Codec specific data */
- };
- #endif /* MMAL_MSG_FORMAT_H */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
-@@ -13,28 +13,31 @@
- /* MMAL_PORT_TYPE_T */
- enum mmal_port_type {
--      MMAL_PORT_TYPE_UNKNOWN = 0,  /**< Unknown port type */
--      MMAL_PORT_TYPE_CONTROL,      /**< Control port */
--      MMAL_PORT_TYPE_INPUT,        /**< Input port */
--      MMAL_PORT_TYPE_OUTPUT,       /**< Output port */
--      MMAL_PORT_TYPE_CLOCK,        /**< Clock port */
-+      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
-+      MMAL_PORT_TYPE_CONTROL,         /* Control port */
-+      MMAL_PORT_TYPE_INPUT,           /* Input port */
-+      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
-+      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
- };
--/** The port is pass-through and doesn't need buffer headers allocated */
-+/* The port is pass-through and doesn't need buffer headers allocated */
- #define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
--/** The port wants to allocate the buffer payloads.
-+/*
-+ *The port wants to allocate the buffer payloads.
-  * This signals a preference that payload allocation should be done
-  * on this port for efficiency reasons.
-  */
- #define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
--/** The port supports format change events.
-+/*
-+ * The port supports format change events.
-  * This applies to input ports and is used to let the client know
-  * whether the port supports being reconfigured via a format
-  * change event (i.e. without having to disable the port).
-  */
- #define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
--/* mmal port structure (MMAL_PORT_T)
-+/*
-+ * mmal port structure (MMAL_PORT_T)
-  *
-  * most elements are informational only, the pointer values for
-  * interogation messages are generally provided as additional
-@@ -42,50 +45,50 @@ enum mmal_port_type {
-  * buffer_num, buffer_size and userdata parameters are writable.
-  */
- struct mmal_port {
--      u32 priv; /* Private member used by the framework */
--      u32 name; /* Port name. Used for debugging purposes (RO) */
-+      u32 priv;       /* Private member used by the framework */
-+      u32 name;       /* Port name. Used for debugging purposes (RO) */
--      u32 type;      /* Type of the port (RO) enum mmal_port_type */
--      u16 index;     /* Index of the port in its type list (RO) */
--      u16 index_all; /* Index of the port in the list of all ports (RO) */
--
--      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
--      u32 format; /* Format of the elementary stream */
--
--      u32 buffer_num_min; /* Minimum number of buffers the port
--                           *   requires (RO).  This is set by the
--                           *   component.
--                           */
--
--      u32 buffer_size_min; /* Minimum size of buffers the port
--                            * requires (RO).  This is set by the
--                            * component.
--                            */
--
--      u32 buffer_alignment_min; /* Minimum alignment requirement for
--                                 * the buffers (RO).  A value of
--                                 * zero means no special alignment
--                                 * requirements.  This is set by the
--                                 * component.
--                                 */
--
--      u32 buffer_num_recommended;  /* Number of buffers the port
--                                    * recommends for optimal
--                                    * performance (RO).  A value of
--                                    * zero means no special
--                                    * recommendation.  This is set
--                                    * by the component.
--                                    */
--
--      u32 buffer_size_recommended; /* Size of buffers the port
--                                    * recommends for optimal
--                                    * performance (RO).  A value of
--                                    * zero means no special
--                                    * recommendation.  This is set
--                                    * by the component.
--                                    */
-+      u32 type;       /* Type of the port (RO) enum mmal_port_type */
-+      u16 index;      /* Index of the port in its type list (RO) */
-+      u16 index_all;  /* Index of the port in the list of all ports (RO) */
-+
-+      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
-+      u32 format;     /* Format of the elementary stream */
-+
-+      u32 buffer_num_min;     /* Minimum number of buffers the port
-+                               *   requires (RO).  This is set by the
-+                               *   component.
-+                               */
-+
-+      u32 buffer_size_min;    /* Minimum size of buffers the port
-+                               * requires (RO).  This is set by the
-+                               * component.
-+                               */
-+
-+      u32 buffer_alignment_min;/* Minimum alignment requirement for
-+                                * the buffers (RO).  A value of
-+                                * zero means no special alignment
-+                                * requirements.  This is set by the
-+                                * component.
-+                                */
-+
-+      u32 buffer_num_recommended;     /* Number of buffers the port
-+                                       * recommends for optimal
-+                                       * performance (RO).  A value of
-+                                       * zero means no special
-+                                       * recommendation.  This is set
-+                                       * by the component.
-+                                       */
-+
-+      u32 buffer_size_recommended;    /* Size of buffers the port
-+                                       * recommends for optimal
-+                                       * performance (RO).  A value of
-+                                       * zero means no special
-+                                       * recommendation.  This is set
-+                                       * by the component.
-+                                       */
--      u32 buffer_num; /* Actual number of buffers the port will use.
-+      u32 buffer_num; /* Actual number of buffers the port will use.
-                        * This is set by the client.
-                        */
-@@ -94,14 +97,13 @@ struct mmal_port {
-                         * the client.
-                         */
--      u32 component; /* Component this port belongs to (Read Only) */
-+      u32 component;  /* Component this port belongs to (Read Only) */
--      u32 userdata; /* Field reserved for use by the client */
--
--      u32 capabilities; /* Flags describing the capabilities of a
--                         * port (RO).  Bitwise combination of \ref
--                         * portcapabilities "Port capabilities"
--                         * values.
--                         */
-+      u32 userdata;   /* Field reserved for use by the client */
-+      u32 capabilities;       /* Flags describing the capabilities of a
-+                               * port (RO).  Bitwise combination of \ref
-+                               * portcapabilities "Port capabilities"
-+                               * values.
-+                               */
- };
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-@@ -11,7 +11,8 @@
-  *          Luke Diamand @ Broadcom
-  */
--/* all the data structures which serialise the MMAL protocol. note
-+/*
-+ * all the data structures which serialise the MMAL protocol. note
-  * these are directly mapped onto the recived message data.
-  *
-  * BEWARE: They seem to *assume* pointers are u32 and that there is no
-@@ -41,51 +42,51 @@ enum mmal_msg_type {
-       MMAL_MSG_TYPE_SERVICE_CLOSED,
-       MMAL_MSG_TYPE_GET_VERSION,
-       MMAL_MSG_TYPE_COMPONENT_CREATE,
--      MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */
-+      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
-       MMAL_MSG_TYPE_COMPONENT_ENABLE,
-       MMAL_MSG_TYPE_COMPONENT_DISABLE,
-       MMAL_MSG_TYPE_PORT_INFO_GET,
-       MMAL_MSG_TYPE_PORT_INFO_SET,
--      MMAL_MSG_TYPE_PORT_ACTION, /* 10 */
-+      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
-       MMAL_MSG_TYPE_BUFFER_FROM_HOST,
-       MMAL_MSG_TYPE_BUFFER_TO_HOST,
-       MMAL_MSG_TYPE_GET_STATS,
-       MMAL_MSG_TYPE_PORT_PARAMETER_SET,
--      MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */
-+      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
-       MMAL_MSG_TYPE_EVENT_TO_HOST,
-       MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
-       MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
-       MMAL_MSG_TYPE_CONSUME_MEM,
--      MMAL_MSG_TYPE_LMK, /* 20 */
-+      MMAL_MSG_TYPE_LMK,                      /* 20 */
-       MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
-       MMAL_MSG_TYPE_DRM_GET_LHS32,
-       MMAL_MSG_TYPE_DRM_GET_TIME,
-       MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
--      MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */
-+      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
-       MMAL_MSG_TYPE_HOST_LOG,
-       MMAL_MSG_TYPE_MSG_LAST
- };
- /* port action request messages differ depending on the action type */
- enum mmal_msg_port_action_type {
--      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,      /* Unknown action */
--      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,           /* Enable a port */
--      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,          /* Disable a port */
--      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,            /* Flush a port */
--      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,          /* Connect ports */
--      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,       /* Disconnect ports */
-+      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
-+      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
-+      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
-+      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
-+      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
-+      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
-       MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
- };
- struct mmal_msg_header {
-       u32 magic;
--      u32 type; /** enum mmal_msg_type */
-+      u32 type;       /* enum mmal_msg_type */
-       /* Opaque handle to the control service */
-       u32 control_service;
--      u32 context; /** a u32 per message context */
--      u32 status; /** The status of the vchiq operation */
-+      u32 context;    /* a u32 per message context */
-+      u32 status;     /* The status of the vchiq operation */
-       u32 padding;
- };
-@@ -99,9 +100,9 @@ struct mmal_msg_version {
- /* request to VC to create component */
- struct mmal_msg_component_create {
--      u32 client_component; /* component context */
-+      u32 client_component;   /* component context */
-       char name[128];
--      u32 pid;                /* For debug */
-+      u32 pid;                /* For debug */
- };
- /* reply from VC to component creation request */
-@@ -121,7 +122,7 @@ struct mmal_msg_component_destroy {
- };
- struct mmal_msg_component_destroy_reply {
--      u32 status; /** The component destruction status */
-+      u32 status; /* The component destruction status */
- };
- /* request and reply to VC to enable a component */
-@@ -130,7 +131,7 @@ struct mmal_msg_component_enable {
- };
- struct mmal_msg_component_enable_reply {
--      u32 status; /** The component enable status */
-+      u32 status; /* The component enable status */
- };
- /* request and reply to VC to disable a component */
-@@ -139,7 +140,7 @@ struct mmal_msg_component_disable {
- };
- struct mmal_msg_component_disable_reply {
--      u32 status; /** The component disable status */
-+      u32 status; /* The component disable status */
- };
- /* request to VC to get port information */
-@@ -151,12 +152,12 @@ struct mmal_msg_port_info_get {
- /* reply from VC to get port info request */
- struct mmal_msg_port_info_get_reply {
--      u32 status; /** enum mmal_msg_status */
--      u32 component_handle;  /* component handle port is associated with */
--      u32 port_type;         /* enum mmal_msg_port_type */
--      u32 port_index;        /* port indexed in query */
--      s32 found;             /* unused */
--      u32 port_handle;               /**< Handle to use for this port */
-+      u32 status;             /* enum mmal_msg_status */
-+      u32 component_handle;   /* component handle port is associated with */
-+      u32 port_type;          /* enum mmal_msg_port_type */
-+      u32 port_index;         /* port indexed in query */
-+      s32 found;              /* unused */
-+      u32 port_handle;        /* Handle to use for this port */
-       struct mmal_port port;
-       struct mmal_es_format format; /* elementary stream format */
-       union mmal_es_specific_format es; /* es type specific data */
-@@ -166,8 +167,8 @@ struct mmal_msg_port_info_get_reply {
- /* request to VC to set port information */
- struct mmal_msg_port_info_set {
-       u32 component_handle;
--      u32 port_type;         /* enum mmal_msg_port_type */
--      u32 port_index;           /* port indexed in query */
-+      u32 port_type;          /* enum mmal_msg_port_type */
-+      u32 port_index;         /* port indexed in query */
-       struct mmal_port port;
-       struct mmal_es_format format;
-       union mmal_es_specific_format es;
-@@ -177,11 +178,11 @@ struct mmal_msg_port_info_set {
- /* reply from VC to port info set request */
- struct mmal_msg_port_info_set_reply {
-       u32 status;
--      u32 component_handle;  /* component handle port is associated with */
--      u32 port_type;         /* enum mmal_msg_port_type */
--      u32 index;             /* port indexed in query */
--      s32 found;             /* unused */
--      u32 port_handle;               /**< Handle to use for this port */
-+      u32 component_handle;   /* component handle port is associated with */
-+      u32 port_type;          /* enum mmal_msg_port_type */
-+      u32 index;              /* port indexed in query */
-+      s32 found;              /* unused */
-+      u32 port_handle;        /* Handle to use for this port */
-       struct mmal_port port;
-       struct mmal_es_format format;
-       union mmal_es_specific_format es;
-@@ -192,7 +193,7 @@ struct mmal_msg_port_info_set_reply {
- struct mmal_msg_port_action_port {
-       u32 component_handle;
-       u32 port_handle;
--      u32 action; /* enum mmal_msg_port_action_type */
-+      u32 action;             /* enum mmal_msg_port_action_type */
-       struct mmal_port port;
- };
-@@ -200,50 +201,53 @@ struct mmal_msg_port_action_port {
- struct mmal_msg_port_action_handle {
-       u32 component_handle;
-       u32 port_handle;
--      u32 action; /* enum mmal_msg_port_action_type */
-+      u32 action;             /* enum mmal_msg_port_action_type */
-       u32 connect_component_handle;
-       u32 connect_port_handle;
- };
- struct mmal_msg_port_action_reply {
--      u32 status; /** The port action operation status */
-+      u32 status;     /* The port action operation status */
- };
- /* MMAL buffer transfer */
--/** Size of space reserved in a buffer message for short messages. */
-+/* Size of space reserved in a buffer message for short messages. */
- #define MMAL_VC_SHORT_DATA 128
--/** Signals that the current payload is the end of the stream of data */
-+/* Signals that the current payload is the end of the stream of data */
- #define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
--/** Signals that the start of the current payload starts a frame */
-+/* Signals that the start of the current payload starts a frame */
- #define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
--/** Signals that the end of the current payload ends a frame */
-+/* Signals that the end of the current payload ends a frame */
- #define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
--/** Signals that the current payload contains only complete frames (>1) */
-+/* Signals that the current payload contains only complete frames (>1) */
- #define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
-       (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
--/** Signals that the current payload is a keyframe (i.e. self decodable) */
-+/* Signals that the current payload is a keyframe (i.e. self decodable) */
- #define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
--/** Signals a discontinuity in the stream of data (e.g. after a seek).
-+/*
-+ * Signals a discontinuity in the stream of data (e.g. after a seek).
-  * Can be used for instance by a decoder to reset its state
-  */
- #define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
--/** Signals a buffer containing some kind of config data for the component
-+/*
-+ * Signals a buffer containing some kind of config data for the component
-  * (e.g. codec config data)
-  */
- #define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
--/** Signals an encrypted payload */
-+/* Signals an encrypted payload */
- #define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
--/** Signals a buffer containing side information */
-+/* Signals a buffer containing side information */
- #define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
--/** Signals a buffer which is the snapshot/postview image from a stills
-+/*
-+ * Signals a buffer which is the snapshot/postview image from a stills
-  * capture
-  */
- #define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
--/** Signals a buffer which contains data known to be corrupted */
-+/* Signals a buffer which contains data known to be corrupted */
- #define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
--/** Signals that a buffer failed to be transmitted */
-+/* Signals that a buffer failed to be transmitted */
- #define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
- struct mmal_driver_buffer {
-@@ -255,8 +259,8 @@ struct mmal_driver_buffer {
- /* buffer header */
- struct mmal_buffer_header {
--      u32 next; /* next header */
--      u32 priv; /* framework private data */
-+      u32 next;       /* next header */
-+      u32 priv;       /* framework private data */
-       u32 cmd;
-       u32 data;
-       u32 alloc_size;
-@@ -281,7 +285,8 @@ struct mmal_buffer_header_type_specific
- };
- struct mmal_msg_buffer_from_host {
--      /* The front 32 bytes of the buffer header are copied
-+      /*
-+       *The front 32 bytes of the buffer header are copied
-        * back to us in the reply to allow for context. This
-        * area is used to store two mmal_driver_buffer structures to
-        * allow for multiple concurrent service users.
-@@ -296,7 +301,7 @@ struct mmal_msg_buffer_from_host {
-       s32 is_zero_copy;
-       s32 has_reference;
--      /** allows short data to be xfered in control message */
-+      /* allows short data to be xfered in control message */
-       u32 payload_in_message;
-       u8 short_data[MMAL_VC_SHORT_DATA];
- };
-@@ -306,10 +311,10 @@ struct mmal_msg_buffer_from_host {
- #define MMAL_WORKER_PORT_PARAMETER_SPACE      96
- struct mmal_msg_port_parameter_set {
--      u32 component_handle; /* component */
--      u32 port_handle;      /* port */
--      u32 id;     /* Parameter ID  */
--      u32 size;      /* Parameter size */
-+      u32 component_handle;   /* component */
-+      u32 port_handle;        /* port */
-+      u32 id;                 /* Parameter ID  */
-+      u32 size;               /* Parameter size */
-       uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
- };
-@@ -322,16 +327,16 @@ struct mmal_msg_port_parameter_set_reply
- /* port parameter getting */
- struct mmal_msg_port_parameter_get {
--      u32 component_handle; /* component */
--      u32 port_handle;      /* port */
--      u32 id;     /* Parameter ID  */
--      u32 size;      /* Parameter size */
-+      u32 component_handle;   /* component */
-+      u32 port_handle;        /* port */
-+      u32 id;                 /* Parameter ID  */
-+      u32 size;               /* Parameter size */
- };
- struct mmal_msg_port_parameter_get_reply {
--      u32 status;           /* Status of mmal_port_parameter_get call */
--      u32 id;     /* Parameter ID  */
--      u32 size;      /* Parameter size */
-+      u32 status;             /* Status of mmal_port_parameter_get call */
-+      u32 id;                 /* Parameter ID  */
-+      u32 size;               /* Parameter size */
-       uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
- };
-@@ -339,7 +344,7 @@ struct mmal_msg_port_parameter_get_reply
- #define MMAL_WORKER_EVENT_SPACE 256
- struct mmal_msg_event_to_host {
--      u32 client_component; /* component context */
-+      u32 client_component;   /* component context */
-       u32 port_type;
-       u32 port_num;
diff --git a/target/linux/brcm2708/patches-4.19/950-0215-staging-bcm2835-camera-Reduce-length-of-enum-names.patch b/target/linux/brcm2708/patches-4.19/950-0215-staging-bcm2835-camera-Reduce-length-of-enum-names.patch
new file mode 100644 (file)
index 0000000..e6d5875
--- /dev/null
@@ -0,0 +1,774 @@
+From 75aca02c1449e3a97ec32de9974ad410f5d34463 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 15:23:35 +0000
+Subject: [PATCH] staging: bcm2835-camera: Reduce length of enum names
+
+We have numerous lines over 80 chars, or oddly split. Many
+of these are due to using long enum names such as
+MMAL_COMPONENT_CAMERA.
+Reduce the length of these enum names.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 165 +++++++++---------
+ .../bcm2835-camera/bcm2835-camera.h           |  20 +--
+ .../vc04_services/bcm2835-camera/controls.c   |  47 +++--
+ 3 files changed, 114 insertions(+), 118 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -80,7 +80,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_I420,
+               .depth = 12,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 1,
+               .remove_padding = 1,
+       }, {
+@@ -89,7 +89,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_YUYV,
+               .depth = 16,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 2,
+               .remove_padding = 0,
+       }, {
+@@ -98,7 +98,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_RGB24,
+               .depth = 24,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 3,
+               .remove_padding = 0,
+       }, {
+@@ -107,7 +107,7 @@ static struct mmal_fmt formats[] = {
+               .flags = V4L2_FMT_FLAG_COMPRESSED,
+               .mmal = MMAL_ENCODING_JPEG,
+               .depth = 8,
+-              .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
++              .mmal_component = COMP_IMAGE_ENCODE,
+               .ybbp = 0,
+               .remove_padding = 0,
+       }, {
+@@ -116,7 +116,7 @@ static struct mmal_fmt formats[] = {
+               .flags = V4L2_FMT_FLAG_COMPRESSED,
+               .mmal = MMAL_ENCODING_H264,
+               .depth = 8,
+-              .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
++              .mmal_component = COMP_VIDEO_ENCODE,
+               .ybbp = 0,
+               .remove_padding = 0,
+       }, {
+@@ -125,7 +125,7 @@ static struct mmal_fmt formats[] = {
+               .flags = V4L2_FMT_FLAG_COMPRESSED,
+               .mmal = MMAL_ENCODING_MJPEG,
+               .depth = 8,
+-              .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
++              .mmal_component = COMP_VIDEO_ENCODE,
+               .ybbp = 0,
+               .remove_padding = 0,
+       }, {
+@@ -134,7 +134,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_YVYU,
+               .depth = 16,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 2,
+               .remove_padding = 0,
+       }, {
+@@ -143,7 +143,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_VYUY,
+               .depth = 16,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 2,
+               .remove_padding = 0,
+       }, {
+@@ -152,7 +152,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_UYVY,
+               .depth = 16,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 2,
+               .remove_padding = 0,
+       }, {
+@@ -161,7 +161,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_NV12,
+               .depth = 12,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 1,
+               .remove_padding = 1,
+       }, {
+@@ -170,7 +170,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_BGR24,
+               .depth = 24,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 3,
+               .remove_padding = 0,
+       }, {
+@@ -179,7 +179,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_YV12,
+               .depth = 12,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 1,
+               .remove_padding = 1,
+       }, {
+@@ -188,7 +188,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_NV21,
+               .depth = 12,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 1,
+               .remove_padding = 1,
+       }, {
+@@ -197,7 +197,7 @@ static struct mmal_fmt formats[] = {
+               .flags = 0,
+               .mmal = MMAL_ENCODING_BGRA,
+               .depth = 32,
+-              .mmal_component = MMAL_COMPONENT_CAMERA,
++              .mmal_component = COMP_CAMERA,
+               .ybbp = 4,
+               .remove_padding = 0,
+       },
+@@ -314,7 +314,7 @@ static inline bool is_capturing(struct b
+ {
+       return dev->capture.camera_port ==
+           &dev->
+-          component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE];
++          component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
+ }
+ static void buffer_cb(struct vchiq_mmal_instance *instance,
+@@ -439,7 +439,7 @@ static int enable_camera(struct bm2835_m
+       if (!dev->camera_use_count) {
+               ret = vchiq_mmal_port_parameter_set(
+                       dev->instance,
+-                      &dev->component[MMAL_COMPONENT_CAMERA]->control,
++                      &dev->component[COMP_CAMERA]->control,
+                       MMAL_PARAMETER_CAMERA_NUM, &dev->camera_num,
+                       sizeof(dev->camera_num));
+               if (ret < 0) {
+@@ -450,7 +450,7 @@ static int enable_camera(struct bm2835_m
+               ret = vchiq_mmal_component_enable(
+                               dev->instance,
+-                              dev->component[MMAL_COMPONENT_CAMERA]);
++                              dev->component[COMP_CAMERA]);
+               if (ret < 0) {
+                       v4l2_err(&dev->v4l2_dev,
+                                "Failed enabling camera, ret %d\n", ret);
+@@ -482,7 +482,7 @@ static int disable_camera(struct bm2835_
+               ret =
+                   vchiq_mmal_component_disable(
+                               dev->instance,
+-                              dev->component[MMAL_COMPONENT_CAMERA]);
++                              dev->component[COMP_CAMERA]);
+               if (ret < 0) {
+                       v4l2_err(&dev->v4l2_dev,
+                                "Failed disabling camera, ret %d\n", ret);
+@@ -490,7 +490,7 @@ static int disable_camera(struct bm2835_
+               }
+               vchiq_mmal_port_parameter_set(
+                       dev->instance,
+-                      &dev->component[MMAL_COMPONENT_CAMERA]->control,
++                      &dev->component[COMP_CAMERA]->control,
+                       MMAL_PARAMETER_CAMERA_NUM, &i,
+                       sizeof(i));
+       }
+@@ -542,7 +542,7 @@ static int start_streaming(struct vb2_qu
+       /* if the preview is not already running, wait for a few frames for AGC
+        * to settle down.
+        */
+-      if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled)
++      if (!dev->component[COMP_PREVIEW]->enabled)
+               msleep(300);
+       /* enable the connection from camera to encoder (if applicable) */
+@@ -775,9 +775,9 @@ static int vidioc_s_fmt_vid_overlay(stru
+       vidioc_try_fmt_vid_overlay(file, priv, f);
+       dev->overlay = f->fmt.win;
+-      if (dev->component[MMAL_COMPONENT_PREVIEW]->enabled) {
++      if (dev->component[COMP_PREVIEW]->enabled) {
+               set_overlay_params(dev,
+-                                 &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
++                                 &dev->component[COMP_PREVIEW]->input[0]);
+       }
+       return 0;
+@@ -790,13 +790,13 @@ static int vidioc_overlay(struct file *f
+       struct vchiq_mmal_port *src;
+       struct vchiq_mmal_port *dst;
+-      if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) ||
+-          (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled))
++      if ((on && dev->component[COMP_PREVIEW]->enabled) ||
++          (!on && !dev->component[COMP_PREVIEW]->enabled))
+               return 0;       /* already in requested state */
+       src =
+-          &dev->component[MMAL_COMPONENT_CAMERA]->
+-          output[MMAL_CAMERA_PORT_PREVIEW];
++          &dev->component[COMP_CAMERA]->
++          output[CAM_PORT_PREVIEW];
+       if (!on) {
+               /* disconnect preview ports and disable component */
+@@ -808,14 +808,14 @@ static int vidioc_overlay(struct file *f
+               if (ret >= 0)
+                       ret = vchiq_mmal_component_disable(
+                                       dev->instance,
+-                                      dev->component[MMAL_COMPONENT_PREVIEW]);
++                                      dev->component[COMP_PREVIEW]);
+               disable_camera(dev);
+               return ret;
+       }
+       /* set preview port format and connect it to output */
+-      dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0];
++      dst = &dev->component[COMP_PREVIEW]->input[0];
+       ret = vchiq_mmal_port_set_format(dev->instance, src);
+       if (ret < 0)
+@@ -832,7 +832,7 @@ static int vidioc_overlay(struct file *f
+       ret = vchiq_mmal_component_enable(
+                       dev->instance,
+-                      dev->component[MMAL_COMPONENT_PREVIEW]);
++                      dev->component[COMP_PREVIEW]);
+       if (ret < 0)
+               return ret;
+@@ -853,8 +853,8 @@ static int vidioc_g_fbuf(struct file *fi
+        */
+       struct bm2835_mmal_dev *dev = video_drvdata(file);
+       struct vchiq_mmal_port *preview_port =
+-                  &dev->component[MMAL_COMPONENT_CAMERA]->
+-                  output[MMAL_CAMERA_PORT_PREVIEW];
++              &dev->component[COMP_CAMERA]->
++              output[CAM_PORT_PREVIEW];
+       a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY |
+                       V4L2_FBUF_CAP_GLOBAL_ALPHA;
+@@ -1057,31 +1057,31 @@ static int mmal_setup_components(struct
+       }
+       /* format dependent port setup */
+       switch (mfmt->mmal_component) {
+-      case MMAL_COMPONENT_CAMERA:
++      case COMP_CAMERA:
+               /* Make a further decision on port based on resolution */
+               if (f->fmt.pix.width <= max_video_width
+                   && f->fmt.pix.height <= max_video_height)
+                       camera_port = port =
+-                          &dev->component[MMAL_COMPONENT_CAMERA]->
+-                          output[MMAL_CAMERA_PORT_VIDEO];
++                          &dev->component[COMP_CAMERA]->
++                          output[CAM_PORT_VIDEO];
+               else
+                       camera_port = port =
+-                          &dev->component[MMAL_COMPONENT_CAMERA]->
+-                          output[MMAL_CAMERA_PORT_CAPTURE];
++                          &dev->component[COMP_CAMERA]->
++                          output[CAM_PORT_CAPTURE];
+               break;
+-      case MMAL_COMPONENT_IMAGE_ENCODE:
+-              encode_component = dev->component[MMAL_COMPONENT_IMAGE_ENCODE];
+-              port = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
++      case COMP_IMAGE_ENCODE:
++              encode_component = dev->component[COMP_IMAGE_ENCODE];
++              port = &dev->component[COMP_IMAGE_ENCODE]->output[0];
+               camera_port =
+-                  &dev->component[MMAL_COMPONENT_CAMERA]->
+-                  output[MMAL_CAMERA_PORT_CAPTURE];
++                  &dev->component[COMP_CAMERA]->
++                  output[CAM_PORT_CAPTURE];
+               break;
+-      case MMAL_COMPONENT_VIDEO_ENCODE:
+-              encode_component = dev->component[MMAL_COMPONENT_VIDEO_ENCODE];
+-              port = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++      case COMP_VIDEO_ENCODE:
++              encode_component = dev->component[COMP_VIDEO_ENCODE];
++              port = &dev->component[COMP_VIDEO_ENCODE]->output[0];
+               camera_port =
+-                  &dev->component[MMAL_COMPONENT_CAMERA]->
+-                  output[MMAL_CAMERA_PORT_VIDEO];
++                  &dev->component[COMP_CAMERA]->
++                  output[CAM_PORT_VIDEO];
+               break;
+       default:
+               break;
+@@ -1123,13 +1123,12 @@ static int mmal_setup_components(struct
+       if (!ret
+           && camera_port ==
+-          &dev->component[MMAL_COMPONENT_CAMERA]->
+-          output[MMAL_CAMERA_PORT_VIDEO]) {
++          &dev->component[COMP_CAMERA]->
++          output[CAM_PORT_VIDEO]) {
+               bool overlay_enabled =
+-                  !!dev->component[MMAL_COMPONENT_PREVIEW]->enabled;
++                  !!dev->component[COMP_PREVIEW]->enabled;
+               struct vchiq_mmal_port *preview_port =
+-                  &dev->component[MMAL_COMPONENT_CAMERA]->
+-                  output[MMAL_CAMERA_PORT_PREVIEW];
++                  &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW];
+               /* Preview and encode ports need to match on resolution */
+               if (overlay_enabled) {
+                       /* Need to disable the overlay before we can update
+@@ -1160,7 +1159,7 @@ static int mmal_setup_components(struct
+                       ret = vchiq_mmal_port_connect_tunnel(
+                               dev->instance,
+                               preview_port,
+-                              &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
++                              &dev->component[COMP_PREVIEW]->input[0]);
+                       if (!ret)
+                               ret = vchiq_mmal_port_enable(dev->instance,
+                                                            preview_port,
+@@ -1214,11 +1213,11 @@ static int mmal_setup_components(struct
+                               port->format.encoding_variant = 0;
+                               /* Set any encoding specific parameters */
+                               switch (mfmt->mmal_component) {
+-                              case MMAL_COMPONENT_VIDEO_ENCODE:
++                              case COMP_VIDEO_ENCODE:
+                                       port->format.bitrate =
+                                           dev->capture.encode_bitrate;
+                                       break;
+-                              case MMAL_COMPONENT_IMAGE_ENCODE:
++                              case COMP_IMAGE_ENCODE:
+                                       /* Could set EXIF parameters here */
+                                       break;
+                               default:
+@@ -1593,14 +1592,14 @@ static int mmal_init(struct bm2835_mmal_
+       /* get the camera component ready */
+       ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
+-                                      &dev->component[MMAL_COMPONENT_CAMERA]);
++                                      &dev->component[COMP_CAMERA]);
+       if (ret < 0)
+               goto unreg_mmal;
+-      camera = dev->component[MMAL_COMPONENT_CAMERA];
+-      if (camera->outputs < MMAL_CAMERA_PORT_COUNT) {
++      camera = dev->component[COMP_CAMERA];
++      if (camera->outputs < CAM_PORT_COUNT) {
+               v4l2_err(&dev->v4l2_dev, "%s: too few camera outputs %d needed %d\n",
+-                       __func__, camera->outputs, MMAL_CAMERA_PORT_COUNT);
++                       __func__, camera->outputs, CAM_PORT_COUNT);
+               ret = -EINVAL;
+               goto unreg_camera;
+       }
+@@ -1622,7 +1621,7 @@ static int mmal_init(struct bm2835_mmal_
+       dev->rgb_bgr_swapped = true;
+       param_size = sizeof(supported_encodings);
+       ret = vchiq_mmal_port_parameter_get(dev->instance,
+-                                          &camera->output[MMAL_CAMERA_PORT_CAPTURE],
++                                          &camera->output[CAM_PORT_CAPTURE],
+                                           MMAL_PARAMETER_SUPPORTED_ENCODINGS,
+                                           &supported_encodings,
+                                           &param_size);
+@@ -1643,7 +1642,7 @@ static int mmal_init(struct bm2835_mmal_
+                       }
+               }
+       }
+-      format = &camera->output[MMAL_CAMERA_PORT_PREVIEW].format;
++      format = &camera->output[CAM_PORT_PREVIEW].format;
+       format->encoding = MMAL_ENCODING_OPAQUE;
+       format->encoding_variant = MMAL_ENCODING_I420;
+@@ -1657,7 +1656,7 @@ static int mmal_init(struct bm2835_mmal_
+       format->es->video.frame_rate.num = 0; /* Rely on fps_range */
+       format->es->video.frame_rate.den = 1;
+-      format = &camera->output[MMAL_CAMERA_PORT_VIDEO].format;
++      format = &camera->output[CAM_PORT_VIDEO].format;
+       format->encoding = MMAL_ENCODING_OPAQUE;
+       format->encoding_variant = MMAL_ENCODING_I420;
+@@ -1671,7 +1670,7 @@ static int mmal_init(struct bm2835_mmal_
+       format->es->video.frame_rate.num = 0; /* Rely on fps_range */
+       format->es->video.frame_rate.den = 1;
+-      format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format;
++      format = &camera->output[CAM_PORT_CAPTURE].format;
+       format->encoding = MMAL_ENCODING_OPAQUE;
+@@ -1695,28 +1694,28 @@ static int mmal_init(struct bm2835_mmal_
+       /* get the preview component ready */
+       ret = vchiq_mmal_component_init(
+                       dev->instance, "ril.video_render",
+-                      &dev->component[MMAL_COMPONENT_PREVIEW]);
++                      &dev->component[COMP_PREVIEW]);
+       if (ret < 0)
+               goto unreg_camera;
+-      if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
++      if (dev->component[COMP_PREVIEW]->inputs < 1) {
+               ret = -EINVAL;
+               v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
+-                       __func__, dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
++                       __func__, dev->component[COMP_PREVIEW]->inputs, 1);
+               goto unreg_preview;
+       }
+       /* get the image encoder component ready */
+       ret = vchiq_mmal_component_init(
+               dev->instance, "ril.image_encode",
+-              &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
++              &dev->component[COMP_IMAGE_ENCODE]);
+       if (ret < 0)
+               goto unreg_preview;
+-      if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
++      if (dev->component[COMP_IMAGE_ENCODE]->inputs < 1) {
+               ret = -EINVAL;
+               v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
+-                       __func__, dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
++                       __func__, dev->component[COMP_IMAGE_ENCODE]->inputs,
+                        1);
+               goto unreg_image_encoder;
+       }
+@@ -1724,21 +1723,21 @@ static int mmal_init(struct bm2835_mmal_
+       /* get the video encoder component ready */
+       ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
+                                       &dev->
+-                                      component[MMAL_COMPONENT_VIDEO_ENCODE]);
++                                      component[COMP_VIDEO_ENCODE]);
+       if (ret < 0)
+               goto unreg_image_encoder;
+-      if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
++      if (dev->component[COMP_VIDEO_ENCODE]->inputs < 1) {
+               ret = -EINVAL;
+               v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
+-                       __func__, dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
++                       __func__, dev->component[COMP_VIDEO_ENCODE]->inputs,
+                        1);
+               goto unreg_vid_encoder;
+       }
+       {
+               struct vchiq_mmal_port *encoder_port =
+-                      &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++                      &dev->component[COMP_VIDEO_ENCODE]->output[0];
+               encoder_port->format.encoding = MMAL_ENCODING_H264;
+               ret = vchiq_mmal_port_set_format(dev->instance,
+                                                encoder_port);
+@@ -1749,12 +1748,12 @@ static int mmal_init(struct bm2835_mmal_
+               vchiq_mmal_port_parameter_set(
+                       dev->instance,
+-                      &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
++                      &dev->component[COMP_VIDEO_ENCODE]->control,
+                       MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
+                       &enable, sizeof(enable));
+               vchiq_mmal_port_parameter_set(dev->instance,
+-                                            &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
++                                            &dev->component[COMP_VIDEO_ENCODE]->control,
+                                             MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
+                                             &enable,
+                                             sizeof(enable));
+@@ -1772,23 +1771,23 @@ unreg_vid_encoder:
+       pr_err("Cleanup: Destroy video encoder\n");
+       vchiq_mmal_component_finalise(
+               dev->instance,
+-              dev->component[MMAL_COMPONENT_VIDEO_ENCODE]);
++              dev->component[COMP_VIDEO_ENCODE]);
+ unreg_image_encoder:
+       pr_err("Cleanup: Destroy image encoder\n");
+       vchiq_mmal_component_finalise(
+               dev->instance,
+-              dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
++              dev->component[COMP_IMAGE_ENCODE]);
+ unreg_preview:
+       pr_err("Cleanup: Destroy video render\n");
+       vchiq_mmal_component_finalise(dev->instance,
+-                                    dev->component[MMAL_COMPONENT_PREVIEW]);
++                                    dev->component[COMP_PREVIEW]);
+ unreg_camera:
+       pr_err("Cleanup: Destroy camera\n");
+       vchiq_mmal_component_finalise(dev->instance,
+-                                    dev->component[MMAL_COMPONENT_CAMERA]);
++                                    dev->component[COMP_CAMERA]);
+ unreg_mmal:
+       vchiq_mmal_finalise(dev->instance);
+@@ -1844,21 +1843,21 @@ static void bcm2835_cleanup_instance(str
+                                            dev->capture.encode_component);
+       }
+       vchiq_mmal_component_disable(dev->instance,
+-                                   dev->component[MMAL_COMPONENT_CAMERA]);
++                                   dev->component[COMP_CAMERA]);
+       vchiq_mmal_component_finalise(dev->instance,
+                                     dev->
+-                                    component[MMAL_COMPONENT_VIDEO_ENCODE]);
++                                    component[COMP_VIDEO_ENCODE]);
+       vchiq_mmal_component_finalise(dev->instance,
+                                     dev->
+-                                    component[MMAL_COMPONENT_IMAGE_ENCODE]);
++                                    component[COMP_IMAGE_ENCODE]);
+       vchiq_mmal_component_finalise(dev->instance,
+-                                    dev->component[MMAL_COMPONENT_PREVIEW]);
++                                    dev->component[COMP_PREVIEW]);
+       vchiq_mmal_component_finalise(dev->instance,
+-                                    dev->component[MMAL_COMPONENT_CAMERA]);
++                                    dev->component[COMP_CAMERA]);
+       v4l2_ctrl_handler_free(&dev->ctrl_handler);
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
+@@ -16,18 +16,18 @@
+ #define V4L2_CTRL_COUNT 29 /* number of v4l controls */
+ enum {
+-      MMAL_COMPONENT_CAMERA = 0,
+-      MMAL_COMPONENT_PREVIEW,
+-      MMAL_COMPONENT_IMAGE_ENCODE,
+-      MMAL_COMPONENT_VIDEO_ENCODE,
+-      MMAL_COMPONENT_COUNT
++      COMP_CAMERA = 0,
++      COMP_PREVIEW,
++      COMP_IMAGE_ENCODE,
++      COMP_VIDEO_ENCODE,
++      COMP_COUNT
+ };
+ enum {
+-      MMAL_CAMERA_PORT_PREVIEW = 0,
+-      MMAL_CAMERA_PORT_VIDEO,
+-      MMAL_CAMERA_PORT_CAPTURE,
+-      MMAL_CAMERA_PORT_COUNT
++      CAM_PORT_PREVIEW = 0,
++      CAM_PORT_VIDEO,
++      CAM_PORT_CAPTURE,
++      CAM_PORT_COUNT
+ };
+ #define PREVIEW_LAYER      2
+@@ -61,7 +61,7 @@ struct bm2835_mmal_dev {
+       /* allocated mmal instance and components */
+       struct vchiq_mmal_instance   *instance;
+-      struct vchiq_mmal_component  *component[MMAL_COMPONENT_COUNT];
++      struct vchiq_mmal_component  *component[COMP_COUNT];
+       int camera_use_count;
+       struct v4l2_window overlay;
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -176,7 +176,7 @@ static int ctrl_set_rational(struct bm28
+       struct mmal_parameter_rational rational_value;
+       struct vchiq_mmal_port *control;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       rational_value.num = ctrl->val;
+       rational_value.den = 100;
+@@ -194,7 +194,7 @@ static int ctrl_set_value(struct bm2835_
+       u32 u32_value;
+       struct vchiq_mmal_port *control;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       u32_value = ctrl->val;
+@@ -219,7 +219,7 @@ static int ctrl_set_iso(struct bm2835_mm
+               dev->manual_iso_enabled =
+                               (ctrl->val == V4L2_ISO_SENSITIVITY_MANUAL);
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       if (dev->manual_iso_enabled)
+               u32_value = dev->iso;
+@@ -238,7 +238,7 @@ static int ctrl_set_value_ev(struct bm28
+       s32 s32_value;
+       struct vchiq_mmal_port *control;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       s32_value = (ctrl->val - 12) * 2;       /* Convert from index to 1/6ths */
+@@ -255,7 +255,7 @@ static int ctrl_set_rotate(struct bm2835
+       u32 u32_value;
+       struct vchiq_mmal_component *camera;
+-      camera = dev->component[MMAL_COMPONENT_CAMERA];
++      camera = dev->component[COMP_CAMERA];
+       u32_value = ((ctrl->val % 360) / 90) * 90;
+@@ -291,7 +291,7 @@ static int ctrl_set_flip(struct bm2835_m
+       else
+               dev->vflip = ctrl->val;
+-      camera = dev->component[MMAL_COMPONENT_CAMERA];
++      camera = dev->component[COMP_CAMERA];
+       if (dev->hflip && dev->vflip)
+               u32_value = MMAL_PARAM_MIRROR_BOTH;
+@@ -330,7 +330,7 @@ static int ctrl_set_exposure(struct bm28
+       struct vchiq_mmal_port *control;
+       int ret = 0;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       if (mmal_ctrl->mmal_id == MMAL_PARAMETER_SHUTTER_SPEED) {
+               /* V4L2 is in 100usec increments.
+@@ -405,7 +405,7 @@ static int ctrl_set_metering_mode(struct
+               struct vchiq_mmal_port *control;
+               u32 u32_value = dev->metering_mode;
+-              control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++              control = &dev->component[COMP_CAMERA]->control;
+               return vchiq_mmal_port_parameter_set(dev->instance, control,
+                                            mmal_ctrl->mmal_id,
+@@ -421,7 +421,7 @@ static int ctrl_set_flicker_avoidance(st
+       u32 u32_value;
+       struct vchiq_mmal_port *control;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       switch (ctrl->val) {
+       case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
+@@ -450,7 +450,7 @@ static int ctrl_set_awb_mode(struct bm28
+       u32 u32_value;
+       struct vchiq_mmal_port *control;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       switch (ctrl->val) {
+       case V4L2_WHITE_BALANCE_MANUAL:
+@@ -506,7 +506,7 @@ static int ctrl_set_awb_gains(struct bm2
+       struct vchiq_mmal_port *control;
+       struct mmal_parameter_awbgains gains;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       if (ctrl->id == V4L2_CID_RED_BALANCE)
+               dev->red_gain = ctrl->val;
+@@ -554,7 +554,7 @@ static int ctrl_set_image_effect(struct
+                                       v4l2_to_mmal_effects_values[i].v;
+                       }
+-                      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++                      control = &dev->component[COMP_CAMERA]->control;
+                       ret = vchiq_mmal_port_parameter_set(
+                                       dev->instance, control,
+@@ -587,7 +587,7 @@ static int ctrl_set_colfx(struct bm2835_
+       int ret = -EINVAL;
+       struct vchiq_mmal_port *control;
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
+       dev->colourfx.enable = ctrl->val & 0xff;
+@@ -613,7 +613,7 @@ static int ctrl_set_bitrate(struct bm283
+       dev->capture.encode_bitrate = ctrl->val;
+-      encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++      encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0];
+       ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
+                                           mmal_ctrl->mmal_id,
+@@ -629,7 +629,7 @@ static int ctrl_set_bitrate_mode(struct
+       u32 bitrate_mode;
+       struct vchiq_mmal_port *encoder_out;
+-      encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++      encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0];
+       dev->capture.encode_bitrate_mode = ctrl->val;
+       switch (ctrl->val) {
+@@ -656,7 +656,7 @@ static int ctrl_set_image_encode_output(
+       u32 u32_value;
+       struct vchiq_mmal_port *jpeg_out;
+-      jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
++      jpeg_out = &dev->component[COMP_IMAGE_ENCODE]->output[0];
+       u32_value = ctrl->val;
+@@ -672,7 +672,7 @@ static int ctrl_set_video_encode_param_o
+       u32 u32_value;
+       struct vchiq_mmal_port *vid_enc_ctl;
+-      vid_enc_ctl = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++      vid_enc_ctl = &dev->component[COMP_VIDEO_ENCODE]->output[0];
+       u32_value = ctrl->val;
+@@ -785,7 +785,7 @@ static int ctrl_set_video_encode_profile
+               }
+               ret = vchiq_mmal_port_parameter_set(dev->instance,
+-                                                  &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0],
++                                                  &dev->component[COMP_VIDEO_ENCODE]->output[0],
+                       mmal_ctrl->mmal_id,
+                       &param, sizeof(param));
+       }
+@@ -803,7 +803,7 @@ static int ctrl_set_scene_mode(struct bm
+       v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                "scene mode selected %d, was %d\n", ctrl->val,
+                dev->scene_mode);
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++      control = &dev->component[COMP_CAMERA]->control;
+       if (ctrl->val == dev->scene_mode)
+               return 0;
+@@ -1221,18 +1221,15 @@ int set_framerate_params(struct bm2835_m
+                fps_range.fps_high.den);
+       ret = vchiq_mmal_port_parameter_set(dev->instance,
+-                                          &dev->component[MMAL_COMPONENT_CAMERA]->
+-                                          output[MMAL_CAMERA_PORT_PREVIEW],
++                                          &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW],
+                                           MMAL_PARAMETER_FPS_RANGE,
+                                           &fps_range, sizeof(fps_range));
+       ret += vchiq_mmal_port_parameter_set(dev->instance,
+-                                           &dev->component[MMAL_COMPONENT_CAMERA]->
+-                                           output[MMAL_CAMERA_PORT_VIDEO],
++                                           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO],
+                                            MMAL_PARAMETER_FPS_RANGE,
+                                            &fps_range, sizeof(fps_range));
+       ret += vchiq_mmal_port_parameter_set(dev->instance,
+-                                           &dev->component[MMAL_COMPONENT_CAMERA]->
+-                                           output[MMAL_CAMERA_PORT_CAPTURE],
++                                           &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE],
+                                            MMAL_PARAMETER_FPS_RANGE,
+                                            &fps_range, sizeof(fps_range));
+       if (ret)
diff --git a/target/linux/brcm2708/patches-4.19/950-0216-staging-bcm2835-camera-Fix-multiple-line-dereference.patch b/target/linux/brcm2708/patches-4.19/950-0216-staging-bcm2835-camera-Fix-multiple-line-dereference.patch
new file mode 100644 (file)
index 0000000..7797510
--- /dev/null
@@ -0,0 +1,133 @@
+From 2730c4538b6edbe1e9d4071a8a64aa62f655eeaa Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 15:28:07 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix multiple line
+ dereference errors
+
+Fix checkpatch errors "Avoid multiple line dereference"
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 41 +++++++------------
+ 1 file changed, 14 insertions(+), 27 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -313,8 +313,7 @@ static void buffer_cleanup(struct vb2_bu
+ static inline bool is_capturing(struct bm2835_mmal_dev *dev)
+ {
+       return dev->capture.camera_port ==
+-          &dev->
+-          component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
++          &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
+ }
+ static void buffer_cb(struct vchiq_mmal_instance *instance,
+@@ -795,8 +794,7 @@ static int vidioc_overlay(struct file *f
+               return 0;       /* already in requested state */
+       src =
+-          &dev->component[COMP_CAMERA]->
+-          output[CAM_PORT_PREVIEW];
++          &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW];
+       if (!on) {
+               /* disconnect preview ports and disable component */
+@@ -853,8 +851,7 @@ static int vidioc_g_fbuf(struct file *fi
+        */
+       struct bm2835_mmal_dev *dev = video_drvdata(file);
+       struct vchiq_mmal_port *preview_port =
+-              &dev->component[COMP_CAMERA]->
+-              output[CAM_PORT_PREVIEW];
++              &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW];
+       a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY |
+                       V4L2_FBUF_CAP_GLOBAL_ALPHA;
+@@ -1046,8 +1043,7 @@ static int mmal_setup_components(struct
+                                              dev->capture.camera_port, NULL);
+               dev->capture.camera_port = NULL;
+               ret = vchiq_mmal_component_disable(dev->instance,
+-                                                 dev->capture.
+-                                                 encode_component);
++                                                 dev->capture.encode_component);
+               if (ret)
+                       v4l2_err(&dev->v4l2_dev,
+                                "Failed to disable encode component %d\n",
+@@ -1062,26 +1058,22 @@ static int mmal_setup_components(struct
+               if (f->fmt.pix.width <= max_video_width
+                   && f->fmt.pix.height <= max_video_height)
+                       camera_port = port =
+-                          &dev->component[COMP_CAMERA]->
+-                          output[CAM_PORT_VIDEO];
++                          &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
+               else
+                       camera_port = port =
+-                          &dev->component[COMP_CAMERA]->
+-                          output[CAM_PORT_CAPTURE];
++                          &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
+               break;
+       case COMP_IMAGE_ENCODE:
+               encode_component = dev->component[COMP_IMAGE_ENCODE];
+               port = &dev->component[COMP_IMAGE_ENCODE]->output[0];
+               camera_port =
+-                  &dev->component[COMP_CAMERA]->
+-                  output[CAM_PORT_CAPTURE];
++                  &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
+               break;
+       case COMP_VIDEO_ENCODE:
+               encode_component = dev->component[COMP_VIDEO_ENCODE];
+               port = &dev->component[COMP_VIDEO_ENCODE]->output[0];
+               camera_port =
+-                  &dev->component[COMP_CAMERA]->
+-                  output[CAM_PORT_VIDEO];
++                  &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
+               break;
+       default:
+               break;
+@@ -1123,8 +1115,7 @@ static int mmal_setup_components(struct
+       if (!ret
+           && camera_port ==
+-          &dev->component[COMP_CAMERA]->
+-          output[CAM_PORT_VIDEO]) {
++          &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]) {
+               bool overlay_enabled =
+                   !!dev->component[COMP_PREVIEW]->enabled;
+               struct vchiq_mmal_port *preview_port =
+@@ -1261,9 +1252,8 @@ static int mmal_setup_components(struct
+                                                port->current_buffer.size);
+                                       port->current_buffer.size =
+                                           (f->fmt.pix.sizeimage <
+-                                           (100 << 10))
+-                                          ? (100 << 10)
+-                                          : f->fmt.pix.sizeimage;
++                                           (100 << 10)) ?
++                                          (100 << 10) : f->fmt.pix.sizeimage;
+                               }
+                               v4l2_dbg(1, bcm2835_v4l2_debug,
+                                        &dev->v4l2_dev,
+@@ -1722,8 +1712,7 @@ static int mmal_init(struct bm2835_mmal_
+       /* get the video encoder component ready */
+       ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
+-                                      &dev->
+-                                      component[COMP_VIDEO_ENCODE]);
++                                      &dev->component[COMP_VIDEO_ENCODE]);
+       if (ret < 0)
+               goto unreg_image_encoder;
+@@ -1846,12 +1835,10 @@ static void bcm2835_cleanup_instance(str
+                                    dev->component[COMP_CAMERA]);
+       vchiq_mmal_component_finalise(dev->instance,
+-                                    dev->
+-                                    component[COMP_VIDEO_ENCODE]);
++                                    dev->component[COMP_VIDEO_ENCODE]);
+       vchiq_mmal_component_finalise(dev->instance,
+-                                    dev->
+-                                    component[COMP_IMAGE_ENCODE]);
++                                    dev->component[COMP_IMAGE_ENCODE]);
+       vchiq_mmal_component_finalise(dev->instance,
+                                     dev->component[COMP_PREVIEW]);
diff --git a/target/linux/brcm2708/patches-4.19/950-0216-staging-bcm2835-camera-Fix-spacing-around-operators.patch b/target/linux/brcm2708/patches-4.19/950-0216-staging-bcm2835-camera-Fix-spacing-around-operators.patch
deleted file mode 100644 (file)
index 38bcbbd..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From 54fde7601287891754bef85efbbc9b5648d043f4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 14:13:03 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix spacing around operators
-
-Fix checkpatch warnings over spaces around operators.
-Many were around operations that can be replaced with the
-BIT(x) macro, so replace with that where appropriate.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/controls.c   | 32 +++++++++----------
- .../vc04_services/bcm2835-camera/mmal-msg.h   |  3 +-
- .../bcm2835-camera/mmal-parameters.h          | 12 +++----
- 3 files changed, 24 insertions(+), 23 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -1123,10 +1123,10 @@ static const struct bm2835_mmal_v4l2_ctr
-       {
-               V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-               MMAL_CONTROL_TYPE_STD_MENU,
--              ~((1<<V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
--                      (1<<V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
--                      (1<<V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
--                      (1<<V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
-+              ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
-+                BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
-+                BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
-+                BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
-               V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
-               V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, 1, NULL,
-               MMAL_PARAMETER_PROFILE,
-@@ -1135,18 +1135,18 @@ static const struct bm2835_mmal_v4l2_ctr
-       },
-       {
-               V4L2_CID_MPEG_VIDEO_H264_LEVEL, MMAL_CONTROL_TYPE_STD_MENU,
--              ~((1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
--                      (1<<V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
-+              ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
-+                BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
-               V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
-               V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 1, NULL,
-               MMAL_PARAMETER_PROFILE,
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-@@ -223,7 +223,8 @@ struct mmal_msg_port_action_reply {
- #define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
- /* Signals that the current payload contains only complete frames (>1) */
- #define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
--      (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
-+      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
-+       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
- /* Signals that the current payload is a keyframe (i.e. self decodable) */
- #define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
- /*
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-@@ -23,17 +23,17 @@
- #define __MMAL_PARAMETERS_H
- /** Common parameter ID group, used with many types of component. */
--#define MMAL_PARAMETER_GROUP_COMMON            (0<<16)
-+#define MMAL_PARAMETER_GROUP_COMMON            (0 << 16)
- /** Camera-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CAMERA            (1<<16)
-+#define MMAL_PARAMETER_GROUP_CAMERA            (1 << 16)
- /** Video-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_VIDEO             (2<<16)
-+#define MMAL_PARAMETER_GROUP_VIDEO             (2 << 16)
- /** Audio-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_AUDIO             (3<<16)
-+#define MMAL_PARAMETER_GROUP_AUDIO             (3 << 16)
- /** Clock-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CLOCK             (4<<16)
-+#define MMAL_PARAMETER_GROUP_CLOCK             (4 << 16)
- /** Miracast-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_MIRACAST       (5<<16)
-+#define MMAL_PARAMETER_GROUP_MIRACAST       (5 << 16)
- /* Common parameters */
- enum mmal_parameter_common_type {
diff --git a/target/linux/brcm2708/patches-4.19/950-0217-staging-bcm2835-camera-Fix-brace-style-issues.patch b/target/linux/brcm2708/patches-4.19/950-0217-staging-bcm2835-camera-Fix-brace-style-issues.patch
new file mode 100644 (file)
index 0000000..6aa8e93
--- /dev/null
@@ -0,0 +1,56 @@
+From a023ee926b7e923058203e82edc5405c1e82842c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 15:37:11 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix brace style issues.
+
+Fix mismatched or missing brace issues flagged by checkpatch.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 3 ++-
+ drivers/staging/vc04_services/bcm2835-camera/controls.c       | 3 ++-
+ drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c     | 3 ++-
+ 3 files changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -569,10 +569,11 @@ static int start_streaming(struct vb2_qu
+               /* Flag to indicate just to rely on kernel timestamps */
+               dev->capture.vc_start_timestamp = -1;
+-      } else
++      } else {
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                        "Start time %lld size %d\n",
+                        dev->capture.vc_start_timestamp, parameter_size);
++      }
+       dev->capture.kernel_start_ts = ktime_get();
+       dev->capture.last_timestamp = 0;
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -410,8 +410,9 @@ static int ctrl_set_metering_mode(struct
+               return vchiq_mmal_port_parameter_set(dev->instance, control,
+                                            mmal_ctrl->mmal_id,
+                                            &u32_value, sizeof(u32_value));
+-      } else
++      } else {
+               return 0;
++      }
+ }
+ static int ctrl_set_flicker_avoidance(struct bm2835_mmal_dev *dev,
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -1268,9 +1268,10 @@ static int port_parameter_get(struct vch
+               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+                      *value_size);
+               *value_size = rmsg->u.port_parameter_get_reply.size;
+-      } else
++      } else {
+               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+                      rmsg->u.port_parameter_get_reply.size);
++      }
+       pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
+                ret, port->component->handle, port->handle, parameter_id);
diff --git a/target/linux/brcm2708/patches-4.19/950-0217-staging-bcm2835-camera-Reduce-length-of-enum-names.patch b/target/linux/brcm2708/patches-4.19/950-0217-staging-bcm2835-camera-Reduce-length-of-enum-names.patch
deleted file mode 100644 (file)
index e6d5875..0000000
+++ /dev/null
@@ -1,774 +0,0 @@
-From 75aca02c1449e3a97ec32de9974ad410f5d34463 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 15:23:35 +0000
-Subject: [PATCH] staging: bcm2835-camera: Reduce length of enum names
-
-We have numerous lines over 80 chars, or oddly split. Many
-of these are due to using long enum names such as
-MMAL_COMPONENT_CAMERA.
-Reduce the length of these enum names.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c           | 165 +++++++++---------
- .../bcm2835-camera/bcm2835-camera.h           |  20 +--
- .../vc04_services/bcm2835-camera/controls.c   |  47 +++--
- 3 files changed, 114 insertions(+), 118 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -80,7 +80,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_I420,
-               .depth = 12,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 1,
-               .remove_padding = 1,
-       }, {
-@@ -89,7 +89,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_YUYV,
-               .depth = 16,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 2,
-               .remove_padding = 0,
-       }, {
-@@ -98,7 +98,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_RGB24,
-               .depth = 24,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 3,
-               .remove_padding = 0,
-       }, {
-@@ -107,7 +107,7 @@ static struct mmal_fmt formats[] = {
-               .flags = V4L2_FMT_FLAG_COMPRESSED,
-               .mmal = MMAL_ENCODING_JPEG,
-               .depth = 8,
--              .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
-+              .mmal_component = COMP_IMAGE_ENCODE,
-               .ybbp = 0,
-               .remove_padding = 0,
-       }, {
-@@ -116,7 +116,7 @@ static struct mmal_fmt formats[] = {
-               .flags = V4L2_FMT_FLAG_COMPRESSED,
-               .mmal = MMAL_ENCODING_H264,
-               .depth = 8,
--              .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
-+              .mmal_component = COMP_VIDEO_ENCODE,
-               .ybbp = 0,
-               .remove_padding = 0,
-       }, {
-@@ -125,7 +125,7 @@ static struct mmal_fmt formats[] = {
-               .flags = V4L2_FMT_FLAG_COMPRESSED,
-               .mmal = MMAL_ENCODING_MJPEG,
-               .depth = 8,
--              .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
-+              .mmal_component = COMP_VIDEO_ENCODE,
-               .ybbp = 0,
-               .remove_padding = 0,
-       }, {
-@@ -134,7 +134,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_YVYU,
-               .depth = 16,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 2,
-               .remove_padding = 0,
-       }, {
-@@ -143,7 +143,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_VYUY,
-               .depth = 16,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 2,
-               .remove_padding = 0,
-       }, {
-@@ -152,7 +152,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_UYVY,
-               .depth = 16,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 2,
-               .remove_padding = 0,
-       }, {
-@@ -161,7 +161,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_NV12,
-               .depth = 12,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 1,
-               .remove_padding = 1,
-       }, {
-@@ -170,7 +170,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_BGR24,
-               .depth = 24,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 3,
-               .remove_padding = 0,
-       }, {
-@@ -179,7 +179,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_YV12,
-               .depth = 12,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 1,
-               .remove_padding = 1,
-       }, {
-@@ -188,7 +188,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_NV21,
-               .depth = 12,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 1,
-               .remove_padding = 1,
-       }, {
-@@ -197,7 +197,7 @@ static struct mmal_fmt formats[] = {
-               .flags = 0,
-               .mmal = MMAL_ENCODING_BGRA,
-               .depth = 32,
--              .mmal_component = MMAL_COMPONENT_CAMERA,
-+              .mmal_component = COMP_CAMERA,
-               .ybbp = 4,
-               .remove_padding = 0,
-       },
-@@ -314,7 +314,7 @@ static inline bool is_capturing(struct b
- {
-       return dev->capture.camera_port ==
-           &dev->
--          component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE];
-+          component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
- }
- static void buffer_cb(struct vchiq_mmal_instance *instance,
-@@ -439,7 +439,7 @@ static int enable_camera(struct bm2835_m
-       if (!dev->camera_use_count) {
-               ret = vchiq_mmal_port_parameter_set(
-                       dev->instance,
--                      &dev->component[MMAL_COMPONENT_CAMERA]->control,
-+                      &dev->component[COMP_CAMERA]->control,
-                       MMAL_PARAMETER_CAMERA_NUM, &dev->camera_num,
-                       sizeof(dev->camera_num));
-               if (ret < 0) {
-@@ -450,7 +450,7 @@ static int enable_camera(struct bm2835_m
-               ret = vchiq_mmal_component_enable(
-                               dev->instance,
--                              dev->component[MMAL_COMPONENT_CAMERA]);
-+                              dev->component[COMP_CAMERA]);
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "Failed enabling camera, ret %d\n", ret);
-@@ -482,7 +482,7 @@ static int disable_camera(struct bm2835_
-               ret =
-                   vchiq_mmal_component_disable(
-                               dev->instance,
--                              dev->component[MMAL_COMPONENT_CAMERA]);
-+                              dev->component[COMP_CAMERA]);
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "Failed disabling camera, ret %d\n", ret);
-@@ -490,7 +490,7 @@ static int disable_camera(struct bm2835_
-               }
-               vchiq_mmal_port_parameter_set(
-                       dev->instance,
--                      &dev->component[MMAL_COMPONENT_CAMERA]->control,
-+                      &dev->component[COMP_CAMERA]->control,
-                       MMAL_PARAMETER_CAMERA_NUM, &i,
-                       sizeof(i));
-       }
-@@ -542,7 +542,7 @@ static int start_streaming(struct vb2_qu
-       /* if the preview is not already running, wait for a few frames for AGC
-        * to settle down.
-        */
--      if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled)
-+      if (!dev->component[COMP_PREVIEW]->enabled)
-               msleep(300);
-       /* enable the connection from camera to encoder (if applicable) */
-@@ -775,9 +775,9 @@ static int vidioc_s_fmt_vid_overlay(stru
-       vidioc_try_fmt_vid_overlay(file, priv, f);
-       dev->overlay = f->fmt.win;
--      if (dev->component[MMAL_COMPONENT_PREVIEW]->enabled) {
-+      if (dev->component[COMP_PREVIEW]->enabled) {
-               set_overlay_params(dev,
--                                 &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
-+                                 &dev->component[COMP_PREVIEW]->input[0]);
-       }
-       return 0;
-@@ -790,13 +790,13 @@ static int vidioc_overlay(struct file *f
-       struct vchiq_mmal_port *src;
-       struct vchiq_mmal_port *dst;
--      if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) ||
--          (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled))
-+      if ((on && dev->component[COMP_PREVIEW]->enabled) ||
-+          (!on && !dev->component[COMP_PREVIEW]->enabled))
-               return 0;       /* already in requested state */
-       src =
--          &dev->component[MMAL_COMPONENT_CAMERA]->
--          output[MMAL_CAMERA_PORT_PREVIEW];
-+          &dev->component[COMP_CAMERA]->
-+          output[CAM_PORT_PREVIEW];
-       if (!on) {
-               /* disconnect preview ports and disable component */
-@@ -808,14 +808,14 @@ static int vidioc_overlay(struct file *f
-               if (ret >= 0)
-                       ret = vchiq_mmal_component_disable(
-                                       dev->instance,
--                                      dev->component[MMAL_COMPONENT_PREVIEW]);
-+                                      dev->component[COMP_PREVIEW]);
-               disable_camera(dev);
-               return ret;
-       }
-       /* set preview port format and connect it to output */
--      dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0];
-+      dst = &dev->component[COMP_PREVIEW]->input[0];
-       ret = vchiq_mmal_port_set_format(dev->instance, src);
-       if (ret < 0)
-@@ -832,7 +832,7 @@ static int vidioc_overlay(struct file *f
-       ret = vchiq_mmal_component_enable(
-                       dev->instance,
--                      dev->component[MMAL_COMPONENT_PREVIEW]);
-+                      dev->component[COMP_PREVIEW]);
-       if (ret < 0)
-               return ret;
-@@ -853,8 +853,8 @@ static int vidioc_g_fbuf(struct file *fi
-        */
-       struct bm2835_mmal_dev *dev = video_drvdata(file);
-       struct vchiq_mmal_port *preview_port =
--                  &dev->component[MMAL_COMPONENT_CAMERA]->
--                  output[MMAL_CAMERA_PORT_PREVIEW];
-+              &dev->component[COMP_CAMERA]->
-+              output[CAM_PORT_PREVIEW];
-       a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY |
-                       V4L2_FBUF_CAP_GLOBAL_ALPHA;
-@@ -1057,31 +1057,31 @@ static int mmal_setup_components(struct
-       }
-       /* format dependent port setup */
-       switch (mfmt->mmal_component) {
--      case MMAL_COMPONENT_CAMERA:
-+      case COMP_CAMERA:
-               /* Make a further decision on port based on resolution */
-               if (f->fmt.pix.width <= max_video_width
-                   && f->fmt.pix.height <= max_video_height)
-                       camera_port = port =
--                          &dev->component[MMAL_COMPONENT_CAMERA]->
--                          output[MMAL_CAMERA_PORT_VIDEO];
-+                          &dev->component[COMP_CAMERA]->
-+                          output[CAM_PORT_VIDEO];
-               else
-                       camera_port = port =
--                          &dev->component[MMAL_COMPONENT_CAMERA]->
--                          output[MMAL_CAMERA_PORT_CAPTURE];
-+                          &dev->component[COMP_CAMERA]->
-+                          output[CAM_PORT_CAPTURE];
-               break;
--      case MMAL_COMPONENT_IMAGE_ENCODE:
--              encode_component = dev->component[MMAL_COMPONENT_IMAGE_ENCODE];
--              port = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
-+      case COMP_IMAGE_ENCODE:
-+              encode_component = dev->component[COMP_IMAGE_ENCODE];
-+              port = &dev->component[COMP_IMAGE_ENCODE]->output[0];
-               camera_port =
--                  &dev->component[MMAL_COMPONENT_CAMERA]->
--                  output[MMAL_CAMERA_PORT_CAPTURE];
-+                  &dev->component[COMP_CAMERA]->
-+                  output[CAM_PORT_CAPTURE];
-               break;
--      case MMAL_COMPONENT_VIDEO_ENCODE:
--              encode_component = dev->component[MMAL_COMPONENT_VIDEO_ENCODE];
--              port = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
-+      case COMP_VIDEO_ENCODE:
-+              encode_component = dev->component[COMP_VIDEO_ENCODE];
-+              port = &dev->component[COMP_VIDEO_ENCODE]->output[0];
-               camera_port =
--                  &dev->component[MMAL_COMPONENT_CAMERA]->
--                  output[MMAL_CAMERA_PORT_VIDEO];
-+                  &dev->component[COMP_CAMERA]->
-+                  output[CAM_PORT_VIDEO];
-               break;
-       default:
-               break;
-@@ -1123,13 +1123,12 @@ static int mmal_setup_components(struct
-       if (!ret
-           && camera_port ==
--          &dev->component[MMAL_COMPONENT_CAMERA]->
--          output[MMAL_CAMERA_PORT_VIDEO]) {
-+          &dev->component[COMP_CAMERA]->
-+          output[CAM_PORT_VIDEO]) {
-               bool overlay_enabled =
--                  !!dev->component[MMAL_COMPONENT_PREVIEW]->enabled;
-+                  !!dev->component[COMP_PREVIEW]->enabled;
-               struct vchiq_mmal_port *preview_port =
--                  &dev->component[MMAL_COMPONENT_CAMERA]->
--                  output[MMAL_CAMERA_PORT_PREVIEW];
-+                  &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW];
-               /* Preview and encode ports need to match on resolution */
-               if (overlay_enabled) {
-                       /* Need to disable the overlay before we can update
-@@ -1160,7 +1159,7 @@ static int mmal_setup_components(struct
-                       ret = vchiq_mmal_port_connect_tunnel(
-                               dev->instance,
-                               preview_port,
--                              &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
-+                              &dev->component[COMP_PREVIEW]->input[0]);
-                       if (!ret)
-                               ret = vchiq_mmal_port_enable(dev->instance,
-                                                            preview_port,
-@@ -1214,11 +1213,11 @@ static int mmal_setup_components(struct
-                               port->format.encoding_variant = 0;
-                               /* Set any encoding specific parameters */
-                               switch (mfmt->mmal_component) {
--                              case MMAL_COMPONENT_VIDEO_ENCODE:
-+                              case COMP_VIDEO_ENCODE:
-                                       port->format.bitrate =
-                                           dev->capture.encode_bitrate;
-                                       break;
--                              case MMAL_COMPONENT_IMAGE_ENCODE:
-+                              case COMP_IMAGE_ENCODE:
-                                       /* Could set EXIF parameters here */
-                                       break;
-                               default:
-@@ -1593,14 +1592,14 @@ static int mmal_init(struct bm2835_mmal_
-       /* get the camera component ready */
-       ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
--                                      &dev->component[MMAL_COMPONENT_CAMERA]);
-+                                      &dev->component[COMP_CAMERA]);
-       if (ret < 0)
-               goto unreg_mmal;
--      camera = dev->component[MMAL_COMPONENT_CAMERA];
--      if (camera->outputs < MMAL_CAMERA_PORT_COUNT) {
-+      camera = dev->component[COMP_CAMERA];
-+      if (camera->outputs < CAM_PORT_COUNT) {
-               v4l2_err(&dev->v4l2_dev, "%s: too few camera outputs %d needed %d\n",
--                       __func__, camera->outputs, MMAL_CAMERA_PORT_COUNT);
-+                       __func__, camera->outputs, CAM_PORT_COUNT);
-               ret = -EINVAL;
-               goto unreg_camera;
-       }
-@@ -1622,7 +1621,7 @@ static int mmal_init(struct bm2835_mmal_
-       dev->rgb_bgr_swapped = true;
-       param_size = sizeof(supported_encodings);
-       ret = vchiq_mmal_port_parameter_get(dev->instance,
--                                          &camera->output[MMAL_CAMERA_PORT_CAPTURE],
-+                                          &camera->output[CAM_PORT_CAPTURE],
-                                           MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-                                           &supported_encodings,
-                                           &param_size);
-@@ -1643,7 +1642,7 @@ static int mmal_init(struct bm2835_mmal_
-                       }
-               }
-       }
--      format = &camera->output[MMAL_CAMERA_PORT_PREVIEW].format;
-+      format = &camera->output[CAM_PORT_PREVIEW].format;
-       format->encoding = MMAL_ENCODING_OPAQUE;
-       format->encoding_variant = MMAL_ENCODING_I420;
-@@ -1657,7 +1656,7 @@ static int mmal_init(struct bm2835_mmal_
-       format->es->video.frame_rate.num = 0; /* Rely on fps_range */
-       format->es->video.frame_rate.den = 1;
--      format = &camera->output[MMAL_CAMERA_PORT_VIDEO].format;
-+      format = &camera->output[CAM_PORT_VIDEO].format;
-       format->encoding = MMAL_ENCODING_OPAQUE;
-       format->encoding_variant = MMAL_ENCODING_I420;
-@@ -1671,7 +1670,7 @@ static int mmal_init(struct bm2835_mmal_
-       format->es->video.frame_rate.num = 0; /* Rely on fps_range */
-       format->es->video.frame_rate.den = 1;
--      format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format;
-+      format = &camera->output[CAM_PORT_CAPTURE].format;
-       format->encoding = MMAL_ENCODING_OPAQUE;
-@@ -1695,28 +1694,28 @@ static int mmal_init(struct bm2835_mmal_
-       /* get the preview component ready */
-       ret = vchiq_mmal_component_init(
-                       dev->instance, "ril.video_render",
--                      &dev->component[MMAL_COMPONENT_PREVIEW]);
-+                      &dev->component[COMP_PREVIEW]);
-       if (ret < 0)
-               goto unreg_camera;
--      if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
-+      if (dev->component[COMP_PREVIEW]->inputs < 1) {
-               ret = -EINVAL;
-               v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
--                       __func__, dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
-+                       __func__, dev->component[COMP_PREVIEW]->inputs, 1);
-               goto unreg_preview;
-       }
-       /* get the image encoder component ready */
-       ret = vchiq_mmal_component_init(
-               dev->instance, "ril.image_encode",
--              &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
-+              &dev->component[COMP_IMAGE_ENCODE]);
-       if (ret < 0)
-               goto unreg_preview;
--      if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
-+      if (dev->component[COMP_IMAGE_ENCODE]->inputs < 1) {
-               ret = -EINVAL;
-               v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
--                       __func__, dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
-+                       __func__, dev->component[COMP_IMAGE_ENCODE]->inputs,
-                        1);
-               goto unreg_image_encoder;
-       }
-@@ -1724,21 +1723,21 @@ static int mmal_init(struct bm2835_mmal_
-       /* get the video encoder component ready */
-       ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
-                                       &dev->
--                                      component[MMAL_COMPONENT_VIDEO_ENCODE]);
-+                                      component[COMP_VIDEO_ENCODE]);
-       if (ret < 0)
-               goto unreg_image_encoder;
--      if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
-+      if (dev->component[COMP_VIDEO_ENCODE]->inputs < 1) {
-               ret = -EINVAL;
-               v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n",
--                       __func__, dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
-+                       __func__, dev->component[COMP_VIDEO_ENCODE]->inputs,
-                        1);
-               goto unreg_vid_encoder;
-       }
-       {
-               struct vchiq_mmal_port *encoder_port =
--                      &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
-+                      &dev->component[COMP_VIDEO_ENCODE]->output[0];
-               encoder_port->format.encoding = MMAL_ENCODING_H264;
-               ret = vchiq_mmal_port_set_format(dev->instance,
-                                                encoder_port);
-@@ -1749,12 +1748,12 @@ static int mmal_init(struct bm2835_mmal_
-               vchiq_mmal_port_parameter_set(
-                       dev->instance,
--                      &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
-+                      &dev->component[COMP_VIDEO_ENCODE]->control,
-                       MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
-                       &enable, sizeof(enable));
-               vchiq_mmal_port_parameter_set(dev->instance,
--                                            &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
-+                                            &dev->component[COMP_VIDEO_ENCODE]->control,
-                                             MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
-                                             &enable,
-                                             sizeof(enable));
-@@ -1772,23 +1771,23 @@ unreg_vid_encoder:
-       pr_err("Cleanup: Destroy video encoder\n");
-       vchiq_mmal_component_finalise(
-               dev->instance,
--              dev->component[MMAL_COMPONENT_VIDEO_ENCODE]);
-+              dev->component[COMP_VIDEO_ENCODE]);
- unreg_image_encoder:
-       pr_err("Cleanup: Destroy image encoder\n");
-       vchiq_mmal_component_finalise(
-               dev->instance,
--              dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
-+              dev->component[COMP_IMAGE_ENCODE]);
- unreg_preview:
-       pr_err("Cleanup: Destroy video render\n");
-       vchiq_mmal_component_finalise(dev->instance,
--                                    dev->component[MMAL_COMPONENT_PREVIEW]);
-+                                    dev->component[COMP_PREVIEW]);
- unreg_camera:
-       pr_err("Cleanup: Destroy camera\n");
-       vchiq_mmal_component_finalise(dev->instance,
--                                    dev->component[MMAL_COMPONENT_CAMERA]);
-+                                    dev->component[COMP_CAMERA]);
- unreg_mmal:
-       vchiq_mmal_finalise(dev->instance);
-@@ -1844,21 +1843,21 @@ static void bcm2835_cleanup_instance(str
-                                            dev->capture.encode_component);
-       }
-       vchiq_mmal_component_disable(dev->instance,
--                                   dev->component[MMAL_COMPONENT_CAMERA]);
-+                                   dev->component[COMP_CAMERA]);
-       vchiq_mmal_component_finalise(dev->instance,
-                                     dev->
--                                    component[MMAL_COMPONENT_VIDEO_ENCODE]);
-+                                    component[COMP_VIDEO_ENCODE]);
-       vchiq_mmal_component_finalise(dev->instance,
-                                     dev->
--                                    component[MMAL_COMPONENT_IMAGE_ENCODE]);
-+                                    component[COMP_IMAGE_ENCODE]);
-       vchiq_mmal_component_finalise(dev->instance,
--                                    dev->component[MMAL_COMPONENT_PREVIEW]);
-+                                    dev->component[COMP_PREVIEW]);
-       vchiq_mmal_component_finalise(dev->instance,
--                                    dev->component[MMAL_COMPONENT_CAMERA]);
-+                                    dev->component[COMP_CAMERA]);
-       v4l2_ctrl_handler_free(&dev->ctrl_handler);
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-@@ -16,18 +16,18 @@
- #define V4L2_CTRL_COUNT 29 /* number of v4l controls */
- enum {
--      MMAL_COMPONENT_CAMERA = 0,
--      MMAL_COMPONENT_PREVIEW,
--      MMAL_COMPONENT_IMAGE_ENCODE,
--      MMAL_COMPONENT_VIDEO_ENCODE,
--      MMAL_COMPONENT_COUNT
-+      COMP_CAMERA = 0,
-+      COMP_PREVIEW,
-+      COMP_IMAGE_ENCODE,
-+      COMP_VIDEO_ENCODE,
-+      COMP_COUNT
- };
- enum {
--      MMAL_CAMERA_PORT_PREVIEW = 0,
--      MMAL_CAMERA_PORT_VIDEO,
--      MMAL_CAMERA_PORT_CAPTURE,
--      MMAL_CAMERA_PORT_COUNT
-+      CAM_PORT_PREVIEW = 0,
-+      CAM_PORT_VIDEO,
-+      CAM_PORT_CAPTURE,
-+      CAM_PORT_COUNT
- };
- #define PREVIEW_LAYER      2
-@@ -61,7 +61,7 @@ struct bm2835_mmal_dev {
-       /* allocated mmal instance and components */
-       struct vchiq_mmal_instance   *instance;
--      struct vchiq_mmal_component  *component[MMAL_COMPONENT_COUNT];
-+      struct vchiq_mmal_component  *component[COMP_COUNT];
-       int camera_use_count;
-       struct v4l2_window overlay;
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -176,7 +176,7 @@ static int ctrl_set_rational(struct bm28
-       struct mmal_parameter_rational rational_value;
-       struct vchiq_mmal_port *control;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       rational_value.num = ctrl->val;
-       rational_value.den = 100;
-@@ -194,7 +194,7 @@ static int ctrl_set_value(struct bm2835_
-       u32 u32_value;
-       struct vchiq_mmal_port *control;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       u32_value = ctrl->val;
-@@ -219,7 +219,7 @@ static int ctrl_set_iso(struct bm2835_mm
-               dev->manual_iso_enabled =
-                               (ctrl->val == V4L2_ISO_SENSITIVITY_MANUAL);
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       if (dev->manual_iso_enabled)
-               u32_value = dev->iso;
-@@ -238,7 +238,7 @@ static int ctrl_set_value_ev(struct bm28
-       s32 s32_value;
-       struct vchiq_mmal_port *control;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       s32_value = (ctrl->val - 12) * 2;       /* Convert from index to 1/6ths */
-@@ -255,7 +255,7 @@ static int ctrl_set_rotate(struct bm2835
-       u32 u32_value;
-       struct vchiq_mmal_component *camera;
--      camera = dev->component[MMAL_COMPONENT_CAMERA];
-+      camera = dev->component[COMP_CAMERA];
-       u32_value = ((ctrl->val % 360) / 90) * 90;
-@@ -291,7 +291,7 @@ static int ctrl_set_flip(struct bm2835_m
-       else
-               dev->vflip = ctrl->val;
--      camera = dev->component[MMAL_COMPONENT_CAMERA];
-+      camera = dev->component[COMP_CAMERA];
-       if (dev->hflip && dev->vflip)
-               u32_value = MMAL_PARAM_MIRROR_BOTH;
-@@ -330,7 +330,7 @@ static int ctrl_set_exposure(struct bm28
-       struct vchiq_mmal_port *control;
-       int ret = 0;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       if (mmal_ctrl->mmal_id == MMAL_PARAMETER_SHUTTER_SPEED) {
-               /* V4L2 is in 100usec increments.
-@@ -405,7 +405,7 @@ static int ctrl_set_metering_mode(struct
-               struct vchiq_mmal_port *control;
-               u32 u32_value = dev->metering_mode;
--              control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+              control = &dev->component[COMP_CAMERA]->control;
-               return vchiq_mmal_port_parameter_set(dev->instance, control,
-                                            mmal_ctrl->mmal_id,
-@@ -421,7 +421,7 @@ static int ctrl_set_flicker_avoidance(st
-       u32 u32_value;
-       struct vchiq_mmal_port *control;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       switch (ctrl->val) {
-       case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
-@@ -450,7 +450,7 @@ static int ctrl_set_awb_mode(struct bm28
-       u32 u32_value;
-       struct vchiq_mmal_port *control;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       switch (ctrl->val) {
-       case V4L2_WHITE_BALANCE_MANUAL:
-@@ -506,7 +506,7 @@ static int ctrl_set_awb_gains(struct bm2
-       struct vchiq_mmal_port *control;
-       struct mmal_parameter_awbgains gains;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       if (ctrl->id == V4L2_CID_RED_BALANCE)
-               dev->red_gain = ctrl->val;
-@@ -554,7 +554,7 @@ static int ctrl_set_image_effect(struct
-                                       v4l2_to_mmal_effects_values[i].v;
-                       }
--                      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+                      control = &dev->component[COMP_CAMERA]->control;
-                       ret = vchiq_mmal_port_parameter_set(
-                                       dev->instance, control,
-@@ -587,7 +587,7 @@ static int ctrl_set_colfx(struct bm2835_
-       int ret = -EINVAL;
-       struct vchiq_mmal_port *control;
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
-       dev->colourfx.enable = ctrl->val & 0xff;
-@@ -613,7 +613,7 @@ static int ctrl_set_bitrate(struct bm283
-       dev->capture.encode_bitrate = ctrl->val;
--      encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
-+      encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0];
-       ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
-                                           mmal_ctrl->mmal_id,
-@@ -629,7 +629,7 @@ static int ctrl_set_bitrate_mode(struct
-       u32 bitrate_mode;
-       struct vchiq_mmal_port *encoder_out;
--      encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
-+      encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0];
-       dev->capture.encode_bitrate_mode = ctrl->val;
-       switch (ctrl->val) {
-@@ -656,7 +656,7 @@ static int ctrl_set_image_encode_output(
-       u32 u32_value;
-       struct vchiq_mmal_port *jpeg_out;
--      jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
-+      jpeg_out = &dev->component[COMP_IMAGE_ENCODE]->output[0];
-       u32_value = ctrl->val;
-@@ -672,7 +672,7 @@ static int ctrl_set_video_encode_param_o
-       u32 u32_value;
-       struct vchiq_mmal_port *vid_enc_ctl;
--      vid_enc_ctl = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
-+      vid_enc_ctl = &dev->component[COMP_VIDEO_ENCODE]->output[0];
-       u32_value = ctrl->val;
-@@ -785,7 +785,7 @@ static int ctrl_set_video_encode_profile
-               }
-               ret = vchiq_mmal_port_parameter_set(dev->instance,
--                                                  &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0],
-+                                                  &dev->component[COMP_VIDEO_ENCODE]->output[0],
-                       mmal_ctrl->mmal_id,
-                       &param, sizeof(param));
-       }
-@@ -803,7 +803,7 @@ static int ctrl_set_scene_mode(struct bm
-       v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                "scene mode selected %d, was %d\n", ctrl->val,
-                dev->scene_mode);
--      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+      control = &dev->component[COMP_CAMERA]->control;
-       if (ctrl->val == dev->scene_mode)
-               return 0;
-@@ -1221,18 +1221,15 @@ int set_framerate_params(struct bm2835_m
-                fps_range.fps_high.den);
-       ret = vchiq_mmal_port_parameter_set(dev->instance,
--                                          &dev->component[MMAL_COMPONENT_CAMERA]->
--                                          output[MMAL_CAMERA_PORT_PREVIEW],
-+                                          &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW],
-                                           MMAL_PARAMETER_FPS_RANGE,
-                                           &fps_range, sizeof(fps_range));
-       ret += vchiq_mmal_port_parameter_set(dev->instance,
--                                           &dev->component[MMAL_COMPONENT_CAMERA]->
--                                           output[MMAL_CAMERA_PORT_VIDEO],
-+                                           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO],
-                                            MMAL_PARAMETER_FPS_RANGE,
-                                            &fps_range, sizeof(fps_range));
-       ret += vchiq_mmal_port_parameter_set(dev->instance,
--                                           &dev->component[MMAL_COMPONENT_CAMERA]->
--                                           output[MMAL_CAMERA_PORT_CAPTURE],
-+                                           &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE],
-                                            MMAL_PARAMETER_FPS_RANGE,
-                                            &fps_range, sizeof(fps_range));
-       if (ret)
diff --git a/target/linux/brcm2708/patches-4.19/950-0218-staging-bcm2835-camera-Fix-missing-lines-between-ite.patch b/target/linux/brcm2708/patches-4.19/950-0218-staging-bcm2835-camera-Fix-missing-lines-between-ite.patch
new file mode 100644 (file)
index 0000000..2780112
--- /dev/null
@@ -0,0 +1,35 @@
+From 6974c0c97b821c30af9f6f4ff9b4b6989cb5a573 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 15:39:26 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix missing lines between
+ items
+
+Fix checkpatch errors for missing blank lines after variable
+or structure declarations.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h | 1 +
+ drivers/staging/vc04_services/bcm2835-camera/controls.c       | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
+@@ -130,6 +130,7 @@ int set_framerate_params(struct bm2835_m
+               (pix_fmt)->pixelformat, (pix_fmt)->bytesperline,        \
+               (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \
+ }
++
+ #define v4l2_dump_win_format(level, debug, dev, win_fmt, desc)        \
+ {     \
+       v4l2_dbg(level, debug, dev,     \
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -53,6 +53,7 @@ static const s64 ev_bias_qmenu[] = {
+ static const s64 iso_qmenu[] = {
+       0, 100000, 200000, 400000, 800000,
+ };
++
+ static const uint32_t iso_values[] = {
+       0, 100, 200, 400, 800,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0218-staging-bcm2835-camera-Fix-multiple-line-dereference.patch b/target/linux/brcm2708/patches-4.19/950-0218-staging-bcm2835-camera-Fix-multiple-line-dereference.patch
deleted file mode 100644 (file)
index 7797510..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-From 2730c4538b6edbe1e9d4071a8a64aa62f655eeaa Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 15:28:07 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix multiple line
- dereference errors
-
-Fix checkpatch errors "Avoid multiple line dereference"
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c           | 41 +++++++------------
- 1 file changed, 14 insertions(+), 27 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -313,8 +313,7 @@ static void buffer_cleanup(struct vb2_bu
- static inline bool is_capturing(struct bm2835_mmal_dev *dev)
- {
-       return dev->capture.camera_port ==
--          &dev->
--          component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
-+          &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
- }
- static void buffer_cb(struct vchiq_mmal_instance *instance,
-@@ -795,8 +794,7 @@ static int vidioc_overlay(struct file *f
-               return 0;       /* already in requested state */
-       src =
--          &dev->component[COMP_CAMERA]->
--          output[CAM_PORT_PREVIEW];
-+          &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW];
-       if (!on) {
-               /* disconnect preview ports and disable component */
-@@ -853,8 +851,7 @@ static int vidioc_g_fbuf(struct file *fi
-        */
-       struct bm2835_mmal_dev *dev = video_drvdata(file);
-       struct vchiq_mmal_port *preview_port =
--              &dev->component[COMP_CAMERA]->
--              output[CAM_PORT_PREVIEW];
-+              &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW];
-       a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY |
-                       V4L2_FBUF_CAP_GLOBAL_ALPHA;
-@@ -1046,8 +1043,7 @@ static int mmal_setup_components(struct
-                                              dev->capture.camera_port, NULL);
-               dev->capture.camera_port = NULL;
-               ret = vchiq_mmal_component_disable(dev->instance,
--                                                 dev->capture.
--                                                 encode_component);
-+                                                 dev->capture.encode_component);
-               if (ret)
-                       v4l2_err(&dev->v4l2_dev,
-                                "Failed to disable encode component %d\n",
-@@ -1062,26 +1058,22 @@ static int mmal_setup_components(struct
-               if (f->fmt.pix.width <= max_video_width
-                   && f->fmt.pix.height <= max_video_height)
-                       camera_port = port =
--                          &dev->component[COMP_CAMERA]->
--                          output[CAM_PORT_VIDEO];
-+                          &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
-               else
-                       camera_port = port =
--                          &dev->component[COMP_CAMERA]->
--                          output[CAM_PORT_CAPTURE];
-+                          &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
-               break;
-       case COMP_IMAGE_ENCODE:
-               encode_component = dev->component[COMP_IMAGE_ENCODE];
-               port = &dev->component[COMP_IMAGE_ENCODE]->output[0];
-               camera_port =
--                  &dev->component[COMP_CAMERA]->
--                  output[CAM_PORT_CAPTURE];
-+                  &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
-               break;
-       case COMP_VIDEO_ENCODE:
-               encode_component = dev->component[COMP_VIDEO_ENCODE];
-               port = &dev->component[COMP_VIDEO_ENCODE]->output[0];
-               camera_port =
--                  &dev->component[COMP_CAMERA]->
--                  output[CAM_PORT_VIDEO];
-+                  &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
-               break;
-       default:
-               break;
-@@ -1123,8 +1115,7 @@ static int mmal_setup_components(struct
-       if (!ret
-           && camera_port ==
--          &dev->component[COMP_CAMERA]->
--          output[CAM_PORT_VIDEO]) {
-+          &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]) {
-               bool overlay_enabled =
-                   !!dev->component[COMP_PREVIEW]->enabled;
-               struct vchiq_mmal_port *preview_port =
-@@ -1261,9 +1252,8 @@ static int mmal_setup_components(struct
-                                                port->current_buffer.size);
-                                       port->current_buffer.size =
-                                           (f->fmt.pix.sizeimage <
--                                           (100 << 10))
--                                          ? (100 << 10)
--                                          : f->fmt.pix.sizeimage;
-+                                           (100 << 10)) ?
-+                                          (100 << 10) : f->fmt.pix.sizeimage;
-                               }
-                               v4l2_dbg(1, bcm2835_v4l2_debug,
-                                        &dev->v4l2_dev,
-@@ -1722,8 +1712,7 @@ static int mmal_init(struct bm2835_mmal_
-       /* get the video encoder component ready */
-       ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
--                                      &dev->
--                                      component[COMP_VIDEO_ENCODE]);
-+                                      &dev->component[COMP_VIDEO_ENCODE]);
-       if (ret < 0)
-               goto unreg_image_encoder;
-@@ -1846,12 +1835,10 @@ static void bcm2835_cleanup_instance(str
-                                    dev->component[COMP_CAMERA]);
-       vchiq_mmal_component_finalise(dev->instance,
--                                    dev->
--                                    component[COMP_VIDEO_ENCODE]);
-+                                    dev->component[COMP_VIDEO_ENCODE]);
-       vchiq_mmal_component_finalise(dev->instance,
--                                    dev->
--                                    component[COMP_IMAGE_ENCODE]);
-+                                    dev->component[COMP_IMAGE_ENCODE]);
-       vchiq_mmal_component_finalise(dev->instance,
-                                     dev->component[COMP_PREVIEW]);
diff --git a/target/linux/brcm2708/patches-4.19/950-0219-staging-bcm2835-camera-Fix-brace-style-issues.patch b/target/linux/brcm2708/patches-4.19/950-0219-staging-bcm2835-camera-Fix-brace-style-issues.patch
deleted file mode 100644 (file)
index 6aa8e93..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From a023ee926b7e923058203e82edc5405c1e82842c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 15:37:11 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix brace style issues.
-
-Fix mismatched or missing brace issues flagged by checkpatch.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 3 ++-
- drivers/staging/vc04_services/bcm2835-camera/controls.c       | 3 ++-
- drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c     | 3 ++-
- 3 files changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -569,10 +569,11 @@ static int start_streaming(struct vb2_qu
-               /* Flag to indicate just to rely on kernel timestamps */
-               dev->capture.vc_start_timestamp = -1;
--      } else
-+      } else {
-               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                        "Start time %lld size %d\n",
-                        dev->capture.vc_start_timestamp, parameter_size);
-+      }
-       dev->capture.kernel_start_ts = ktime_get();
-       dev->capture.last_timestamp = 0;
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -410,8 +410,9 @@ static int ctrl_set_metering_mode(struct
-               return vchiq_mmal_port_parameter_set(dev->instance, control,
-                                            mmal_ctrl->mmal_id,
-                                            &u32_value, sizeof(u32_value));
--      } else
-+      } else {
-               return 0;
-+      }
- }
- static int ctrl_set_flicker_avoidance(struct bm2835_mmal_dev *dev,
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-@@ -1268,9 +1268,10 @@ static int port_parameter_get(struct vch
-               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
-                      *value_size);
-               *value_size = rmsg->u.port_parameter_get_reply.size;
--      } else
-+      } else {
-               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
-                      rmsg->u.port_parameter_get_reply.size);
-+      }
-       pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
-                ret, port->component->handle, port->handle, parameter_id);
diff --git a/target/linux/brcm2708/patches-4.19/950-0219-staging-bcm2835-camera-Fix-logical-continuation-spli.patch b/target/linux/brcm2708/patches-4.19/950-0219-staging-bcm2835-camera-Fix-logical-continuation-spli.patch
new file mode 100644 (file)
index 0000000..8d6b7a9
--- /dev/null
@@ -0,0 +1,49 @@
+From 5056b62708ac730f36114e1d792d0cc878b43561 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 15:48:54 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix logical continuation
+ splits
+
+Fix checkpatch errors for "Logical continuations should be
+on the previous line".
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/bcm2835-camera.c    | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -545,8 +545,8 @@ static int start_streaming(struct vb2_qu
+               msleep(300);
+       /* enable the connection from camera to encoder (if applicable) */
+-      if (dev->capture.camera_port != dev->capture.port
+-          && dev->capture.camera_port) {
++      if (dev->capture.camera_port != dev->capture.port &&
++          dev->capture.camera_port) {
+               ret = vchiq_mmal_port_enable(dev->instance,
+                                            dev->capture.camera_port, NULL);
+               if (ret) {
+@@ -1056,8 +1056,8 @@ static int mmal_setup_components(struct
+       switch (mfmt->mmal_component) {
+       case COMP_CAMERA:
+               /* Make a further decision on port based on resolution */
+-              if (f->fmt.pix.width <= max_video_width
+-                  && f->fmt.pix.height <= max_video_height)
++              if (f->fmt.pix.width <= max_video_width &&
++                  f->fmt.pix.height <= max_video_height)
+                       camera_port = port =
+                           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
+               else
+@@ -1114,8 +1114,8 @@ static int mmal_setup_components(struct
+       ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
+-      if (!ret
+-          && camera_port ==
++      if (!ret &&
++          camera_port ==
+           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]) {
+               bool overlay_enabled =
+                   !!dev->component[COMP_PREVIEW]->enabled;
diff --git a/target/linux/brcm2708/patches-4.19/950-0220-staging-bcm2835-camera-Fix-missing-lines-between-ite.patch b/target/linux/brcm2708/patches-4.19/950-0220-staging-bcm2835-camera-Fix-missing-lines-between-ite.patch
deleted file mode 100644 (file)
index 2780112..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From 6974c0c97b821c30af9f6f4ff9b4b6989cb5a573 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 15:39:26 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix missing lines between
- items
-
-Fix checkpatch errors for missing blank lines after variable
-or structure declarations.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h | 1 +
- drivers/staging/vc04_services/bcm2835-camera/controls.c       | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-@@ -130,6 +130,7 @@ int set_framerate_params(struct bm2835_m
-               (pix_fmt)->pixelformat, (pix_fmt)->bytesperline,        \
-               (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \
- }
-+
- #define v4l2_dump_win_format(level, debug, dev, win_fmt, desc)        \
- {     \
-       v4l2_dbg(level, debug, dev,     \
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -53,6 +53,7 @@ static const s64 ev_bias_qmenu[] = {
- static const s64 iso_qmenu[] = {
-       0, 100000, 200000, 400000, 800000,
- };
-+
- static const uint32_t iso_values[] = {
-       0, 100, 200, 400, 800,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0220-staging-bcm2835-camera-Fix-open-parenthesis-alignmen.patch b/target/linux/brcm2708/patches-4.19/950-0220-staging-bcm2835-camera-Fix-open-parenthesis-alignmen.patch
new file mode 100644 (file)
index 0000000..85c7f1e
--- /dev/null
@@ -0,0 +1,137 @@
+From 4ed895c5c9f55f565d5ecc19e799e109673db44f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 21 Feb 2018 15:53:59 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix open parenthesis
+ alignment
+
+Fix checkpatch "Alignment should match open parenthesis"
+errors.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 12 ++++-----
+ .../vc04_services/bcm2835-camera/controls.c   | 25 ++++++++++++-------
+ .../vc04_services/bcm2835-camera/mmal-vchiq.c |  2 +-
+ .../vc04_services/bcm2835-camera/mmal-vchiq.h |  6 ++---
+ 4 files changed, 25 insertions(+), 20 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -415,8 +415,7 @@ static void buffer_cb(struct vchiq_mmal_
+               buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+-               "Buffer has ts %llu",
+-               dev->capture.last_timestamp);
++               "Buffer has ts %llu", dev->capture.last_timestamp);
+       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
+@@ -584,8 +583,8 @@ static int start_streaming(struct vb2_qu
+           vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev,
+-                      "Failed to enable capture port - error %d. Disabling camera port again\n",
+-                      ret);
++                       "Failed to enable capture port - error %d. Disabling camera port again\n",
++                       ret);
+               vchiq_mmal_port_disable(dev->instance,
+                                       dev->capture.camera_port);
+@@ -991,8 +990,7 @@ static int vidioc_try_fmt_vid_cap(struct
+               f->fmt.pix.bytesperline =
+                       (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+-                       "Not removing padding, so bytes/line = %d, "
+-                       "(align_mask %d)\n",
++                       "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
+                        f->fmt.pix.bytesperline, align_mask);
+       }
+@@ -1338,7 +1336,7 @@ static int vidioc_s_fmt_vid_cap(struct f
+ }
+ static int vidioc_enum_framesizes(struct file *file, void *fh,
+-                         struct v4l2_frmsizeenum *fsize)
++                                struct v4l2_frmsizeenum *fsize)
+ {
+       struct bm2835_mmal_dev *dev = video_drvdata(file);
+       static const struct v4l2_frmsize_stepwise sizes = {
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -1254,9 +1254,12 @@ int bm2835_mmal_init_controls(struct bm2
+               switch (ctrl->type) {
+               case MMAL_CONTROL_TYPE_STD:
+-                      dev->ctrls[c] = v4l2_ctrl_new_std(hdl,
+-                              &bm2835_mmal_ctrl_ops, ctrl->id,
+-                              ctrl->min, ctrl->max, ctrl->step, ctrl->def);
++                      dev->ctrls[c] =
++                              v4l2_ctrl_new_std(hdl,
++                                                &bm2835_mmal_ctrl_ops,
++                                                ctrl->id, ctrl->min,
++                                                ctrl->max, ctrl->step,
++                                                ctrl->def);
+                       break;
+               case MMAL_CONTROL_TYPE_STD_MENU:
+@@ -1280,16 +1283,20 @@ int bm2835_mmal_init_controls(struct bm2
+                               mask = ~mask;
+                       }
+-                      dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
+-                      &bm2835_mmal_ctrl_ops, ctrl->id,
+-                      ctrl->max, mask, ctrl->def);
++                      dev->ctrls[c] =
++                              v4l2_ctrl_new_std_menu(hdl,
++                                                     &bm2835_mmal_ctrl_ops,
++                                                     ctrl->id, ctrl->max,
++                                                     mask, ctrl->def);
+                       break;
+               }
+               case MMAL_CONTROL_TYPE_INT_MENU:
+-                      dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,
+-                              &bm2835_mmal_ctrl_ops, ctrl->id,
+-                              ctrl->max, ctrl->def, ctrl->imenu);
++                      dev->ctrls[c] =
++                              v4l2_ctrl_new_int_menu(hdl,
++                                                     &bm2835_mmal_ctrl_ops,
++                                                     ctrl->id, ctrl->max,
++                                                     ctrl->def, ctrl->imenu);
+                       break;
+               case MMAL_CONTROL_TYPE_CLUSTER:
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -651,7 +651,7 @@ static int send_synchronous_mmal_msg(str
+       if (payload_len >
+           (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
+               pr_err("payload length %d exceeds max:%d\n", payload_len,
+-                    (int)(MMAL_MSG_MAX_SIZE -
++                     (int)(MMAL_MSG_MAX_SIZE -
+                           sizeof(struct mmal_msg_header)));
+               return -EINVAL;
+       }
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
+@@ -131,7 +131,7 @@ int vchiq_mmal_port_enable(
+  * disable a port will dequeue any pending buffers
+  */
+ int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
+-                         struct vchiq_mmal_port *port);
++                          struct vchiq_mmal_port *port);
+ int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
+                                 struct vchiq_mmal_port *port,
+@@ -149,8 +149,8 @@ int vchiq_mmal_port_set_format(struct vc
+                              struct vchiq_mmal_port *port);
+ int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_port *src,
+-                          struct vchiq_mmal_port *dst);
++                                 struct vchiq_mmal_port *src,
++                                 struct vchiq_mmal_port *dst);
+ int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
+                      u32 *major_out,
diff --git a/target/linux/brcm2708/patches-4.19/950-0221-staging-bcm2835-camera-Fix-logical-continuation-spli.patch b/target/linux/brcm2708/patches-4.19/950-0221-staging-bcm2835-camera-Fix-logical-continuation-spli.patch
deleted file mode 100644 (file)
index 8d6b7a9..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 5056b62708ac730f36114e1d792d0cc878b43561 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 15:48:54 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix logical continuation
- splits
-
-Fix checkpatch errors for "Logical continuations should be
-on the previous line".
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/bcm2835-camera.c    | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -545,8 +545,8 @@ static int start_streaming(struct vb2_qu
-               msleep(300);
-       /* enable the connection from camera to encoder (if applicable) */
--      if (dev->capture.camera_port != dev->capture.port
--          && dev->capture.camera_port) {
-+      if (dev->capture.camera_port != dev->capture.port &&
-+          dev->capture.camera_port) {
-               ret = vchiq_mmal_port_enable(dev->instance,
-                                            dev->capture.camera_port, NULL);
-               if (ret) {
-@@ -1056,8 +1056,8 @@ static int mmal_setup_components(struct
-       switch (mfmt->mmal_component) {
-       case COMP_CAMERA:
-               /* Make a further decision on port based on resolution */
--              if (f->fmt.pix.width <= max_video_width
--                  && f->fmt.pix.height <= max_video_height)
-+              if (f->fmt.pix.width <= max_video_width &&
-+                  f->fmt.pix.height <= max_video_height)
-                       camera_port = port =
-                           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
-               else
-@@ -1114,8 +1114,8 @@ static int mmal_setup_components(struct
-       ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
--      if (!ret
--          && camera_port ==
-+      if (!ret &&
-+          camera_port ==
-           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]) {
-               bool overlay_enabled =
-                   !!dev->component[COMP_PREVIEW]->enabled;
diff --git a/target/linux/brcm2708/patches-4.19/950-0221-staging-bcm2835-camera-Set-sequence-number-correctly.patch b/target/linux/brcm2708/patches-4.19/950-0221-staging-bcm2835-camera-Set-sequence-number-correctly.patch
new file mode 100644 (file)
index 0000000..dbfa67c
--- /dev/null
@@ -0,0 +1,46 @@
+From ba37d62e7bbdf42c2fa9ac3655354992da199a4b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 21 Jun 2018 17:02:14 +0100
+Subject: [PATCH] staging: bcm2835-camera: Set sequence number
+ correctly
+
+Set the sequence number in vb2_v4l2_buffer mainly so the
+latest v4l2-ctl reports the frame rate correctly.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 4 ++++
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h | 2 ++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -409,6 +409,7 @@ static void buffer_cb(struct vchiq_mmal_
+               }
+       }
+       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
++      buf->vb.sequence = dev->capture.sequence++;
+       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
+       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+@@ -537,6 +538,9 @@ static int start_streaming(struct vb2_qu
+       /* enable frame capture */
+       dev->capture.frame_count = 1;
++      /* reset sequence number */
++      dev->capture.sequence = 0;
++
+       /* if the preview is not already running, wait for a few frames for AGC
+        * to settle down.
+        */
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
+@@ -93,6 +93,8 @@ struct bm2835_mmal_dev {
+               ktime_t kernel_start_ts;
+               /* Timestamp of last frame */
+               u64             last_timestamp;
++              /* Sequence number of last buffer */
++              u32             sequence;
+               struct vchiq_mmal_port  *port; /* port being used for capture */
+               /* camera port being used for capture */
diff --git a/target/linux/brcm2708/patches-4.19/950-0222-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch b/target/linux/brcm2708/patches-4.19/950-0222-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch
new file mode 100644 (file)
index 0000000..802ff8b
--- /dev/null
@@ -0,0 +1,38 @@
+From 0d0b7a58ab065f72ffa55fbc7ab5436628694919 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 24 Jul 2018 12:08:29 +0100
+Subject: [PATCH] staging: bcm2835-camera: Ensure timestamps never go
+ backwards.
+
+There is an awkward situation with H264 header bytes. Currently
+they are returned with a PTS of 0 because they aren't associated
+with a timestamped frame to encode. These are handled by either
+returning the timestamp of the last buffer to have been received,
+or in the case of the first buffer the timestamp taken at
+start_streaming.
+This results in a race where the current frame may have started
+before we take the start time, which results in the first encoded
+frame having an earlier timestamp than the header bytes.
+
+Ensure that we never return a negative delta to the user by checking
+against the previous timestamp.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c    | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -393,6 +393,11 @@ static void buffer_cb(struct vchiq_mmal_
+                        ktime_to_ns(dev->capture.kernel_start_ts),
+                        dev->capture.vc_start_timestamp, pts,
+                        ktime_to_ns(timestamp));
++              if (timestamp < dev->capture.last_timestamp) {
++                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                               "Negative delta - using last time\n");
++                      timestamp = dev->capture.last_timestamp;
++              }
+               buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
+       } else {
+               if (dev->capture.last_timestamp) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0222-staging-bcm2835-camera-Fix-open-parenthesis-alignmen.patch b/target/linux/brcm2708/patches-4.19/950-0222-staging-bcm2835-camera-Fix-open-parenthesis-alignmen.patch
deleted file mode 100644 (file)
index 85c7f1e..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-From 4ed895c5c9f55f565d5ecc19e799e109673db44f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 21 Feb 2018 15:53:59 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix open parenthesis
- alignment
-
-Fix checkpatch "Alignment should match open parenthesis"
-errors.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c           | 12 ++++-----
- .../vc04_services/bcm2835-camera/controls.c   | 25 ++++++++++++-------
- .../vc04_services/bcm2835-camera/mmal-vchiq.c |  2 +-
- .../vc04_services/bcm2835-camera/mmal-vchiq.h |  6 ++---
- 4 files changed, 25 insertions(+), 20 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -415,8 +415,7 @@ static void buffer_cb(struct vchiq_mmal_
-               buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
--               "Buffer has ts %llu",
--               dev->capture.last_timestamp);
-+               "Buffer has ts %llu", dev->capture.last_timestamp);
-       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
-       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
-@@ -584,8 +583,8 @@ static int start_streaming(struct vb2_qu
-           vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
-       if (ret) {
-               v4l2_err(&dev->v4l2_dev,
--                      "Failed to enable capture port - error %d. Disabling camera port again\n",
--                      ret);
-+                       "Failed to enable capture port - error %d. Disabling camera port again\n",
-+                       ret);
-               vchiq_mmal_port_disable(dev->instance,
-                                       dev->capture.camera_port);
-@@ -991,8 +990,7 @@ static int vidioc_try_fmt_vid_cap(struct
-               f->fmt.pix.bytesperline =
-                       (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
-               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
--                       "Not removing padding, so bytes/line = %d, "
--                       "(align_mask %d)\n",
-+                       "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
-                        f->fmt.pix.bytesperline, align_mask);
-       }
-@@ -1338,7 +1336,7 @@ static int vidioc_s_fmt_vid_cap(struct f
- }
- static int vidioc_enum_framesizes(struct file *file, void *fh,
--                         struct v4l2_frmsizeenum *fsize)
-+                                struct v4l2_frmsizeenum *fsize)
- {
-       struct bm2835_mmal_dev *dev = video_drvdata(file);
-       static const struct v4l2_frmsize_stepwise sizes = {
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -1254,9 +1254,12 @@ int bm2835_mmal_init_controls(struct bm2
-               switch (ctrl->type) {
-               case MMAL_CONTROL_TYPE_STD:
--                      dev->ctrls[c] = v4l2_ctrl_new_std(hdl,
--                              &bm2835_mmal_ctrl_ops, ctrl->id,
--                              ctrl->min, ctrl->max, ctrl->step, ctrl->def);
-+                      dev->ctrls[c] =
-+                              v4l2_ctrl_new_std(hdl,
-+                                                &bm2835_mmal_ctrl_ops,
-+                                                ctrl->id, ctrl->min,
-+                                                ctrl->max, ctrl->step,
-+                                                ctrl->def);
-                       break;
-               case MMAL_CONTROL_TYPE_STD_MENU:
-@@ -1280,16 +1283,20 @@ int bm2835_mmal_init_controls(struct bm2
-                               mask = ~mask;
-                       }
--                      dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
--                      &bm2835_mmal_ctrl_ops, ctrl->id,
--                      ctrl->max, mask, ctrl->def);
-+                      dev->ctrls[c] =
-+                              v4l2_ctrl_new_std_menu(hdl,
-+                                                     &bm2835_mmal_ctrl_ops,
-+                                                     ctrl->id, ctrl->max,
-+                                                     mask, ctrl->def);
-                       break;
-               }
-               case MMAL_CONTROL_TYPE_INT_MENU:
--                      dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,
--                              &bm2835_mmal_ctrl_ops, ctrl->id,
--                              ctrl->max, ctrl->def, ctrl->imenu);
-+                      dev->ctrls[c] =
-+                              v4l2_ctrl_new_int_menu(hdl,
-+                                                     &bm2835_mmal_ctrl_ops,
-+                                                     ctrl->id, ctrl->max,
-+                                                     ctrl->def, ctrl->imenu);
-                       break;
-               case MMAL_CONTROL_TYPE_CLUSTER:
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-@@ -651,7 +651,7 @@ static int send_synchronous_mmal_msg(str
-       if (payload_len >
-           (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
-               pr_err("payload length %d exceeds max:%d\n", payload_len,
--                    (int)(MMAL_MSG_MAX_SIZE -
-+                     (int)(MMAL_MSG_MAX_SIZE -
-                           sizeof(struct mmal_msg_header)));
-               return -EINVAL;
-       }
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
-@@ -131,7 +131,7 @@ int vchiq_mmal_port_enable(
-  * disable a port will dequeue any pending buffers
-  */
- int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
--                         struct vchiq_mmal_port *port);
-+                          struct vchiq_mmal_port *port);
- int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
-                                 struct vchiq_mmal_port *port,
-@@ -149,8 +149,8 @@ int vchiq_mmal_port_set_format(struct vc
-                              struct vchiq_mmal_port *port);
- int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
--                          struct vchiq_mmal_port *src,
--                          struct vchiq_mmal_port *dst);
-+                                 struct vchiq_mmal_port *src,
-+                                 struct vchiq_mmal_port *dst);
- int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
-                      u32 *major_out,
diff --git a/target/linux/brcm2708/patches-4.19/950-0223-staging-bcm2835-camera-Avoid-unneeded-internal-decla.patch b/target/linux/brcm2708/patches-4.19/950-0223-staging-bcm2835-camera-Avoid-unneeded-internal-decla.patch
new file mode 100644 (file)
index 0000000..11e6f1f
--- /dev/null
@@ -0,0 +1,41 @@
+From f658f48d662c5ecd84af235f47cc48636b9a55e2 Mon Sep 17 00:00:00 2001
+From: Nathan Chancellor <natechancellor@gmail.com>
+Date: Thu, 27 Sep 2018 17:50:39 -0700
+Subject: [PATCH] staging: bcm2835-camera: Avoid unneeded internal
+ declaration warning
+
+Clang warns:
+
+drivers/staging/vc04_services/bcm2835-camera/controls.c:59:18: warning:
+variable 'mains_freq_qmenu' is not needed and will not be emitted
+[-Wunneeded-internal-declaration]
+static const s64 mains_freq_qmenu[] = {
+                 ^
+1 warning generated.
+
+This is because mains_freq_qmenu is currently only used in an ARRAY_SIZE
+macro, which is a compile time evaluation in this case. Avoid this by
+adding mains_freq_qmenu as the imenu member of this structure, which
+matches all other controls that uses the ARRAY_SIZE macro in v4l2_ctrls.
+This turns out to be a no-op because V4L2_CID_MPEG_VIDEO_BITRATE_MODE is
+defined as a MMAL_CONTROL_TYPE_STD_MENU, which does not pass the imenu
+definition along to v4l2_ctrl_new in bm2835_mmal_init_controls.
+
+Link: https://github.com/ClangBuiltLinux/linux/issues/122
+Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -1109,7 +1109,7 @@ static const struct bm2835_mmal_v4l2_ctr
+       {
+               V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
+               0, ARRAY_SIZE(mains_freq_qmenu) - 1,
+-              1, 1, NULL,
++              1, 1, mains_freq_qmenu,
+               MMAL_PARAMETER_FLICKER_AVOID,
+               &ctrl_set_flicker_avoidance,
+               false
diff --git a/target/linux/brcm2708/patches-4.19/950-0223-staging-bcm2835-camera-Set-sequence-number-correctly.patch b/target/linux/brcm2708/patches-4.19/950-0223-staging-bcm2835-camera-Set-sequence-number-correctly.patch
deleted file mode 100644 (file)
index dbfa67c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From ba37d62e7bbdf42c2fa9ac3655354992da199a4b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 21 Jun 2018 17:02:14 +0100
-Subject: [PATCH] staging: bcm2835-camera: Set sequence number
- correctly
-
-Set the sequence number in vb2_v4l2_buffer mainly so the
-latest v4l2-ctl reports the frame rate correctly.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 4 ++++
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h | 2 ++
- 2 files changed, 6 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -409,6 +409,7 @@ static void buffer_cb(struct vchiq_mmal_
-               }
-       }
-       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-+      buf->vb.sequence = dev->capture.sequence++;
-       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
-       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-@@ -537,6 +538,9 @@ static int start_streaming(struct vb2_qu
-       /* enable frame capture */
-       dev->capture.frame_count = 1;
-+      /* reset sequence number */
-+      dev->capture.sequence = 0;
-+
-       /* if the preview is not already running, wait for a few frames for AGC
-        * to settle down.
-        */
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-@@ -93,6 +93,8 @@ struct bm2835_mmal_dev {
-               ktime_t kernel_start_ts;
-               /* Timestamp of last frame */
-               u64             last_timestamp;
-+              /* Sequence number of last buffer */
-+              u32             sequence;
-               struct vchiq_mmal_port  *port; /* port being used for capture */
-               /* camera port being used for capture */
diff --git a/target/linux/brcm2708/patches-4.19/950-0224-staging-bcm2835-camera-Add-multiple-inclusion-protec.patch b/target/linux/brcm2708/patches-4.19/950-0224-staging-bcm2835-camera-Add-multiple-inclusion-protec.patch
new file mode 100644 (file)
index 0000000..0feb273
--- /dev/null
@@ -0,0 +1,48 @@
+From c37e8c9137e4858ed86e211f3fddbb9d9af08532 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:21:06 +0100
+Subject: [PATCH] staging: bcm2835-camera: Add multiple inclusion
+ protection to headers
+
+mmal-common.h and mmal-msg.h didn't have the normal
+ifndef FOO / define FOO / endif protection to stop it being
+included multiple times. Add it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/mmal-common.h | 3 +++
+ drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h    | 3 +++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
+@@ -13,6 +13,8 @@
+  * MMAL structures
+  *
+  */
++#ifndef MMAL_COMMON_H
++#define MMAL_COMMON_H
+ #define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
+ #define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
+@@ -56,3 +58,4 @@ struct mmal_colourfx {
+       u32 u;
+       u32 v;
+ };
++#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
+@@ -23,6 +23,8 @@
+  * implementation uses fixed size types and not the enums (though the
+  * comments have the actual enum type
+  */
++#ifndef MMAL_MSG_H
++#define MMAL_MSG_H
+ #define VC_MMAL_VER 15
+ #define VC_MMAL_MIN_VER 10
+@@ -401,3 +403,4 @@ struct mmal_msg {
+               u8 payload[MMAL_MSG_MAX_PAYLOAD];
+       } u;
+ };
++#endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0224-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch b/target/linux/brcm2708/patches-4.19/950-0224-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch
deleted file mode 100644 (file)
index 802ff8b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 0d0b7a58ab065f72ffa55fbc7ab5436628694919 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 24 Jul 2018 12:08:29 +0100
-Subject: [PATCH] staging: bcm2835-camera: Ensure timestamps never go
- backwards.
-
-There is an awkward situation with H264 header bytes. Currently
-they are returned with a PTS of 0 because they aren't associated
-with a timestamped frame to encode. These are handled by either
-returning the timestamp of the last buffer to have been received,
-or in the case of the first buffer the timestamp taken at
-start_streaming.
-This results in a race where the current frame may have started
-before we take the start time, which results in the first encoded
-frame having an earlier timestamp than the header bytes.
-
-Ensure that we never return a negative delta to the user by checking
-against the previous timestamp.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c    | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -393,6 +393,11 @@ static void buffer_cb(struct vchiq_mmal_
-                        ktime_to_ns(dev->capture.kernel_start_ts),
-                        dev->capture.vc_start_timestamp, pts,
-                        ktime_to_ns(timestamp));
-+              if (timestamp < dev->capture.last_timestamp) {
-+                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                               "Negative delta - using last time\n");
-+                      timestamp = dev->capture.last_timestamp;
-+              }
-               buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
-       } else {
-               if (dev->capture.last_timestamp) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0225-staging-bcm2835-camera-Avoid-unneeded-internal-decla.patch b/target/linux/brcm2708/patches-4.19/950-0225-staging-bcm2835-camera-Avoid-unneeded-internal-decla.patch
deleted file mode 100644 (file)
index 11e6f1f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From f658f48d662c5ecd84af235f47cc48636b9a55e2 Mon Sep 17 00:00:00 2001
-From: Nathan Chancellor <natechancellor@gmail.com>
-Date: Thu, 27 Sep 2018 17:50:39 -0700
-Subject: [PATCH] staging: bcm2835-camera: Avoid unneeded internal
- declaration warning
-
-Clang warns:
-
-drivers/staging/vc04_services/bcm2835-camera/controls.c:59:18: warning:
-variable 'mains_freq_qmenu' is not needed and will not be emitted
-[-Wunneeded-internal-declaration]
-static const s64 mains_freq_qmenu[] = {
-                 ^
-1 warning generated.
-
-This is because mains_freq_qmenu is currently only used in an ARRAY_SIZE
-macro, which is a compile time evaluation in this case. Avoid this by
-adding mains_freq_qmenu as the imenu member of this structure, which
-matches all other controls that uses the ARRAY_SIZE macro in v4l2_ctrls.
-This turns out to be a no-op because V4L2_CID_MPEG_VIDEO_BITRATE_MODE is
-defined as a MMAL_CONTROL_TYPE_STD_MENU, which does not pass the imenu
-definition along to v4l2_ctrl_new in bm2835_mmal_init_controls.
-
-Link: https://github.com/ClangBuiltLinux/linux/issues/122
-Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -1109,7 +1109,7 @@ static const struct bm2835_mmal_v4l2_ctr
-       {
-               V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
-               0, ARRAY_SIZE(mains_freq_qmenu) - 1,
--              1, 1, NULL,
-+              1, 1, mains_freq_qmenu,
-               MMAL_PARAMETER_FLICKER_AVOID,
-               &ctrl_set_flicker_avoidance,
-               false
diff --git a/target/linux/brcm2708/patches-4.19/950-0225-staging-bcm2835-camera-Unify-header-inclusion-define.patch b/target/linux/brcm2708/patches-4.19/950-0225-staging-bcm2835-camera-Unify-header-inclusion-define.patch
new file mode 100644 (file)
index 0000000..56d62f5
--- /dev/null
@@ -0,0 +1,30 @@
+From 925b969a16a2e3503803c47a87f093f88d1b2060 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 3 Dec 2018 13:15:20 +0000
+Subject: [PATCH] staging: bcm2835-camera: Unify header inclusion
+ defines
+
+Most of the headers use ifndef FOO_H, whilst mmal-parameters.h
+used ifndef __FOO_H.
+
+Revise mmal-parameters.h to drop the underscores and make the
+headers all consistent.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/mmal-parameters.h    | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
+@@ -19,8 +19,8 @@
+  * @{
+  */
+-#ifndef __MMAL_PARAMETERS_H
+-#define __MMAL_PARAMETERS_H
++#ifndef MMAL_PARAMETERS_H
++#define MMAL_PARAMETERS_H
+ /** Common parameter ID group, used with many types of component. */
+ #define MMAL_PARAMETER_GROUP_COMMON            (0 << 16)
diff --git a/target/linux/brcm2708/patches-4.19/950-0226-staging-bcm2835-camera-Add-multiple-inclusion-protec.patch b/target/linux/brcm2708/patches-4.19/950-0226-staging-bcm2835-camera-Add-multiple-inclusion-protec.patch
deleted file mode 100644 (file)
index 0feb273..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From c37e8c9137e4858ed86e211f3fddbb9d9af08532 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:21:06 +0100
-Subject: [PATCH] staging: bcm2835-camera: Add multiple inclusion
- protection to headers
-
-mmal-common.h and mmal-msg.h didn't have the normal
-ifndef FOO / define FOO / endif protection to stop it being
-included multiple times. Add it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/mmal-common.h | 3 +++
- drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h    | 3 +++
- 2 files changed, 6 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-@@ -13,6 +13,8 @@
-  * MMAL structures
-  *
-  */
-+#ifndef MMAL_COMMON_H
-+#define MMAL_COMMON_H
- #define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
- #define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
-@@ -56,3 +58,4 @@ struct mmal_colourfx {
-       u32 u;
-       u32 v;
- };
-+#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-@@ -23,6 +23,8 @@
-  * implementation uses fixed size types and not the enums (though the
-  * comments have the actual enum type
-  */
-+#ifndef MMAL_MSG_H
-+#define MMAL_MSG_H
- #define VC_MMAL_VER 15
- #define VC_MMAL_MIN_VER 10
-@@ -401,3 +403,4 @@ struct mmal_msg {
-               u8 payload[MMAL_MSG_MAX_PAYLOAD];
-       } u;
- };
-+#endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0226-staging-bcm2835-camera-Fix-alignment-should-match-op.patch b/target/linux/brcm2708/patches-4.19/950-0226-staging-bcm2835-camera-Fix-alignment-should-match-op.patch
new file mode 100644 (file)
index 0000000..53fb95d
--- /dev/null
@@ -0,0 +1,51 @@
+From 11129d36669a3efee5dd0d49f969f11c42764f9d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 15:55:42 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix alignment should match
+ open parenthesis
+
+Fix up checkpatch "Alignment should match open parenthesis" errors
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -1934,7 +1934,7 @@ static int bcm2835_mmal_probe(struct pla
+               ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
+               if (ret < 0) {
+                       v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n",
+-                              __func__, ret);
++                               __func__, ret);
+                       goto unreg_dev;
+               }
+               dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
+@@ -1944,7 +1944,7 @@ static int bcm2835_mmal_probe(struct pla
+               ret = mmal_init(dev);
+               if (ret < 0) {
+                       v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n",
+-                              __func__, ret);
++                               __func__, ret);
+                       goto unreg_dev;
+               }
+               /* initialize queue */
+@@ -1966,7 +1966,7 @@ static int bcm2835_mmal_probe(struct pla
+               ret = bm2835_mmal_init_device(dev, &dev->vdev);
+               if (ret < 0) {
+                       v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n",
+-                              __func__, ret);
++                               __func__, ret);
+                       goto unreg_dev;
+               }
+@@ -1976,7 +1976,7 @@ static int bcm2835_mmal_probe(struct pla
+               ret = mmal_setup_components(dev, &default_v4l2_format);
+               if (ret < 0) {
+                       v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n",
+-                              __func__, ret);
++                               __func__, ret);
+                       goto unreg_dev;
+               }
diff --git a/target/linux/brcm2708/patches-4.19/950-0227-staging-bcm2835-camera-Fix-multiple-assignments-shou.patch b/target/linux/brcm2708/patches-4.19/950-0227-staging-bcm2835-camera-Fix-multiple-assignments-shou.patch
new file mode 100644 (file)
index 0000000..34bbe82
--- /dev/null
@@ -0,0 +1,30 @@
+From d1f9d21346c642fadb2676077b050106afaf7579 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 15:58:14 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix multiple assignments
+ should be avoided
+
+Clear checkpatch complaints of "multiple assignments should be avoided"
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c    | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -1065,11 +1065,12 @@ static int mmal_setup_components(struct
+               /* Make a further decision on port based on resolution */
+               if (f->fmt.pix.width <= max_video_width &&
+                   f->fmt.pix.height <= max_video_height)
+-                      camera_port = port =
++                      camera_port =
+                           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
+               else
+-                      camera_port = port =
++                      camera_port =
+                           &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
++              port = camera_port;
+               break;
+       case COMP_IMAGE_ENCODE:
+               encode_component = dev->component[COMP_IMAGE_ENCODE];
diff --git a/target/linux/brcm2708/patches-4.19/950-0227-staging-bcm2835-camera-Unify-header-inclusion-define.patch b/target/linux/brcm2708/patches-4.19/950-0227-staging-bcm2835-camera-Unify-header-inclusion-define.patch
deleted file mode 100644 (file)
index 56d62f5..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 925b969a16a2e3503803c47a87f093f88d1b2060 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 3 Dec 2018 13:15:20 +0000
-Subject: [PATCH] staging: bcm2835-camera: Unify header inclusion
- defines
-
-Most of the headers use ifndef FOO_H, whilst mmal-parameters.h
-used ifndef __FOO_H.
-
-Revise mmal-parameters.h to drop the underscores and make the
-headers all consistent.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/mmal-parameters.h    | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-@@ -19,8 +19,8 @@
-  * @{
-  */
--#ifndef __MMAL_PARAMETERS_H
--#define __MMAL_PARAMETERS_H
-+#ifndef MMAL_PARAMETERS_H
-+#define MMAL_PARAMETERS_H
- /** Common parameter ID group, used with many types of component. */
- #define MMAL_PARAMETER_GROUP_COMMON            (0 << 16)
diff --git a/target/linux/brcm2708/patches-4.19/950-0228-staging-bcm2835-camera-Fix-alignment-should-match-op.patch b/target/linux/brcm2708/patches-4.19/950-0228-staging-bcm2835-camera-Fix-alignment-should-match-op.patch
deleted file mode 100644 (file)
index 53fb95d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From 11129d36669a3efee5dd0d49f969f11c42764f9d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 15:55:42 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix alignment should match
- open parenthesis
-
-Fix up checkpatch "Alignment should match open parenthesis" errors
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -1934,7 +1934,7 @@ static int bcm2835_mmal_probe(struct pla
-               ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n",
--                              __func__, ret);
-+                               __func__, ret);
-                       goto unreg_dev;
-               }
-               dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
-@@ -1944,7 +1944,7 @@ static int bcm2835_mmal_probe(struct pla
-               ret = mmal_init(dev);
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n",
--                              __func__, ret);
-+                               __func__, ret);
-                       goto unreg_dev;
-               }
-               /* initialize queue */
-@@ -1966,7 +1966,7 @@ static int bcm2835_mmal_probe(struct pla
-               ret = bm2835_mmal_init_device(dev, &dev->vdev);
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n",
--                              __func__, ret);
-+                               __func__, ret);
-                       goto unreg_dev;
-               }
-@@ -1976,7 +1976,7 @@ static int bcm2835_mmal_probe(struct pla
-               ret = mmal_setup_components(dev, &default_v4l2_format);
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n",
--                              __func__, ret);
-+                               __func__, ret);
-                       goto unreg_dev;
-               }
diff --git a/target/linux/brcm2708/patches-4.19/950-0228-staging-bcm2835-camera-Fix-up-all-formatting-in-mmal.patch b/target/linux/brcm2708/patches-4.19/950-0228-staging-bcm2835-camera-Fix-up-all-formatting-in-mmal.patch
new file mode 100644 (file)
index 0000000..254664b
--- /dev/null
@@ -0,0 +1,336 @@
+From be10ef41af683e175521f80b49b99d7ddeac2f2c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 16:08:41 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix up all formatting in
+ mmal-paramters.h
+
+Fixes up all checkpatch errors in mmal-parameters.h
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/mmal-parameters.h          | 273 +++++++++++-------
+ 1 file changed, 165 insertions(+), 108 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
+@@ -23,148 +23,204 @@
+ #define MMAL_PARAMETERS_H
+ /** Common parameter ID group, used with many types of component. */
+-#define MMAL_PARAMETER_GROUP_COMMON            (0 << 16)
++#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
+ /** Camera-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CAMERA            (1 << 16)
++#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
+ /** Video-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_VIDEO             (2 << 16)
++#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
+ /** Audio-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_AUDIO             (3 << 16)
++#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
+ /** Clock-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CLOCK             (4 << 16)
++#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
+ /** Miracast-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_MIRACAST       (5 << 16)
++#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
+ /* Common parameters */
+ enum mmal_parameter_common_type {
+-      MMAL_PARAMETER_UNUSED  /**< Never a valid parameter ID */
+-              = MMAL_PARAMETER_GROUP_COMMON,
+-      MMAL_PARAMETER_SUPPORTED_ENCODINGS, /**< MMAL_PARAMETER_ENCODING_T */
+-      MMAL_PARAMETER_URI, /**< MMAL_PARAMETER_URI_T */
++      /**< Never a valid parameter ID */
++      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
+-      /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
++              /**< MMAL_PARAMETER_ENCODING_T */
++      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++              /**< MMAL_PARAMETER_URI_T */
++      MMAL_PARAMETER_URI,
++              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
+       MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
+-
+-      /** MMAL_PARAMETER_BOOLEAN_T */
++              /** MMAL_PARAMETER_BOOLEAN_T */
+       MMAL_PARAMETER_ZERO_COPY,
+-
+-      /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
++              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
+       MMAL_PARAMETER_BUFFER_REQUIREMENTS,
+-
+-      MMAL_PARAMETER_STATISTICS, /**< MMAL_PARAMETER_STATISTICS_T */
+-      MMAL_PARAMETER_CORE_STATISTICS, /**< MMAL_PARAMETER_CORE_STATISTICS_T */
+-      MMAL_PARAMETER_MEM_USAGE, /**< MMAL_PARAMETER_MEM_USAGE_T */
+-      MMAL_PARAMETER_BUFFER_FLAG_FILTER, /**< MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */
+-      MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */
+-      MMAL_PARAMETER_SYSTEM_TIME, /**< MMAL_PARAMETER_UINT64_T */
+-      MMAL_PARAMETER_NO_IMAGE_PADDING  /**< MMAL_PARAMETER_BOOLEAN_T */
++              /**< MMAL_PARAMETER_STATISTICS_T */
++      MMAL_PARAMETER_STATISTICS,
++              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
++      MMAL_PARAMETER_CORE_STATISTICS,
++              /**< MMAL_PARAMETER_MEM_USAGE_T */
++      MMAL_PARAMETER_MEM_USAGE,
++              /**< MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
++              /**< MMAL_PARAMETER_SEEK_T */
++      MMAL_PARAMETER_SEEK,
++              /**< MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_POWERMON_ENABLE,
++              /**< MMAL_PARAMETER_LOGGING_T */
++      MMAL_PARAMETER_LOGGING,
++              /**< MMAL_PARAMETER_UINT64_T */
++      MMAL_PARAMETER_SYSTEM_TIME,
++              /**< MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_NO_IMAGE_PADDING,
+ };
+ /* camera parameters */
+ enum mmal_parameter_camera_type {
+       /* 0 */
+-      /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
+-      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION
+-              = MMAL_PARAMETER_GROUP_CAMERA,
+-      MMAL_PARAMETER_CAPTURE_QUALITY, /**< Unused? */
+-      MMAL_PARAMETER_ROTATION, /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_EXIF_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_EXIF, /**< @ref MMAL_PARAMETER_EXIF_T */
+-      MMAL_PARAMETER_AWB_MODE, /**< @ref MMAL_PARAM_AWBMODE_T */
+-      MMAL_PARAMETER_IMAGE_EFFECT, /**< @ref MMAL_PARAMETER_IMAGEFX_T */
+-      MMAL_PARAMETER_COLOUR_EFFECT, /**< @ref MMAL_PARAMETER_COLOURFX_T */
+-      MMAL_PARAMETER_FLICKER_AVOID, /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
+-      MMAL_PARAMETER_FLASH, /**< @ref MMAL_PARAMETER_FLASH_T */
+-      MMAL_PARAMETER_REDEYE, /**< @ref MMAL_PARAMETER_REDEYE_T */
+-      MMAL_PARAMETER_FOCUS, /**< @ref MMAL_PARAMETER_FOCUS_T */
+-      MMAL_PARAMETER_FOCAL_LENGTHS, /**< Unused? */
+-      MMAL_PARAMETER_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_ZOOM, /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
+-      MMAL_PARAMETER_MIRROR, /**< @ref MMAL_PARAMETER_MIRROR_T */
++              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
++      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
++              MMAL_PARAMETER_GROUP_CAMERA,
++              /**< Unused? */
++      MMAL_PARAMETER_CAPTURE_QUALITY,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_ROTATION,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_EXIF_DISABLE,
++              /**< @ref MMAL_PARAMETER_EXIF_T */
++      MMAL_PARAMETER_EXIF,
++              /**< @ref MMAL_PARAM_AWBMODE_T */
++      MMAL_PARAMETER_AWB_MODE,
++              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
++      MMAL_PARAMETER_IMAGE_EFFECT,
++              /**< @ref MMAL_PARAMETER_COLOURFX_T */
++      MMAL_PARAMETER_COLOUR_EFFECT,
++              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
++      MMAL_PARAMETER_FLICKER_AVOID,
++              /**< @ref MMAL_PARAMETER_FLASH_T */
++      MMAL_PARAMETER_FLASH,
++              /**< @ref MMAL_PARAMETER_REDEYE_T */
++      MMAL_PARAMETER_REDEYE,
++              /**< @ref MMAL_PARAMETER_FOCUS_T */
++      MMAL_PARAMETER_FOCUS,
++              /**< Unused? */
++      MMAL_PARAMETER_FOCAL_LENGTHS,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_EXPOSURE_COMP,
++              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
++      MMAL_PARAMETER_ZOOM,
++              /**< @ref MMAL_PARAMETER_MIRROR_T */
++      MMAL_PARAMETER_MIRROR,
+       /* 0x10 */
+-      MMAL_PARAMETER_CAMERA_NUM, /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_EXPOSURE_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
+-      MMAL_PARAMETER_EXP_METERING_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
+-      MMAL_PARAMETER_FOCUS_STATUS, /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
+-      MMAL_PARAMETER_CAMERA_CONFIG, /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
+-      MMAL_PARAMETER_CAPTURE_STATUS, /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
+-      MMAL_PARAMETER_FACE_TRACK, /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
+-      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_JPEG_Q_FACTOR, /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_FRAME_RATE, /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
+-      MMAL_PARAMETER_USE_STC, /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
+-      MMAL_PARAMETER_CAMERA_INFO, /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
+-      MMAL_PARAMETER_VIDEO_STABILISATION, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_FACE_TRACK_RESULTS, /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
+-      MMAL_PARAMETER_ENABLE_RAW_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_CAMERA_NUM,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_CAPTURE,
++              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
++      MMAL_PARAMETER_EXPOSURE_MODE,
++              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
++      MMAL_PARAMETER_EXP_METERING_MODE,
++              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
++      MMAL_PARAMETER_FOCUS_STATUS,
++              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
++      MMAL_PARAMETER_CAMERA_CONFIG,
++              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
++      MMAL_PARAMETER_CAPTURE_STATUS,
++              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
++      MMAL_PARAMETER_FACE_TRACK,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_JPEG_Q_FACTOR,
++              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
++      MMAL_PARAMETER_FRAME_RATE,
++              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
++      MMAL_PARAMETER_USE_STC,
++              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
++      MMAL_PARAMETER_CAMERA_INFO,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_STABILISATION,
++              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
++      MMAL_PARAMETER_FACE_TRACK_RESULTS,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
+       /* 0x20 */
+-      MMAL_PARAMETER_DPF_FILE, /**< @ref MMAL_PARAMETER_URI_T */
+-      MMAL_PARAMETER_ENABLE_DPF_FILE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_DPF_FAIL_IS_FATAL, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_CAPTURE_MODE, /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
+-      MMAL_PARAMETER_FOCUS_REGIONS, /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
+-      MMAL_PARAMETER_INPUT_CROP, /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
+-      MMAL_PARAMETER_SENSOR_INFORMATION, /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
+-      MMAL_PARAMETER_FLASH_SELECT, /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
+-      MMAL_PARAMETER_FIELD_OF_VIEW, /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
+-      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, /**< @ref MMAL_PARAMETER_DRC_T */
+-      MMAL_PARAMETER_ALGORITHM_CONTROL, /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
+-      MMAL_PARAMETER_SHARPNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_CONTRAST, /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_BRIGHTNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_SATURATION, /**< @ref MMAL_PARAMETER_RATIONAL_T */
++              /**< @ref MMAL_PARAMETER_URI_T */
++      MMAL_PARAMETER_DPF_FILE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_DPF_FILE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
++              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
++      MMAL_PARAMETER_CAPTURE_MODE,
++              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
++      MMAL_PARAMETER_FOCUS_REGIONS,
++              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
++      MMAL_PARAMETER_INPUT_CROP,
++              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
++      MMAL_PARAMETER_SENSOR_INFORMATION,
++              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
++      MMAL_PARAMETER_FLASH_SELECT,
++              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
++      MMAL_PARAMETER_FIELD_OF_VIEW,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
++              /**< @ref MMAL_PARAMETER_DRC_T */
++      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
++              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
++      MMAL_PARAMETER_ALGORITHM_CONTROL,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_SHARPNESS,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_CONTRAST,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_BRIGHTNESS,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_SATURATION,
+       /* 0x30 */
+-      MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-
+-      /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_ISO,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ANTISHAKE,
++              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
+       MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+       MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T */
++              /** @ref MMAL_PARAMETER_UINT32_T */
+       MMAL_PARAMETER_CAMERA_MIN_ISO,
+-
+-      /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
++              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
+       MMAL_PARAMETER_CAMERA_USE_CASE,
+-
+-      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+       MMAL_PARAMETER_CAPTURE_STATS_PASS,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T */
++              /** @ref MMAL_PARAMETER_UINT32_T */
+       MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+       MMAL_PARAMETER_ENABLE_REGISTER_FILE,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+       MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
+-
+-      /** @ref MMAL_PARAMETER_CONFIGFILE_T */
++              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
+       MMAL_PARAMETER_CONFIGFILE_REGISTERS,
+-
+-      /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
++              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
+       MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
+-      MMAL_PARAMETER_JPEG_ATTACH_LOG, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ZERO_SHUTTER_LAG, /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
+-      MMAL_PARAMETER_FPS_RANGE, /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
+-      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_JPEG_ATTACH_LOG,
++              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
++      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
++              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
++      MMAL_PARAMETER_FPS_RANGE,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
+       /* 0x40 */
+-      MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_SHUTTER_SPEED,             /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CUSTOM_AWB_GAINS,          /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_FLASH_REQUIRED,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_SW_SATURATION_DISABLE,
++      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_SHUTTER_SPEED,
++              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
++      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
+ };
+ struct mmal_parameter_rational {
+@@ -411,7 +467,8 @@ enum mmal_parameter_video_type {
+       MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
+       /** @ref MMAL_PARAMETER_UINT32_T.
+-       * Setting the value to zero resets to the default (one slice per frame).
++       * Setting the value to zero resets to the default (one slice per
++       * frame).
+        */
+       MMAL_PARAMETER_MB_ROWS_PER_SLICE,
diff --git a/target/linux/brcm2708/patches-4.19/950-0229-staging-bcm2835-camera-Fix-multiple-assignments-shou.patch b/target/linux/brcm2708/patches-4.19/950-0229-staging-bcm2835-camera-Fix-multiple-assignments-shou.patch
deleted file mode 100644 (file)
index 34bbe82..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From d1f9d21346c642fadb2676077b050106afaf7579 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 15:58:14 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix multiple assignments
- should be avoided
-
-Clear checkpatch complaints of "multiple assignments should be avoided"
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c    | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -1065,11 +1065,12 @@ static int mmal_setup_components(struct
-               /* Make a further decision on port based on resolution */
-               if (f->fmt.pix.width <= max_video_width &&
-                   f->fmt.pix.height <= max_video_height)
--                      camera_port = port =
-+                      camera_port =
-                           &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
-               else
--                      camera_port = port =
-+                      camera_port =
-                           &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
-+              port = camera_port;
-               break;
-       case COMP_IMAGE_ENCODE:
-               encode_component = dev->component[COMP_IMAGE_ENCODE];
diff --git a/target/linux/brcm2708/patches-4.19/950-0229-staging-bcm2835-camera-Use-enums-for-max-value-in-co.patch b/target/linux/brcm2708/patches-4.19/950-0229-staging-bcm2835-camera-Use-enums-for-max-value-in-co.patch
new file mode 100644 (file)
index 0000000..2d3b540
--- /dev/null
@@ -0,0 +1,112 @@
+From 316725374b7c221f5d43b31ee9cbe738d3df4709 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 28 Sep 2018 10:17:11 +0100
+Subject: [PATCH] staging: bcm2835-camera: Use enums for max value in
+ controls
+
+Controls of type MMAL_CONTROL_TYPE_STD_MENU call v4l2_ctrl_new_std_menu
+with a max value and a mask. The max value is one of the defined
+values for the control, however in the config array there are several
+entries where raw numbers have been used instead. Replace these
+with the appropriate enum.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/controls.c   | 37 +++++++------------
+ 1 file changed, 13 insertions(+), 24 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -58,19 +58,6 @@ static const uint32_t iso_values[] = {
+       0, 100, 200, 400, 800,
+ };
+-static const s64 mains_freq_qmenu[] = {
+-      V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
+-      V4L2_CID_POWER_LINE_FREQUENCY_50HZ,
+-      V4L2_CID_POWER_LINE_FREQUENCY_60HZ,
+-      V4L2_CID_POWER_LINE_FREQUENCY_AUTO
+-};
+-
+-/* Supported video encode modes */
+-static const s64 bitrate_mode_qmenu[] = {
+-      (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+-      (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+-};
+-
+ enum bm2835_mmal_ctrl_type {
+       MMAL_CONTROL_TYPE_STD,
+       MMAL_CONTROL_TYPE_STD_MENU,
+@@ -966,8 +953,8 @@ static const struct bm2835_mmal_v4l2_ctr
+       },
+       {
+               V4L2_CID_ISO_SENSITIVITY_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
+-              0, 1, V4L2_ISO_SENSITIVITY_AUTO, 1, NULL,
+-              MMAL_PARAMETER_ISO,
++              0, V4L2_ISO_SENSITIVITY_AUTO, V4L2_ISO_SENSITIVITY_AUTO, 1,
++              NULL, MMAL_PARAMETER_ISO,
+               &ctrl_set_iso,
+               false
+       },
+@@ -984,8 +971,8 @@ static const struct bm2835_mmal_v4l2_ctr
+  */
+       {
+               V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
+-              ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
+-              MMAL_PARAMETER_EXPOSURE_MODE,
++              ~0x03, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
++              NULL, MMAL_PARAMETER_EXPOSURE_MODE,
+               &ctrl_set_exposure,
+               false
+       },
+@@ -1021,7 +1008,8 @@ static const struct bm2835_mmal_v4l2_ctr
+       {
+               V4L2_CID_EXPOSURE_METERING,
+               MMAL_CONTROL_TYPE_STD_MENU,
+-              ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
++              ~0x7, V4L2_EXPOSURE_METERING_SPOT,
++              V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
+               MMAL_PARAMETER_EXP_METERING_MODE,
+               &ctrl_set_metering_mode,
+               false
+@@ -1029,7 +1017,8 @@ static const struct bm2835_mmal_v4l2_ctr
+       {
+               V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+               MMAL_CONTROL_TYPE_STD_MENU,
+-              ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
++              ~0x3ff, V4L2_WHITE_BALANCE_SHADE, V4L2_WHITE_BALANCE_AUTO, 0,
++              NULL,
+               MMAL_PARAMETER_AWB_MODE,
+               &ctrl_set_awb_mode,
+               false
+@@ -1050,7 +1039,7 @@ static const struct bm2835_mmal_v4l2_ctr
+       },
+       {
+               V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
+-              0, 15, V4L2_COLORFX_NONE, 0, NULL,
++              0, V4L2_COLORFX_SET_CBCR, V4L2_COLORFX_NONE, 0, NULL,
+               MMAL_PARAMETER_IMAGE_EFFECT,
+               &ctrl_set_image_effect,
+               false
+@@ -1085,8 +1074,8 @@ static const struct bm2835_mmal_v4l2_ctr
+       },
+       {
+               V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
+-              0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
+-              0, 0, bitrate_mode_qmenu,
++              0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
++              0, 0, NULL,
+               MMAL_PARAMETER_RATECONTROL,
+               &ctrl_set_bitrate_mode,
+               false
+@@ -1108,8 +1097,8 @@ static const struct bm2835_mmal_v4l2_ctr
+       },
+       {
+               V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
+-              0, ARRAY_SIZE(mains_freq_qmenu) - 1,
+-              1, 1, mains_freq_qmenu,
++              0, V4L2_CID_POWER_LINE_FREQUENCY_AUTO,
++              1, 1, NULL,
+               MMAL_PARAMETER_FLICKER_AVOID,
+               &ctrl_set_flicker_avoidance,
+               false
diff --git a/target/linux/brcm2708/patches-4.19/950-0230-staging-bcm2835-camera-Correct-V4L2_CID_COLORFX_CBCR.patch b/target/linux/brcm2708/patches-4.19/950-0230-staging-bcm2835-camera-Correct-V4L2_CID_COLORFX_CBCR.patch
new file mode 100644 (file)
index 0000000..0272305
--- /dev/null
@@ -0,0 +1,34 @@
+From f07147faddeb0e99bfe181af78fcda9ea7f06c3d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 8 Oct 2018 18:26:15 +0100
+Subject: [PATCH] staging: bcm2835-camera: Correct
+ V4L2_CID_COLORFX_CBCR behaviour
+
+With V4L2_CID_COLORFX_CBCR calling ctrl_set_colfx it was incorrectly
+assigning the colour values to the enable field of dev->colourfx
+instead of the u and v fields.
+
+Correct the assignments.
+
+Reported as a Coverity issue
+Detected by CoverityScan CID#1419711 ("Unused value")
+
+Reported-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/controls.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -578,8 +578,8 @@ static int ctrl_set_colfx(struct bm2835_
+       control = &dev->component[COMP_CAMERA]->control;
+-      dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
+-      dev->colourfx.enable = ctrl->val & 0xff;
++      dev->colourfx.u = (ctrl->val & 0xff00) >> 8;
++      dev->colourfx.v = ctrl->val & 0xff;
+       ret = vchiq_mmal_port_parameter_set(dev->instance, control,
+                                           MMAL_PARAMETER_COLOUR_EFFECT,
diff --git a/target/linux/brcm2708/patches-4.19/950-0230-staging-bcm2835-camera-Fix-up-all-formatting-in-mmal.patch b/target/linux/brcm2708/patches-4.19/950-0230-staging-bcm2835-camera-Fix-up-all-formatting-in-mmal.patch
deleted file mode 100644 (file)
index 254664b..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-From be10ef41af683e175521f80b49b99d7ddeac2f2c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 16:08:41 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix up all formatting in
- mmal-paramters.h
-
-Fixes up all checkpatch errors in mmal-parameters.h
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/mmal-parameters.h          | 273 +++++++++++-------
- 1 file changed, 165 insertions(+), 108 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-@@ -23,148 +23,204 @@
- #define MMAL_PARAMETERS_H
- /** Common parameter ID group, used with many types of component. */
--#define MMAL_PARAMETER_GROUP_COMMON            (0 << 16)
-+#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
- /** Camera-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CAMERA            (1 << 16)
-+#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
- /** Video-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_VIDEO             (2 << 16)
-+#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
- /** Audio-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_AUDIO             (3 << 16)
-+#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
- /** Clock-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CLOCK             (4 << 16)
-+#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
- /** Miracast-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_MIRACAST       (5 << 16)
-+#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
- /* Common parameters */
- enum mmal_parameter_common_type {
--      MMAL_PARAMETER_UNUSED  /**< Never a valid parameter ID */
--              = MMAL_PARAMETER_GROUP_COMMON,
--      MMAL_PARAMETER_SUPPORTED_ENCODINGS, /**< MMAL_PARAMETER_ENCODING_T */
--      MMAL_PARAMETER_URI, /**< MMAL_PARAMETER_URI_T */
-+      /**< Never a valid parameter ID */
-+      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
--      /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
-+              /**< MMAL_PARAMETER_ENCODING_T */
-+      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+              /**< MMAL_PARAMETER_URI_T */
-+      MMAL_PARAMETER_URI,
-+              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
-       MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
--
--      /** MMAL_PARAMETER_BOOLEAN_T */
-+              /** MMAL_PARAMETER_BOOLEAN_T */
-       MMAL_PARAMETER_ZERO_COPY,
--
--      /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
-+              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
-       MMAL_PARAMETER_BUFFER_REQUIREMENTS,
--
--      MMAL_PARAMETER_STATISTICS, /**< MMAL_PARAMETER_STATISTICS_T */
--      MMAL_PARAMETER_CORE_STATISTICS, /**< MMAL_PARAMETER_CORE_STATISTICS_T */
--      MMAL_PARAMETER_MEM_USAGE, /**< MMAL_PARAMETER_MEM_USAGE_T */
--      MMAL_PARAMETER_BUFFER_FLAG_FILTER, /**< MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */
--      MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */
--      MMAL_PARAMETER_SYSTEM_TIME, /**< MMAL_PARAMETER_UINT64_T */
--      MMAL_PARAMETER_NO_IMAGE_PADDING  /**< MMAL_PARAMETER_BOOLEAN_T */
-+              /**< MMAL_PARAMETER_STATISTICS_T */
-+      MMAL_PARAMETER_STATISTICS,
-+              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
-+      MMAL_PARAMETER_CORE_STATISTICS,
-+              /**< MMAL_PARAMETER_MEM_USAGE_T */
-+      MMAL_PARAMETER_MEM_USAGE,
-+              /**< MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
-+              /**< MMAL_PARAMETER_SEEK_T */
-+      MMAL_PARAMETER_SEEK,
-+              /**< MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_POWERMON_ENABLE,
-+              /**< MMAL_PARAMETER_LOGGING_T */
-+      MMAL_PARAMETER_LOGGING,
-+              /**< MMAL_PARAMETER_UINT64_T */
-+      MMAL_PARAMETER_SYSTEM_TIME,
-+              /**< MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_NO_IMAGE_PADDING,
- };
- /* camera parameters */
- enum mmal_parameter_camera_type {
-       /* 0 */
--      /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
--      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION
--              = MMAL_PARAMETER_GROUP_CAMERA,
--      MMAL_PARAMETER_CAPTURE_QUALITY, /**< Unused? */
--      MMAL_PARAMETER_ROTATION, /**< @ref MMAL_PARAMETER_INT32_T */
--      MMAL_PARAMETER_EXIF_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_EXIF, /**< @ref MMAL_PARAMETER_EXIF_T */
--      MMAL_PARAMETER_AWB_MODE, /**< @ref MMAL_PARAM_AWBMODE_T */
--      MMAL_PARAMETER_IMAGE_EFFECT, /**< @ref MMAL_PARAMETER_IMAGEFX_T */
--      MMAL_PARAMETER_COLOUR_EFFECT, /**< @ref MMAL_PARAMETER_COLOURFX_T */
--      MMAL_PARAMETER_FLICKER_AVOID, /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
--      MMAL_PARAMETER_FLASH, /**< @ref MMAL_PARAMETER_FLASH_T */
--      MMAL_PARAMETER_REDEYE, /**< @ref MMAL_PARAMETER_REDEYE_T */
--      MMAL_PARAMETER_FOCUS, /**< @ref MMAL_PARAMETER_FOCUS_T */
--      MMAL_PARAMETER_FOCAL_LENGTHS, /**< Unused? */
--      MMAL_PARAMETER_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
--      MMAL_PARAMETER_ZOOM, /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
--      MMAL_PARAMETER_MIRROR, /**< @ref MMAL_PARAMETER_MIRROR_T */
-+              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
-+      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
-+              MMAL_PARAMETER_GROUP_CAMERA,
-+              /**< Unused? */
-+      MMAL_PARAMETER_CAPTURE_QUALITY,
-+              /**< @ref MMAL_PARAMETER_INT32_T */
-+      MMAL_PARAMETER_ROTATION,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_EXIF_DISABLE,
-+              /**< @ref MMAL_PARAMETER_EXIF_T */
-+      MMAL_PARAMETER_EXIF,
-+              /**< @ref MMAL_PARAM_AWBMODE_T */
-+      MMAL_PARAMETER_AWB_MODE,
-+              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
-+      MMAL_PARAMETER_IMAGE_EFFECT,
-+              /**< @ref MMAL_PARAMETER_COLOURFX_T */
-+      MMAL_PARAMETER_COLOUR_EFFECT,
-+              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
-+      MMAL_PARAMETER_FLICKER_AVOID,
-+              /**< @ref MMAL_PARAMETER_FLASH_T */
-+      MMAL_PARAMETER_FLASH,
-+              /**< @ref MMAL_PARAMETER_REDEYE_T */
-+      MMAL_PARAMETER_REDEYE,
-+              /**< @ref MMAL_PARAMETER_FOCUS_T */
-+      MMAL_PARAMETER_FOCUS,
-+              /**< Unused? */
-+      MMAL_PARAMETER_FOCAL_LENGTHS,
-+              /**< @ref MMAL_PARAMETER_INT32_T */
-+      MMAL_PARAMETER_EXPOSURE_COMP,
-+              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
-+      MMAL_PARAMETER_ZOOM,
-+              /**< @ref MMAL_PARAMETER_MIRROR_T */
-+      MMAL_PARAMETER_MIRROR,
-       /* 0x10 */
--      MMAL_PARAMETER_CAMERA_NUM, /**< @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_EXPOSURE_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
--      MMAL_PARAMETER_EXP_METERING_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
--      MMAL_PARAMETER_FOCUS_STATUS, /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
--      MMAL_PARAMETER_CAMERA_CONFIG, /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
--      MMAL_PARAMETER_CAPTURE_STATUS, /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
--      MMAL_PARAMETER_FACE_TRACK, /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
--      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_JPEG_Q_FACTOR, /**< @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_FRAME_RATE, /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
--      MMAL_PARAMETER_USE_STC, /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
--      MMAL_PARAMETER_CAMERA_INFO, /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
--      MMAL_PARAMETER_VIDEO_STABILISATION, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_FACE_TRACK_RESULTS, /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
--      MMAL_PARAMETER_ENABLE_RAW_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+              /**< @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_CAMERA_NUM,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_CAPTURE,
-+              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
-+      MMAL_PARAMETER_EXPOSURE_MODE,
-+              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
-+      MMAL_PARAMETER_EXP_METERING_MODE,
-+              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
-+      MMAL_PARAMETER_FOCUS_STATUS,
-+              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
-+      MMAL_PARAMETER_CAMERA_CONFIG,
-+              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
-+      MMAL_PARAMETER_CAPTURE_STATUS,
-+              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
-+      MMAL_PARAMETER_FACE_TRACK,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
-+              /**< @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_JPEG_Q_FACTOR,
-+              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
-+      MMAL_PARAMETER_FRAME_RATE,
-+              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
-+      MMAL_PARAMETER_USE_STC,
-+              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
-+      MMAL_PARAMETER_CAMERA_INFO,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_STABILISATION,
-+              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
-+      MMAL_PARAMETER_FACE_TRACK_RESULTS,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
-       /* 0x20 */
--      MMAL_PARAMETER_DPF_FILE, /**< @ref MMAL_PARAMETER_URI_T */
--      MMAL_PARAMETER_ENABLE_DPF_FILE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_DPF_FAIL_IS_FATAL, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_CAPTURE_MODE, /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
--      MMAL_PARAMETER_FOCUS_REGIONS, /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
--      MMAL_PARAMETER_INPUT_CROP, /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
--      MMAL_PARAMETER_SENSOR_INFORMATION, /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
--      MMAL_PARAMETER_FLASH_SELECT, /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
--      MMAL_PARAMETER_FIELD_OF_VIEW, /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
--      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, /**< @ref MMAL_PARAMETER_DRC_T */
--      MMAL_PARAMETER_ALGORITHM_CONTROL, /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
--      MMAL_PARAMETER_SHARPNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
--      MMAL_PARAMETER_CONTRAST, /**< @ref MMAL_PARAMETER_RATIONAL_T */
--      MMAL_PARAMETER_BRIGHTNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
--      MMAL_PARAMETER_SATURATION, /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+              /**< @ref MMAL_PARAMETER_URI_T */
-+      MMAL_PARAMETER_DPF_FILE,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ENABLE_DPF_FILE,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
-+              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
-+      MMAL_PARAMETER_CAPTURE_MODE,
-+              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
-+      MMAL_PARAMETER_FOCUS_REGIONS,
-+              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
-+      MMAL_PARAMETER_INPUT_CROP,
-+              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
-+      MMAL_PARAMETER_SENSOR_INFORMATION,
-+              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
-+      MMAL_PARAMETER_FLASH_SELECT,
-+              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
-+      MMAL_PARAMETER_FIELD_OF_VIEW,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
-+              /**< @ref MMAL_PARAMETER_DRC_T */
-+      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
-+              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
-+      MMAL_PARAMETER_ALGORITHM_CONTROL,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_SHARPNESS,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_CONTRAST,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_BRIGHTNESS,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_SATURATION,
-       /* 0x30 */
--      MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--
--      /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
-+              /**< @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_ISO,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ANTISHAKE,
-+              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
-       MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+              /** @ref MMAL_PARAMETER_BOOLEAN_T */
-       MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
--
--      /** @ref MMAL_PARAMETER_UINT32_T */
-+              /** @ref MMAL_PARAMETER_UINT32_T */
-       MMAL_PARAMETER_CAMERA_MIN_ISO,
--
--      /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
-+              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
-       MMAL_PARAMETER_CAMERA_USE_CASE,
--
--      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-       MMAL_PARAMETER_CAPTURE_STATS_PASS,
--
--      /** @ref MMAL_PARAMETER_UINT32_T */
-+              /** @ref MMAL_PARAMETER_UINT32_T */
-       MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+              /** @ref MMAL_PARAMETER_BOOLEAN_T */
-       MMAL_PARAMETER_ENABLE_REGISTER_FILE,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+              /** @ref MMAL_PARAMETER_BOOLEAN_T */
-       MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
--
--      /** @ref MMAL_PARAMETER_CONFIGFILE_T */
-+              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
-       MMAL_PARAMETER_CONFIGFILE_REGISTERS,
--
--      /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
-+              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
-       MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
--      MMAL_PARAMETER_JPEG_ATTACH_LOG, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_ZERO_SHUTTER_LAG, /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
--      MMAL_PARAMETER_FPS_RANGE, /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
--      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_JPEG_ATTACH_LOG,
-+              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
-+      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
-+              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
-+      MMAL_PARAMETER_FPS_RANGE,
-+              /**< @ref MMAL_PARAMETER_INT32_T */
-+      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
-       /* 0x40 */
--      MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_SHUTTER_SPEED,             /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_CUSTOM_AWB_GAINS,          /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_FLASH_REQUIRED,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_SW_SATURATION_DISABLE,
-+      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_SHUTTER_SPEED,
-+              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
-+      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
- };
- struct mmal_parameter_rational {
-@@ -411,7 +467,8 @@ enum mmal_parameter_video_type {
-       MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
-       /** @ref MMAL_PARAMETER_UINT32_T.
--       * Setting the value to zero resets to the default (one slice per frame).
-+       * Setting the value to zero resets to the default (one slice per
-+       * frame).
-        */
-       MMAL_PARAMETER_MB_ROWS_PER_SLICE,
diff --git a/target/linux/brcm2708/patches-4.19/950-0231-staging-bcm2835-camera-Remove-amend-some-obsolete-co.patch b/target/linux/brcm2708/patches-4.19/950-0231-staging-bcm2835-camera-Remove-amend-some-obsolete-co.patch
new file mode 100644 (file)
index 0000000..920249e
--- /dev/null
@@ -0,0 +1,49 @@
+From 37ede4f6a1771b09dea6e8b2fc4d2c5f085a33f3 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 28 Sep 2018 10:22:26 +0100
+Subject: [PATCH] staging: bcm2835-camera: Remove/amend some obsolete
+ comments
+
+Remove a todo which has been done.
+Remove a template line that was redundant.
+Make a comment clearer as to the non-obvious meaning of a field.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/controls.c   | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -965,10 +965,6 @@ static const struct bm2835_mmal_v4l2_ctr
+               &ctrl_set_value,
+               false
+       },
+-/*    {
+- *            0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
+- *    },
+- */
+       {
+               V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
+               ~0x03, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
+@@ -976,11 +972,6 @@ static const struct bm2835_mmal_v4l2_ctr
+               &ctrl_set_exposure,
+               false
+       },
+-/* todo this needs mixing in with set exposure
+- *    {
+- *            V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
+- *    },
+- */
+       {
+               V4L2_CID_EXPOSURE_ABSOLUTE, MMAL_CONTROL_TYPE_STD,
+               /* Units of 100usecs */
+@@ -1146,7 +1137,7 @@ static const struct bm2835_mmal_v4l2_ctr
+       },
+       {
+               V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
+-              -1,     /* Min is computed at runtime */
++              -1,     /* Min (mask) is computed at runtime */
+               V4L2_SCENE_MODE_TEXT,
+               V4L2_SCENE_MODE_NONE, 1, NULL,
+               MMAL_PARAMETER_PROFILE,
diff --git a/target/linux/brcm2708/patches-4.19/950-0231-staging-bcm2835-camera-Use-enums-for-max-value-in-co.patch b/target/linux/brcm2708/patches-4.19/950-0231-staging-bcm2835-camera-Use-enums-for-max-value-in-co.patch
deleted file mode 100644 (file)
index 2d3b540..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-From 316725374b7c221f5d43b31ee9cbe738d3df4709 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 28 Sep 2018 10:17:11 +0100
-Subject: [PATCH] staging: bcm2835-camera: Use enums for max value in
- controls
-
-Controls of type MMAL_CONTROL_TYPE_STD_MENU call v4l2_ctrl_new_std_menu
-with a max value and a mask. The max value is one of the defined
-values for the control, however in the config array there are several
-entries where raw numbers have been used instead. Replace these
-with the appropriate enum.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/controls.c   | 37 +++++++------------
- 1 file changed, 13 insertions(+), 24 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -58,19 +58,6 @@ static const uint32_t iso_values[] = {
-       0, 100, 200, 400, 800,
- };
--static const s64 mains_freq_qmenu[] = {
--      V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
--      V4L2_CID_POWER_LINE_FREQUENCY_50HZ,
--      V4L2_CID_POWER_LINE_FREQUENCY_60HZ,
--      V4L2_CID_POWER_LINE_FREQUENCY_AUTO
--};
--
--/* Supported video encode modes */
--static const s64 bitrate_mode_qmenu[] = {
--      (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
--      (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
--};
--
- enum bm2835_mmal_ctrl_type {
-       MMAL_CONTROL_TYPE_STD,
-       MMAL_CONTROL_TYPE_STD_MENU,
-@@ -966,8 +953,8 @@ static const struct bm2835_mmal_v4l2_ctr
-       },
-       {
-               V4L2_CID_ISO_SENSITIVITY_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
--              0, 1, V4L2_ISO_SENSITIVITY_AUTO, 1, NULL,
--              MMAL_PARAMETER_ISO,
-+              0, V4L2_ISO_SENSITIVITY_AUTO, V4L2_ISO_SENSITIVITY_AUTO, 1,
-+              NULL, MMAL_PARAMETER_ISO,
-               &ctrl_set_iso,
-               false
-       },
-@@ -984,8 +971,8 @@ static const struct bm2835_mmal_v4l2_ctr
-  */
-       {
-               V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
--              ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
--              MMAL_PARAMETER_EXPOSURE_MODE,
-+              ~0x03, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
-+              NULL, MMAL_PARAMETER_EXPOSURE_MODE,
-               &ctrl_set_exposure,
-               false
-       },
-@@ -1021,7 +1008,8 @@ static const struct bm2835_mmal_v4l2_ctr
-       {
-               V4L2_CID_EXPOSURE_METERING,
-               MMAL_CONTROL_TYPE_STD_MENU,
--              ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
-+              ~0x7, V4L2_EXPOSURE_METERING_SPOT,
-+              V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
-               MMAL_PARAMETER_EXP_METERING_MODE,
-               &ctrl_set_metering_mode,
-               false
-@@ -1029,7 +1017,8 @@ static const struct bm2835_mmal_v4l2_ctr
-       {
-               V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
-               MMAL_CONTROL_TYPE_STD_MENU,
--              ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
-+              ~0x3ff, V4L2_WHITE_BALANCE_SHADE, V4L2_WHITE_BALANCE_AUTO, 0,
-+              NULL,
-               MMAL_PARAMETER_AWB_MODE,
-               &ctrl_set_awb_mode,
-               false
-@@ -1050,7 +1039,7 @@ static const struct bm2835_mmal_v4l2_ctr
-       },
-       {
-               V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
--              0, 15, V4L2_COLORFX_NONE, 0, NULL,
-+              0, V4L2_COLORFX_SET_CBCR, V4L2_COLORFX_NONE, 0, NULL,
-               MMAL_PARAMETER_IMAGE_EFFECT,
-               &ctrl_set_image_effect,
-               false
-@@ -1085,8 +1074,8 @@ static const struct bm2835_mmal_v4l2_ctr
-       },
-       {
-               V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
--              0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
--              0, 0, bitrate_mode_qmenu,
-+              0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
-+              0, 0, NULL,
-               MMAL_PARAMETER_RATECONTROL,
-               &ctrl_set_bitrate_mode,
-               false
-@@ -1108,8 +1097,8 @@ static const struct bm2835_mmal_v4l2_ctr
-       },
-       {
-               V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
--              0, ARRAY_SIZE(mains_freq_qmenu) - 1,
--              1, 1, mains_freq_qmenu,
-+              0, V4L2_CID_POWER_LINE_FREQUENCY_AUTO,
-+              1, 1, NULL,
-               MMAL_PARAMETER_FLICKER_AVOID,
-               &ctrl_set_flicker_avoidance,
-               false
diff --git a/target/linux/brcm2708/patches-4.19/950-0232-staging-bcm2835-camera-Correct-V4L2_CID_COLORFX_CBCR.patch b/target/linux/brcm2708/patches-4.19/950-0232-staging-bcm2835-camera-Correct-V4L2_CID_COLORFX_CBCR.patch
deleted file mode 100644 (file)
index 0272305..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From f07147faddeb0e99bfe181af78fcda9ea7f06c3d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 8 Oct 2018 18:26:15 +0100
-Subject: [PATCH] staging: bcm2835-camera: Correct
- V4L2_CID_COLORFX_CBCR behaviour
-
-With V4L2_CID_COLORFX_CBCR calling ctrl_set_colfx it was incorrectly
-assigning the colour values to the enable field of dev->colourfx
-instead of the u and v fields.
-
-Correct the assignments.
-
-Reported as a Coverity issue
-Detected by CoverityScan CID#1419711 ("Unused value")
-
-Reported-by: Colin Ian King <colin.king@canonical.com>
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/controls.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -578,8 +578,8 @@ static int ctrl_set_colfx(struct bm2835_
-       control = &dev->component[COMP_CAMERA]->control;
--      dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
--      dev->colourfx.enable = ctrl->val & 0xff;
-+      dev->colourfx.u = (ctrl->val & 0xff00) >> 8;
-+      dev->colourfx.v = ctrl->val & 0xff;
-       ret = vchiq_mmal_port_parameter_set(dev->instance, control,
-                                           MMAL_PARAMETER_COLOUR_EFFECT,
diff --git a/target/linux/brcm2708/patches-4.19/950-0232-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch b/target/linux/brcm2708/patches-4.19/950-0232-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch
new file mode 100644 (file)
index 0000000..1cd23da
--- /dev/null
@@ -0,0 +1,7535 @@
+From e7723c6bcf31a440b8762e9e22497ff3fbbb7056 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:30:37 +0100
+Subject: [PATCH] staging: vc04_services: Split vchiq-mmal into a
+ module
+
+In preparation for adding a video codec V4L2 module which also
+wants to use vchiq-mmal functions, split it out into an
+independent module.
+The minimum number of changes have been made to achieve this
+(eg straight moves where possible) so existing checkpatch
+errors will still be present.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/Kconfig         |  1 +
+ drivers/staging/vc04_services/Makefile        |  1 +
+ .../vc04_services/bcm2835-camera/Kconfig      |  2 +-
+ .../vc04_services/bcm2835-camera/Makefile     |  4 ++--
+ .../staging/vc04_services/vchiq-mmal/Kconfig  |  7 ++++++
+ .../staging/vc04_services/vchiq-mmal/Makefile |  8 +++++++
+ .../mmal-common.h                             |  0
+ .../mmal-encodings.h                          |  0
+ .../mmal-msg-common.h                         |  0
+ .../mmal-msg-format.h                         |  0
+ .../mmal-msg-port.h                           |  0
+ .../{bcm2835-camera => vchiq-mmal}/mmal-msg.h |  0
+ .../mmal-parameters.h                         |  0
+ .../mmal-vchiq.c                              | 22 +++++++++++++++++++
+ .../mmal-vchiq.h                              |  0
+ 15 files changed, 42 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Kconfig
+ create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Makefile
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-common.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-encodings.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-common.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-format.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-port.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-parameters.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.c (98%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.h (100%)
+
+--- a/drivers/staging/vc04_services/Kconfig
++++ b/drivers/staging/vc04_services/Kconfig
+@@ -21,6 +21,7 @@ config BCM2835_VCHIQ
+ source "drivers/staging/vc04_services/bcm2835-audio/Kconfig"
+ source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
++source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
+ endif
+--- a/drivers/staging/vc04_services/Makefile
++++ b/drivers/staging/vc04_services/Makefile
+@@ -12,6 +12,7 @@ vchiq-objs := \
+ obj-$(CONFIG_SND_BCM2835)     += bcm2835-audio/
+ obj-$(CONFIG_VIDEO_BCM2835)   += bcm2835-camera/
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
+ ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
+--- a/drivers/staging/vc04_services/bcm2835-camera/Kconfig
++++ b/drivers/staging/vc04_services/bcm2835-camera/Kconfig
+@@ -2,7 +2,7 @@ config VIDEO_BCM2835
+       tristate "BCM2835 Camera"
+       depends on MEDIA_SUPPORT
+       depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
+-      select BCM2835_VCHIQ
++      select BCM2835_VCHIQ_MMAL
+       select VIDEOBUF2_VMALLOC
+       select BTREE
+       help
+--- a/drivers/staging/vc04_services/bcm2835-camera/Makefile
++++ b/drivers/staging/vc04_services/bcm2835-camera/Makefile
+@@ -1,11 +1,11 @@
+ # SPDX-License-Identifier: GPL-2.0
+ bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \
+       bcm2835-camera.o \
+-      controls.o \
+-      mmal-vchiq.o
++      controls.o
+ obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o
+ ccflags-y += \
+       -Idrivers/staging/vc04_services \
++      -Idrivers/staging/vc04_services/vchiq-mmal \
+       -D__VCCOREVER__=0x04000000
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
+@@ -0,0 +1,7 @@
++config BCM2835_VCHIQ_MMAL
++      tristate "BCM2835 MMAL VCHIQ service"
++      depends on (ARCH_BCM2835 || COMPILE_TEST)
++      select BCM2835_VCHIQ
++      help
++        Enables the MMAL API over VCHIQ as used for the
++        majority of the multimedia services on VideoCore.
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/Makefile
+@@ -0,0 +1,8 @@
++# SPDX-License-Identifier: GPL-2.0
++bcm2835-mmal-vchiq-objs := mmal-vchiq.o
++
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o
++
++ccflags-y += \
++      -Idrivers/staging/vc04_services \
++      -D__VCCOREVER__=0x04000000
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ /dev/null
+@@ -1,1899 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- *
+- * V4L2 driver MMAL vchiq interface code
+- */
+-
+-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+-
+-#include <linux/errno.h>
+-#include <linux/kernel.h>
+-#include <linux/mutex.h>
+-#include <linux/mm.h>
+-#include <linux/slab.h>
+-#include <linux/completion.h>
+-#include <linux/vmalloc.h>
+-#include <asm/cacheflush.h>
+-#include <media/videobuf2-vmalloc.h>
+-
+-#include "mmal-common.h"
+-#include "mmal-vchiq.h"
+-#include "mmal-msg.h"
+-
+-#define USE_VCHIQ_ARM
+-#include "interface/vchi/vchi.h"
+-
+-/* maximum number of components supported */
+-#define VCHIQ_MMAL_MAX_COMPONENTS 4
+-
+-/*#define FULL_MSG_DUMP 1*/
+-
+-#ifdef DEBUG
+-static const char *const msg_type_names[] = {
+-      "UNKNOWN",
+-      "QUIT",
+-      "SERVICE_CLOSED",
+-      "GET_VERSION",
+-      "COMPONENT_CREATE",
+-      "COMPONENT_DESTROY",
+-      "COMPONENT_ENABLE",
+-      "COMPONENT_DISABLE",
+-      "PORT_INFO_GET",
+-      "PORT_INFO_SET",
+-      "PORT_ACTION",
+-      "BUFFER_FROM_HOST",
+-      "BUFFER_TO_HOST",
+-      "GET_STATS",
+-      "PORT_PARAMETER_SET",
+-      "PORT_PARAMETER_GET",
+-      "EVENT_TO_HOST",
+-      "GET_CORE_STATS_FOR_PORT",
+-      "OPAQUE_ALLOCATOR",
+-      "CONSUME_MEM",
+-      "LMK",
+-      "OPAQUE_ALLOCATOR_DESC",
+-      "DRM_GET_LHS32",
+-      "DRM_GET_TIME",
+-      "BUFFER_FROM_HOST_ZEROLEN",
+-      "PORT_FLUSH",
+-      "HOST_LOG",
+-};
+-#endif
+-
+-static const char *const port_action_type_names[] = {
+-      "UNKNOWN",
+-      "ENABLE",
+-      "DISABLE",
+-      "FLUSH",
+-      "CONNECT",
+-      "DISCONNECT",
+-      "SET_REQUIREMENTS",
+-};
+-
+-#if defined(DEBUG)
+-#if defined(FULL_MSG_DUMP)
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
+-      do {                                                            \
+-              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
+-                       msg_type_names[(MSG)->h.type],                 \
+-                       (MSG)->h.type, (MSG_LEN));                     \
+-              print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
+-                             16, 4, (MSG),                            \
+-                             sizeof(struct mmal_msg_header), 1);      \
+-              print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
+-                             16, 4,                                   \
+-                             ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
+-                             (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
+-      } while (0)
+-#else
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
+-      {                                                               \
+-              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
+-                       msg_type_names[(MSG)->h.type],                 \
+-                       (MSG)->h.type, (MSG_LEN));                     \
+-      }
+-#endif
+-#else
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
+-#endif
+-
+-struct vchiq_mmal_instance;
+-
+-/* normal message context */
+-struct mmal_msg_context {
+-      struct vchiq_mmal_instance *instance;
+-
+-      /* Index in the context_map idr so that we can find the
+-       * mmal_msg_context again when servicing the VCHI reply.
+-       */
+-      int handle;
+-
+-      union {
+-              struct {
+-                      /* work struct for buffer_cb callback */
+-                      struct work_struct work;
+-                      /* work struct for deferred callback */
+-                      struct work_struct buffer_to_host_work;
+-                      /* mmal instance */
+-                      struct vchiq_mmal_instance *instance;
+-                      /* mmal port */
+-                      struct vchiq_mmal_port *port;
+-                      /* actual buffer used to store bulk reply */
+-                      struct mmal_buffer *buffer;
+-                      /* amount of buffer used */
+-                      unsigned long buffer_used;
+-                      /* MMAL buffer flags */
+-                      u32 mmal_flags;
+-                      /* Presentation and Decode timestamps */
+-                      s64 pts;
+-                      s64 dts;
+-
+-                      int status;     /* context status */
+-
+-              } bulk;         /* bulk data */
+-
+-              struct {
+-                      /* message handle to release */
+-                      VCHI_HELD_MSG_T msg_handle;
+-                      /* pointer to received message */
+-                      struct mmal_msg *msg;
+-                      /* received message length */
+-                      u32 msg_len;
+-                      /* completion upon reply */
+-                      struct completion cmplt;
+-              } sync;         /* synchronous response */
+-      } u;
+-
+-};
+-
+-struct vchiq_mmal_instance {
+-      VCHI_SERVICE_HANDLE_T handle;
+-
+-      /* ensure serialised access to service */
+-      struct mutex vchiq_mutex;
+-
+-      /* vmalloc page to receive scratch bulk xfers into */
+-      void *bulk_scratch;
+-
+-      struct idr context_map;
+-      /* protect accesses to context_map */
+-      struct mutex context_map_lock;
+-
+-      /* component to use next */
+-      int component_idx;
+-      struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
+-
+-      /* ordered workqueue to process all bulk operations */
+-      struct workqueue_struct *bulk_wq;
+-};
+-
+-static struct mmal_msg_context *
+-get_msg_context(struct vchiq_mmal_instance *instance)
+-{
+-      struct mmal_msg_context *msg_context;
+-      int handle;
+-
+-      /* todo: should this be allocated from a pool to avoid kzalloc */
+-      msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
+-
+-      if (!msg_context)
+-              return ERR_PTR(-ENOMEM);
+-
+-      /* Create an ID that will be passed along with our message so
+-       * that when we service the VCHI reply, we can look up what
+-       * message is being replied to.
+-       */
+-      mutex_lock(&instance->context_map_lock);
+-      handle = idr_alloc(&instance->context_map, msg_context,
+-                         0, 0, GFP_KERNEL);
+-      mutex_unlock(&instance->context_map_lock);
+-
+-      if (handle < 0) {
+-              kfree(msg_context);
+-              return ERR_PTR(handle);
+-      }
+-
+-      msg_context->instance = instance;
+-      msg_context->handle = handle;
+-
+-      return msg_context;
+-}
+-
+-static struct mmal_msg_context *
+-lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
+-{
+-      return idr_find(&instance->context_map, handle);
+-}
+-
+-static void
+-release_msg_context(struct mmal_msg_context *msg_context)
+-{
+-      struct vchiq_mmal_instance *instance = msg_context->instance;
+-
+-      mutex_lock(&instance->context_map_lock);
+-      idr_remove(&instance->context_map, msg_context->handle);
+-      mutex_unlock(&instance->context_map_lock);
+-      kfree(msg_context);
+-}
+-
+-/* deals with receipt of event to host message */
+-static void event_to_host_cb(struct vchiq_mmal_instance *instance,
+-                           struct mmal_msg *msg, u32 msg_len)
+-{
+-      pr_debug("unhandled event\n");
+-      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
+-               msg->u.event_to_host.client_component,
+-               msg->u.event_to_host.port_type,
+-               msg->u.event_to_host.port_num,
+-               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
+-}
+-
+-/* workqueue scheduled callback
+- *
+- * we do this because it is important we do not call any other vchiq
+- * sync calls from witin the message delivery thread
+- */
+-static void buffer_work_cb(struct work_struct *work)
+-{
+-      struct mmal_msg_context *msg_context =
+-              container_of(work, struct mmal_msg_context, u.bulk.work);
+-
+-      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
+-
+-      msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
+-                                          msg_context->u.bulk.port,
+-                                          msg_context->u.bulk.status,
+-                                          msg_context->u.bulk.buffer,
+-                                          msg_context->u.bulk.buffer_used,
+-                                          msg_context->u.bulk.mmal_flags,
+-                                          msg_context->u.bulk.dts,
+-                                          msg_context->u.bulk.pts);
+-}
+-
+-/* workqueue scheduled callback to handle receiving buffers
+- *
+- * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
+- * If we block in the service_callback context then we can't process the
+- * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
+- * vchi_bulk_queue_receive() call to complete.
+- */
+-static void buffer_to_host_work_cb(struct work_struct *work)
+-{
+-      struct mmal_msg_context *msg_context =
+-              container_of(work, struct mmal_msg_context,
+-                           u.bulk.buffer_to_host_work);
+-      struct vchiq_mmal_instance *instance = msg_context->instance;
+-      unsigned long len = msg_context->u.bulk.buffer_used;
+-      int ret;
+-
+-      if (!len)
+-              /* Dummy receive to ensure the buffers remain in order */
+-              len = 8;
+-      /* queue the bulk submission */
+-      vchi_service_use(instance->handle);
+-      ret = vchi_bulk_queue_receive(instance->handle,
+-                                    msg_context->u.bulk.buffer->buffer,
+-                                    /* Actual receive needs to be a multiple
+-                                     * of 4 bytes
+-                                     */
+-                                    (len + 3) & ~3,
+-                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
+-                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
+-                                    msg_context);
+-
+-      vchi_service_release(instance->handle);
+-
+-      if (ret != 0)
+-              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
+-                     __func__, msg_context, ret);
+-}
+-
+-/* enqueue a bulk receive for a given message context */
+-static int bulk_receive(struct vchiq_mmal_instance *instance,
+-                      struct mmal_msg *msg,
+-                      struct mmal_msg_context *msg_context)
+-{
+-      unsigned long rd_len;
+-
+-      rd_len = msg->u.buffer_from_host.buffer_header.length;
+-
+-      if (!msg_context->u.bulk.buffer) {
+-              pr_err("bulk.buffer not configured - error in buffer_from_host\n");
+-
+-              /* todo: this is a serious error, we should never have
+-               * committed a buffer_to_host operation to the mmal
+-               * port without the buffer to back it up (underflow
+-               * handling) and there is no obvious way to deal with
+-               * this - how is the mmal servie going to react when
+-               * we fail to do the xfer and reschedule a buffer when
+-               * it arrives? perhaps a starved flag to indicate a
+-               * waiting bulk receive?
+-               */
+-
+-              return -EINVAL;
+-      }
+-
+-      /* ensure we do not overrun the available buffer */
+-      if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
+-              rd_len = msg_context->u.bulk.buffer->buffer_size;
+-              pr_warn("short read as not enough receive buffer space\n");
+-              /* todo: is this the correct response, what happens to
+-               * the rest of the message data?
+-               */
+-      }
+-
+-      /* store length */
+-      msg_context->u.bulk.buffer_used = rd_len;
+-      msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
+-      msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
+-
+-      queue_work(msg_context->instance->bulk_wq,
+-                 &msg_context->u.bulk.buffer_to_host_work);
+-
+-      return 0;
+-}
+-
+-/* data in message, memcpy from packet into output buffer */
+-static int inline_receive(struct vchiq_mmal_instance *instance,
+-                        struct mmal_msg *msg,
+-                        struct mmal_msg_context *msg_context)
+-{
+-      memcpy(msg_context->u.bulk.buffer->buffer,
+-             msg->u.buffer_from_host.short_data,
+-             msg->u.buffer_from_host.payload_in_message);
+-
+-      msg_context->u.bulk.buffer_used =
+-          msg->u.buffer_from_host.payload_in_message;
+-
+-      return 0;
+-}
+-
+-/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
+-static int
+-buffer_from_host(struct vchiq_mmal_instance *instance,
+-               struct vchiq_mmal_port *port, struct mmal_buffer *buf)
+-{
+-      struct mmal_msg_context *msg_context;
+-      struct mmal_msg m;
+-      int ret;
+-
+-      if (!port->enabled)
+-              return -EINVAL;
+-
+-      pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
+-
+-      /* get context */
+-      if (!buf->msg_context) {
+-              pr_err("%s: msg_context not allocated, buf %p\n", __func__,
+-                     buf);
+-              return -EINVAL;
+-      }
+-      msg_context = buf->msg_context;
+-
+-      /* store bulk message context for when data arrives */
+-      msg_context->u.bulk.instance = instance;
+-      msg_context->u.bulk.port = port;
+-      msg_context->u.bulk.buffer = buf;
+-      msg_context->u.bulk.buffer_used = 0;
+-
+-      /* initialise work structure ready to schedule callback */
+-      INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
+-      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
+-                buffer_to_host_work_cb);
+-
+-      atomic_inc(&port->buffers_with_vpu);
+-
+-      /* prep the buffer from host message */
+-      memset(&m, 0xbc, sizeof(m));    /* just to make debug clearer */
+-
+-      m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
+-      m.h.magic = MMAL_MAGIC;
+-      m.h.context = msg_context->handle;
+-      m.h.status = 0;
+-
+-      /* drvbuf is our private data passed back */
+-      m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
+-      m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
+-      m.u.buffer_from_host.drvbuf.port_handle = port->handle;
+-      m.u.buffer_from_host.drvbuf.client_context = msg_context->handle;
+-
+-      /* buffer header */
+-      m.u.buffer_from_host.buffer_header.cmd = 0;
+-      m.u.buffer_from_host.buffer_header.data =
+-              (u32)(unsigned long)buf->buffer;
+-      m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
+-      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
+-      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
+-      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
+-      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
+-      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
+-
+-      /* clear buffer type sepecific data */
+-      memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
+-             sizeof(m.u.buffer_from_host.buffer_header_type_specific));
+-
+-      /* no payload in message */
+-      m.u.buffer_from_host.payload_in_message = 0;
+-
+-      vchi_service_use(instance->handle);
+-
+-      ret = vchi_queue_kernel_message(instance->handle,
+-                                      &m,
+-                                      sizeof(struct mmal_msg_header) +
+-                                      sizeof(m.u.buffer_from_host));
+-
+-      vchi_service_release(instance->handle);
+-
+-      return ret;
+-}
+-
+-/* deals with receipt of buffer to host message */
+-static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
+-                            struct mmal_msg *msg, u32 msg_len)
+-{
+-      struct mmal_msg_context *msg_context;
+-      u32 handle;
+-
+-      pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
+-               __func__, instance, msg, msg_len);
+-
+-      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
+-              handle = msg->u.buffer_from_host.drvbuf.client_context;
+-              msg_context = lookup_msg_context(instance, handle);
+-
+-              if (!msg_context) {
+-                      pr_err("drvbuf.client_context(%u) is invalid\n",
+-                             handle);
+-                      return;
+-              }
+-      } else {
+-              pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
+-              return;
+-      }
+-
+-      msg_context->u.bulk.mmal_flags =
+-                              msg->u.buffer_from_host.buffer_header.flags;
+-
+-      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
+-              /* message reception had an error */
+-              pr_warn("error %d in reply\n", msg->h.status);
+-
+-              msg_context->u.bulk.status = msg->h.status;
+-
+-      } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
+-              /* empty buffer */
+-              if (msg->u.buffer_from_host.buffer_header.flags &
+-                  MMAL_BUFFER_HEADER_FLAG_EOS) {
+-                      msg_context->u.bulk.status =
+-                          bulk_receive(instance, msg, msg_context);
+-                      if (msg_context->u.bulk.status == 0)
+-                              return; /* successful bulk submission, bulk
+-                                       * completion will trigger callback
+-                                       */
+-              } else {
+-                      /* do callback with empty buffer - not EOS though */
+-                      msg_context->u.bulk.status = 0;
+-                      msg_context->u.bulk.buffer_used = 0;
+-              }
+-      } else if (msg->u.buffer_from_host.payload_in_message == 0) {
+-              /* data is not in message, queue a bulk receive */
+-              msg_context->u.bulk.status =
+-                  bulk_receive(instance, msg, msg_context);
+-              if (msg_context->u.bulk.status == 0)
+-                      return; /* successful bulk submission, bulk
+-                               * completion will trigger callback
+-                               */
+-
+-              /* failed to submit buffer, this will end badly */
+-              pr_err("error %d on bulk submission\n",
+-                     msg_context->u.bulk.status);
+-
+-      } else if (msg->u.buffer_from_host.payload_in_message <=
+-                 MMAL_VC_SHORT_DATA) {
+-              /* data payload within message */
+-              msg_context->u.bulk.status = inline_receive(instance, msg,
+-                                                          msg_context);
+-      } else {
+-              pr_err("message with invalid short payload\n");
+-
+-              /* signal error */
+-              msg_context->u.bulk.status = -EINVAL;
+-              msg_context->u.bulk.buffer_used =
+-                  msg->u.buffer_from_host.payload_in_message;
+-      }
+-
+-      /* schedule the port callback */
+-      schedule_work(&msg_context->u.bulk.work);
+-}
+-
+-static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
+-                          struct mmal_msg_context *msg_context)
+-{
+-      msg_context->u.bulk.status = 0;
+-
+-      /* schedule the port callback */
+-      schedule_work(&msg_context->u.bulk.work);
+-}
+-
+-static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
+-                        struct mmal_msg_context *msg_context)
+-{
+-      pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
+-
+-      msg_context->u.bulk.status = -EINTR;
+-
+-      schedule_work(&msg_context->u.bulk.work);
+-}
+-
+-/* incoming event service callback */
+-static void service_callback(void *param,
+-                           const VCHI_CALLBACK_REASON_T reason,
+-                           void *bulk_ctx)
+-{
+-      struct vchiq_mmal_instance *instance = param;
+-      int status;
+-      u32 msg_len;
+-      struct mmal_msg *msg;
+-      VCHI_HELD_MSG_T msg_handle;
+-      struct mmal_msg_context *msg_context;
+-
+-      if (!instance) {
+-              pr_err("Message callback passed NULL instance\n");
+-              return;
+-      }
+-
+-      switch (reason) {
+-      case VCHI_CALLBACK_MSG_AVAILABLE:
+-              status = vchi_msg_hold(instance->handle, (void **)&msg,
+-                                     &msg_len, VCHI_FLAGS_NONE, &msg_handle);
+-              if (status) {
+-                      pr_err("Unable to dequeue a message (%d)\n", status);
+-                      break;
+-              }
+-
+-              DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
+-
+-              /* handling is different for buffer messages */
+-              switch (msg->h.type) {
+-              case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
+-                      vchi_held_msg_release(&msg_handle);
+-                      break;
+-
+-              case MMAL_MSG_TYPE_EVENT_TO_HOST:
+-                      event_to_host_cb(instance, msg, msg_len);
+-                      vchi_held_msg_release(&msg_handle);
+-
+-                      break;
+-
+-              case MMAL_MSG_TYPE_BUFFER_TO_HOST:
+-                      buffer_to_host_cb(instance, msg, msg_len);
+-                      vchi_held_msg_release(&msg_handle);
+-                      break;
+-
+-              default:
+-                      /* messages dependent on header context to complete */
+-                      if (!msg->h.context) {
+-                              pr_err("received message context was null!\n");
+-                              vchi_held_msg_release(&msg_handle);
+-                              break;
+-                      }
+-
+-                      msg_context = lookup_msg_context(instance,
+-                                                       msg->h.context);
+-                      if (!msg_context) {
+-                              pr_err("received invalid message context %u!\n",
+-                                     msg->h.context);
+-                              vchi_held_msg_release(&msg_handle);
+-                              break;
+-                      }
+-
+-                      /* fill in context values */
+-                      msg_context->u.sync.msg_handle = msg_handle;
+-                      msg_context->u.sync.msg = msg;
+-                      msg_context->u.sync.msg_len = msg_len;
+-
+-                      /* todo: should this check (completion_done()
+-                       * == 1) for no one waiting? or do we need a
+-                       * flag to tell us the completion has been
+-                       * interrupted so we can free the message and
+-                       * its context. This probably also solves the
+-                       * message arriving after interruption todo
+-                       * below
+-                       */
+-
+-                      /* complete message so caller knows it happened */
+-                      complete(&msg_context->u.sync.cmplt);
+-                      break;
+-              }
+-
+-              break;
+-
+-      case VCHI_CALLBACK_BULK_RECEIVED:
+-              bulk_receive_cb(instance, bulk_ctx);
+-              break;
+-
+-      case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
+-              bulk_abort_cb(instance, bulk_ctx);
+-              break;
+-
+-      case VCHI_CALLBACK_SERVICE_CLOSED:
+-              /* TODO: consider if this requires action if received when
+-               * driver is not explicitly closing the service
+-               */
+-              break;
+-
+-      default:
+-              pr_err("Received unhandled message reason %d\n", reason);
+-              break;
+-      }
+-}
+-
+-static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
+-                                   struct mmal_msg *msg,
+-                                   unsigned int payload_len,
+-                                   struct mmal_msg **msg_out,
+-                                   VCHI_HELD_MSG_T *msg_handle_out)
+-{
+-      struct mmal_msg_context *msg_context;
+-      int ret;
+-      unsigned long timeout;
+-
+-      /* payload size must not cause message to exceed max size */
+-      if (payload_len >
+-          (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
+-              pr_err("payload length %d exceeds max:%d\n", payload_len,
+-                     (int)(MMAL_MSG_MAX_SIZE -
+-                          sizeof(struct mmal_msg_header)));
+-              return -EINVAL;
+-      }
+-
+-      msg_context = get_msg_context(instance);
+-      if (IS_ERR(msg_context))
+-              return PTR_ERR(msg_context);
+-
+-      init_completion(&msg_context->u.sync.cmplt);
+-
+-      msg->h.magic = MMAL_MAGIC;
+-      msg->h.context = msg_context->handle;
+-      msg->h.status = 0;
+-
+-      DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
+-                   ">>> sync message");
+-
+-      vchi_service_use(instance->handle);
+-
+-      ret = vchi_queue_kernel_message(instance->handle,
+-                                      msg,
+-                                      sizeof(struct mmal_msg_header) +
+-                                      payload_len);
+-
+-      vchi_service_release(instance->handle);
+-
+-      if (ret) {
+-              pr_err("error %d queuing message\n", ret);
+-              release_msg_context(msg_context);
+-              return ret;
+-      }
+-
+-      timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
+-                                            3 * HZ);
+-      if (timeout == 0) {
+-              pr_err("timed out waiting for sync completion\n");
+-              ret = -ETIME;
+-              /* todo: what happens if the message arrives after aborting */
+-              release_msg_context(msg_context);
+-              return ret;
+-      }
+-
+-      *msg_out = msg_context->u.sync.msg;
+-      *msg_handle_out = msg_context->u.sync.msg_handle;
+-      release_msg_context(msg_context);
+-
+-      return 0;
+-}
+-
+-static void dump_port_info(struct vchiq_mmal_port *port)
+-{
+-      pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
+-
+-      pr_debug("buffer minimum num:%d size:%d align:%d\n",
+-               port->minimum_buffer.num,
+-               port->minimum_buffer.size, port->minimum_buffer.alignment);
+-
+-      pr_debug("buffer recommended num:%d size:%d align:%d\n",
+-               port->recommended_buffer.num,
+-               port->recommended_buffer.size,
+-               port->recommended_buffer.alignment);
+-
+-      pr_debug("buffer current values num:%d size:%d align:%d\n",
+-               port->current_buffer.num,
+-               port->current_buffer.size, port->current_buffer.alignment);
+-
+-      pr_debug("elementary stream: type:%d encoding:0x%x variant:0x%x\n",
+-               port->format.type,
+-               port->format.encoding, port->format.encoding_variant);
+-
+-      pr_debug("                  bitrate:%d flags:0x%x\n",
+-               port->format.bitrate, port->format.flags);
+-
+-      if (port->format.type == MMAL_ES_TYPE_VIDEO) {
+-              pr_debug
+-                  ("es video format: width:%d height:%d colourspace:0x%x\n",
+-                   port->es.video.width, port->es.video.height,
+-                   port->es.video.color_space);
+-
+-              pr_debug("               : crop xywh %d,%d,%d,%d\n",
+-                       port->es.video.crop.x,
+-                       port->es.video.crop.y,
+-                       port->es.video.crop.width, port->es.video.crop.height);
+-              pr_debug("               : framerate %d/%d  aspect %d/%d\n",
+-                       port->es.video.frame_rate.num,
+-                       port->es.video.frame_rate.den,
+-                       port->es.video.par.num, port->es.video.par.den);
+-      }
+-}
+-
+-static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
+-{
+-      /* todo do readonly fields need setting at all? */
+-      p->type = port->type;
+-      p->index = port->index;
+-      p->index_all = 0;
+-      p->is_enabled = port->enabled;
+-      p->buffer_num_min = port->minimum_buffer.num;
+-      p->buffer_size_min = port->minimum_buffer.size;
+-      p->buffer_alignment_min = port->minimum_buffer.alignment;
+-      p->buffer_num_recommended = port->recommended_buffer.num;
+-      p->buffer_size_recommended = port->recommended_buffer.size;
+-
+-      /* only three writable fields in a port */
+-      p->buffer_num = port->current_buffer.num;
+-      p->buffer_size = port->current_buffer.size;
+-      p->userdata = (u32)(unsigned long)port;
+-}
+-
+-static int port_info_set(struct vchiq_mmal_instance *instance,
+-                       struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      pr_debug("setting port info port %p\n", port);
+-      if (!port)
+-              return -1;
+-      dump_port_info(port);
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
+-
+-      m.u.port_info_set.component_handle = port->component->handle;
+-      m.u.port_info_set.port_type = port->type;
+-      m.u.port_info_set.port_index = port->index;
+-
+-      port_to_mmal_msg(port, &m.u.port_info_set.port);
+-
+-      /* elementary stream format setup */
+-      m.u.port_info_set.format.type = port->format.type;
+-      m.u.port_info_set.format.encoding = port->format.encoding;
+-      m.u.port_info_set.format.encoding_variant =
+-          port->format.encoding_variant;
+-      m.u.port_info_set.format.bitrate = port->format.bitrate;
+-      m.u.port_info_set.format.flags = port->format.flags;
+-
+-      memcpy(&m.u.port_info_set.es, &port->es,
+-             sizeof(union mmal_es_specific_format));
+-
+-      m.u.port_info_set.format.extradata_size = port->format.extradata_size;
+-      memcpy(&m.u.port_info_set.extradata, port->format.extradata,
+-             port->format.extradata_size);
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_info_set),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      /* return operation status */
+-      ret = -rmsg->u.port_info_get_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
+-               port->component->handle, port->handle);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* use port info get message to retrieve port information */
+-static int port_info_get(struct vchiq_mmal_instance *instance,
+-                       struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      /* port info time */
+-      m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
+-      m.u.port_info_get.component_handle = port->component->handle;
+-      m.u.port_info_get.port_type = port->type;
+-      m.u.port_info_get.index = port->index;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_info_get),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      /* return operation status */
+-      ret = -rmsg->u.port_info_get_reply.status;
+-      if (ret != MMAL_MSG_STATUS_SUCCESS)
+-              goto release_msg;
+-
+-      if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
+-              port->enabled = false;
+-      else
+-              port->enabled = true;
+-
+-      /* copy the values out of the message */
+-      port->handle = rmsg->u.port_info_get_reply.port_handle;
+-
+-      /* port type and index cached to use on port info set because
+-       * it does not use a port handle
+-       */
+-      port->type = rmsg->u.port_info_get_reply.port_type;
+-      port->index = rmsg->u.port_info_get_reply.port_index;
+-
+-      port->minimum_buffer.num =
+-          rmsg->u.port_info_get_reply.port.buffer_num_min;
+-      port->minimum_buffer.size =
+-          rmsg->u.port_info_get_reply.port.buffer_size_min;
+-      port->minimum_buffer.alignment =
+-          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
+-
+-      port->recommended_buffer.alignment =
+-          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
+-      port->recommended_buffer.num =
+-          rmsg->u.port_info_get_reply.port.buffer_num_recommended;
+-
+-      port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
+-      port->current_buffer.size =
+-          rmsg->u.port_info_get_reply.port.buffer_size;
+-
+-      /* stream format */
+-      port->format.type = rmsg->u.port_info_get_reply.format.type;
+-      port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
+-      port->format.encoding_variant =
+-          rmsg->u.port_info_get_reply.format.encoding_variant;
+-      port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
+-      port->format.flags = rmsg->u.port_info_get_reply.format.flags;
+-
+-      /* elementary stream format */
+-      memcpy(&port->es,
+-             &rmsg->u.port_info_get_reply.es,
+-             sizeof(union mmal_es_specific_format));
+-      port->format.es = &port->es;
+-
+-      port->format.extradata_size =
+-          rmsg->u.port_info_get_reply.format.extradata_size;
+-      memcpy(port->format.extradata,
+-             rmsg->u.port_info_get_reply.extradata,
+-             port->format.extradata_size);
+-
+-      pr_debug("received port info\n");
+-      dump_port_info(port);
+-
+-release_msg:
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d\n",
+-               __func__, ret, port->component->handle, port->handle);
+-
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* create comonent on vc */
+-static int create_component(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_component *component,
+-                          const char *name)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      /* build component create message */
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
+-      m.u.component_create.client_component = (u32)(unsigned long)component;
+-      strncpy(m.u.component_create.name, name,
+-              sizeof(m.u.component_create.name));
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_create),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_create_reply.status;
+-      if (ret != MMAL_MSG_STATUS_SUCCESS)
+-              goto release_msg;
+-
+-      /* a valid component response received */
+-      component->handle = rmsg->u.component_create_reply.component_handle;
+-      component->inputs = rmsg->u.component_create_reply.input_num;
+-      component->outputs = rmsg->u.component_create_reply.output_num;
+-      component->clocks = rmsg->u.component_create_reply.clock_num;
+-
+-      pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
+-               component->handle,
+-               component->inputs, component->outputs, component->clocks);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* destroys a component on vc */
+-static int destroy_component(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
+-      m.u.component_destroy.component_handle = component->handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_destroy),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_destroy_reply.status;
+-
+-release_msg:
+-
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* enable a component on vc */
+-static int enable_component(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
+-      m.u.component_enable.component_handle = component->handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_enable),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_enable_reply.status;
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* disable a component on vc */
+-static int disable_component(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
+-      m.u.component_disable.component_handle = component->handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_disable),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_disable_reply.status;
+-
+-release_msg:
+-
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* get version of mmal implementation */
+-static int get_version(struct vchiq_mmal_instance *instance,
+-                     u32 *major_out, u32 *minor_out)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_GET_VERSION;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.version),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      *major_out = rmsg->u.version.major;
+-      *minor_out = rmsg->u.version.minor;
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* do a port action with a port as a parameter */
+-static int port_action_port(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_port *port,
+-                          enum mmal_msg_port_action_type action_type)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
+-      m.u.port_action_port.component_handle = port->component->handle;
+-      m.u.port_action_port.port_handle = port->handle;
+-      m.u.port_action_port.action = action_type;
+-
+-      port_to_mmal_msg(port, &m.u.port_action_port.port);
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_action_port),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_action_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
+-               __func__,
+-               ret, port->component->handle, port->handle,
+-               port_action_type_names[action_type], action_type);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* do a port action with handles as parameters */
+-static int port_action_handle(struct vchiq_mmal_instance *instance,
+-                            struct vchiq_mmal_port *port,
+-                            enum mmal_msg_port_action_type action_type,
+-                            u32 connect_component_handle,
+-                            u32 connect_port_handle)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
+-
+-      m.u.port_action_handle.component_handle = port->component->handle;
+-      m.u.port_action_handle.port_handle = port->handle;
+-      m.u.port_action_handle.action = action_type;
+-
+-      m.u.port_action_handle.connect_component_handle =
+-          connect_component_handle;
+-      m.u.port_action_handle.connect_port_handle = connect_port_handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_action_handle),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_action_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n",
+-               __func__,
+-               ret, port->component->handle, port->handle,
+-               port_action_type_names[action_type],
+-               action_type, connect_component_handle, connect_port_handle);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-static int port_parameter_set(struct vchiq_mmal_instance *instance,
+-                            struct vchiq_mmal_port *port,
+-                            u32 parameter_id, void *value, u32 value_size)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
+-
+-      m.u.port_parameter_set.component_handle = port->component->handle;
+-      m.u.port_parameter_set.port_handle = port->handle;
+-      m.u.port_parameter_set.id = parameter_id;
+-      m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
+-      memcpy(&m.u.port_parameter_set.value, value, value_size);
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      (4 * sizeof(u32)) + value_size,
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_parameter_set_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
+-               __func__,
+-               ret, port->component->handle, port->handle, parameter_id);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-static int port_parameter_get(struct vchiq_mmal_instance *instance,
+-                            struct vchiq_mmal_port *port,
+-                            u32 parameter_id, void *value, u32 *value_size)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
+-
+-      m.u.port_parameter_get.component_handle = port->component->handle;
+-      m.u.port_parameter_get.port_handle = port->handle;
+-      m.u.port_parameter_get.id = parameter_id;
+-      m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(struct
+-                                             mmal_msg_port_parameter_get),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
+-              /* got an unexpected message type in reply */
+-              pr_err("Incorrect reply type %d\n", rmsg->h.type);
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_parameter_get_reply.status;
+-      /* port_parameter_get_reply.size includes the header,
+-       * whilst *value_size doesn't.
+-       */
+-      rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32));
+-
+-      if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) {
+-              /* Copy only as much as we have space for
+-               * but report true size of parameter
+-               */
+-              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+-                     *value_size);
+-              *value_size = rmsg->u.port_parameter_get_reply.size;
+-      } else {
+-              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+-                     rmsg->u.port_parameter_get_reply.size);
+-      }
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
+-               ret, port->component->handle, port->handle, parameter_id);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* disables a port and drains buffers from it */
+-static int port_disable(struct vchiq_mmal_instance *instance,
+-                      struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-      struct list_head *q, *buf_head;
+-      unsigned long flags = 0;
+-
+-      if (!port->enabled)
+-              return 0;
+-
+-      port->enabled = false;
+-
+-      ret = port_action_port(instance, port,
+-                             MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
+-      if (ret == 0) {
+-              /*
+-               * Drain all queued buffers on port. This should only
+-               * apply to buffers that have been queued before the port
+-               * has been enabled. If the port has been enabled and buffers
+-               * passed, then the buffers should have been removed from this
+-               * list, and we should get the relevant callbacks via VCHIQ
+-               * to release the buffers.
+-               */
+-              spin_lock_irqsave(&port->slock, flags);
+-
+-              list_for_each_safe(buf_head, q, &port->buffers) {
+-                      struct mmal_buffer *mmalbuf;
+-
+-                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
+-                                           list);
+-                      list_del(buf_head);
+-                      if (port->buffer_cb)
+-                              port->buffer_cb(instance,
+-                                              port, 0, mmalbuf, 0, 0,
+-                                              MMAL_TIME_UNKNOWN,
+-                                              MMAL_TIME_UNKNOWN);
+-              }
+-
+-              spin_unlock_irqrestore(&port->slock, flags);
+-
+-              ret = port_info_get(instance, port);
+-      }
+-
+-      return ret;
+-}
+-
+-/* enable a port */
+-static int port_enable(struct vchiq_mmal_instance *instance,
+-                     struct vchiq_mmal_port *port)
+-{
+-      unsigned int hdr_count;
+-      struct list_head *q, *buf_head;
+-      int ret;
+-
+-      if (port->enabled)
+-              return 0;
+-
+-      ret = port_action_port(instance, port,
+-                             MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
+-      if (ret)
+-              goto done;
+-
+-      port->enabled = true;
+-
+-      if (port->buffer_cb) {
+-              /* send buffer headers to videocore */
+-              hdr_count = 1;
+-              list_for_each_safe(buf_head, q, &port->buffers) {
+-                      struct mmal_buffer *mmalbuf;
+-
+-                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
+-                                           list);
+-                      ret = buffer_from_host(instance, port, mmalbuf);
+-                      if (ret)
+-                              goto done;
+-
+-                      list_del(buf_head);
+-                      hdr_count++;
+-                      if (hdr_count > port->current_buffer.num)
+-                              break;
+-              }
+-      }
+-
+-      ret = port_info_get(instance, port);
+-
+-done:
+-      return ret;
+-}
+-
+-/* ------------------------------------------------------------------
+- * Exported API
+- *------------------------------------------------------------------
+- */
+-
+-int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
+-                             struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = port_info_set(instance, port);
+-      if (ret)
+-              goto release_unlock;
+-
+-      /* read what has actually been set */
+-      ret = port_info_get(instance, port);
+-
+-release_unlock:
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter, void *value, u32 value_size)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = port_parameter_set(instance, port, parameter, value, value_size);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter, void *value, u32 *value_size)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = port_parameter_get(instance, port, parameter, value, value_size);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/* enable a port
+- *
+- * enables a port and queues buffers for satisfying callbacks if we
+- * provide a callback handler
+- */
+-int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
+-                         struct vchiq_mmal_port *port,
+-                         vchiq_mmal_buffer_cb buffer_cb)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      /* already enabled - noop */
+-      if (port->enabled) {
+-              ret = 0;
+-              goto unlock;
+-      }
+-
+-      port->buffer_cb = buffer_cb;
+-
+-      ret = port_enable(instance, port);
+-
+-unlock:
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (!port->enabled) {
+-              mutex_unlock(&instance->vchiq_mutex);
+-              return 0;
+-      }
+-
+-      ret = port_disable(instance, port);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/* ports will be connected in a tunneled manner so data buffers
+- * are not handled by client.
+- */
+-int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
+-                                 struct vchiq_mmal_port *src,
+-                                 struct vchiq_mmal_port *dst)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      /* disconnect ports if connected */
+-      if (src->connected) {
+-              ret = port_disable(instance, src);
+-              if (ret) {
+-                      pr_err("failed disabling src port(%d)\n", ret);
+-                      goto release_unlock;
+-              }
+-
+-              /* do not need to disable the destination port as they
+-               * are connected and it is done automatically
+-               */
+-
+-              ret = port_action_handle(instance, src,
+-                                       MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
+-                                       src->connected->component->handle,
+-                                       src->connected->handle);
+-              if (ret < 0) {
+-                      pr_err("failed disconnecting src port\n");
+-                      goto release_unlock;
+-              }
+-              src->connected->enabled = false;
+-              src->connected = NULL;
+-      }
+-
+-      if (!dst) {
+-              /* do not make new connection */
+-              ret = 0;
+-              pr_debug("not making new connection\n");
+-              goto release_unlock;
+-      }
+-
+-      /* copy src port format to dst */
+-      dst->format.encoding = src->format.encoding;
+-      dst->es.video.width = src->es.video.width;
+-      dst->es.video.height = src->es.video.height;
+-      dst->es.video.crop.x = src->es.video.crop.x;
+-      dst->es.video.crop.y = src->es.video.crop.y;
+-      dst->es.video.crop.width = src->es.video.crop.width;
+-      dst->es.video.crop.height = src->es.video.crop.height;
+-      dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
+-      dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
+-
+-      /* set new format */
+-      ret = port_info_set(instance, dst);
+-      if (ret) {
+-              pr_debug("setting port info failed\n");
+-              goto release_unlock;
+-      }
+-
+-      /* read what has actually been set */
+-      ret = port_info_get(instance, dst);
+-      if (ret) {
+-              pr_debug("read back port info failed\n");
+-              goto release_unlock;
+-      }
+-
+-      /* connect two ports together */
+-      ret = port_action_handle(instance, src,
+-                               MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
+-                               dst->component->handle, dst->handle);
+-      if (ret < 0) {
+-              pr_debug("connecting port %d:%d to %d:%d failed\n",
+-                       src->component->handle, src->handle,
+-                       dst->component->handle, dst->handle);
+-              goto release_unlock;
+-      }
+-      src->connected = dst;
+-
+-release_unlock:
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_port *port,
+-                           struct mmal_buffer *buffer)
+-{
+-      unsigned long flags = 0;
+-      int ret;
+-
+-      ret = buffer_from_host(instance, port, buffer);
+-      if (ret == -EINVAL) {
+-              /* Port is disabled. Queue for when it is enabled. */
+-              spin_lock_irqsave(&port->slock, flags);
+-              list_add_tail(&buffer->list, &port->buffers);
+-              spin_unlock_irqrestore(&port->slock, flags);
+-      }
+-
+-      return 0;
+-}
+-
+-int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+-                        struct mmal_buffer *buf)
+-{
+-      struct mmal_msg_context *msg_context = get_msg_context(instance);
+-
+-      if (IS_ERR(msg_context))
+-              return (PTR_ERR(msg_context));
+-
+-      buf->msg_context = msg_context;
+-      return 0;
+-}
+-
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
+-{
+-      struct mmal_msg_context *msg_context = buf->msg_context;
+-
+-      if (msg_context)
+-              release_msg_context(msg_context);
+-      buf->msg_context = NULL;
+-
+-      return 0;
+-}
+-
+-/* Initialise a mmal component and its ports
+- *
+- */
+-int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
+-                            const char *name,
+-                            struct vchiq_mmal_component **component_out)
+-{
+-      int ret;
+-      int idx;                /* port index */
+-      struct vchiq_mmal_component *component;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
+-              ret = -EINVAL;  /* todo is this correct error? */
+-              goto unlock;
+-      }
+-
+-      component = &instance->component[instance->component_idx];
+-
+-      ret = create_component(instance, component, name);
+-      if (ret < 0) {
+-              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
+-                     __func__, ret);
+-              goto unlock;
+-      }
+-
+-      /* ports info needs gathering */
+-      component->control.type = MMAL_PORT_TYPE_CONTROL;
+-      component->control.index = 0;
+-      component->control.component = component;
+-      spin_lock_init(&component->control.slock);
+-      INIT_LIST_HEAD(&component->control.buffers);
+-      ret = port_info_get(instance, &component->control);
+-      if (ret < 0)
+-              goto release_component;
+-
+-      for (idx = 0; idx < component->inputs; idx++) {
+-              component->input[idx].type = MMAL_PORT_TYPE_INPUT;
+-              component->input[idx].index = idx;
+-              component->input[idx].component = component;
+-              spin_lock_init(&component->input[idx].slock);
+-              INIT_LIST_HEAD(&component->input[idx].buffers);
+-              ret = port_info_get(instance, &component->input[idx]);
+-              if (ret < 0)
+-                      goto release_component;
+-      }
+-
+-      for (idx = 0; idx < component->outputs; idx++) {
+-              component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
+-              component->output[idx].index = idx;
+-              component->output[idx].component = component;
+-              spin_lock_init(&component->output[idx].slock);
+-              INIT_LIST_HEAD(&component->output[idx].buffers);
+-              ret = port_info_get(instance, &component->output[idx]);
+-              if (ret < 0)
+-                      goto release_component;
+-      }
+-
+-      for (idx = 0; idx < component->clocks; idx++) {
+-              component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
+-              component->clock[idx].index = idx;
+-              component->clock[idx].component = component;
+-              spin_lock_init(&component->clock[idx].slock);
+-              INIT_LIST_HEAD(&component->clock[idx].buffers);
+-              ret = port_info_get(instance, &component->clock[idx]);
+-              if (ret < 0)
+-                      goto release_component;
+-      }
+-
+-      instance->component_idx++;
+-
+-      *component_out = component;
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return 0;
+-
+-release_component:
+-      destroy_component(instance, component);
+-unlock:
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/*
+- * cause a mmal component to be destroyed
+- */
+-int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (component->enabled)
+-              ret = disable_component(instance, component);
+-
+-      ret = destroy_component(instance, component);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/*
+- * cause a mmal component to be enabled
+- */
+-int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
+-                              struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (component->enabled) {
+-              mutex_unlock(&instance->vchiq_mutex);
+-              return 0;
+-      }
+-
+-      ret = enable_component(instance, component);
+-      if (ret == 0)
+-              component->enabled = true;
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/*
+- * cause a mmal component to be enabled
+- */
+-int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
+-                               struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (!component->enabled) {
+-              mutex_unlock(&instance->vchiq_mutex);
+-              return 0;
+-      }
+-
+-      ret = disable_component(instance, component);
+-      if (ret == 0)
+-              component->enabled = false;
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
+-                     u32 *major_out, u32 *minor_out)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = get_version(instance, major_out, minor_out);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
+-{
+-      int status = 0;
+-
+-      if (!instance)
+-              return -EINVAL;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      vchi_service_use(instance->handle);
+-
+-      status = vchi_service_close(instance->handle);
+-      if (status != 0)
+-              pr_err("mmal-vchiq: VCHIQ close failed\n");
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      flush_workqueue(instance->bulk_wq);
+-      destroy_workqueue(instance->bulk_wq);
+-
+-      vfree(instance->bulk_scratch);
+-
+-      idr_destroy(&instance->context_map);
+-
+-      kfree(instance);
+-
+-      return status;
+-}
+-
+-int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
+-{
+-      int status;
+-      struct vchiq_mmal_instance *instance;
+-      static VCHI_CONNECTION_T *vchi_connection;
+-      static VCHI_INSTANCE_T vchi_instance;
+-      SERVICE_CREATION_T params = {
+-              .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
+-              .service_id             = VC_MMAL_SERVER_NAME,
+-              .connection             = vchi_connection,
+-              .rx_fifo_size           = 0,
+-              .tx_fifo_size           = 0,
+-              .callback               = service_callback,
+-              .callback_param         = NULL,
+-              .want_unaligned_bulk_rx = 1,
+-              .want_unaligned_bulk_tx = 1,
+-              .want_crc               = 0
+-      };
+-
+-      /* compile time checks to ensure structure size as they are
+-       * directly (de)serialised from memory.
+-       */
+-
+-      /* ensure the header structure has packed to the correct size */
+-      BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
+-
+-      /* ensure message structure does not exceed maximum length */
+-      BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
+-
+-      /* mmal port struct is correct size */
+-      BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
+-
+-      /* create a vchi instance */
+-      status = vchi_initialise(&vchi_instance);
+-      if (status) {
+-              pr_err("Failed to initialise VCHI instance (status=%d)\n",
+-                     status);
+-              return -EIO;
+-      }
+-
+-      status = vchi_connect(NULL, 0, vchi_instance);
+-      if (status) {
+-              pr_err("Failed to connect VCHI instance (status=%d)\n", status);
+-              return -EIO;
+-      }
+-
+-      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+-
+-      if (!instance)
+-              return -ENOMEM;
+-
+-      mutex_init(&instance->vchiq_mutex);
+-
+-      instance->bulk_scratch = vmalloc(PAGE_SIZE);
+-
+-      mutex_init(&instance->context_map_lock);
+-      idr_init_base(&instance->context_map, 1);
+-
+-      params.callback_param = instance;
+-
+-      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
+-                                                  WQ_MEM_RECLAIM);
+-      if (!instance->bulk_wq)
+-              goto err_free;
+-
+-      status = vchi_service_open(vchi_instance, &params, &instance->handle);
+-      if (status) {
+-              pr_err("Failed to open VCHI service connection (status=%d)\n",
+-                     status);
+-              goto err_close_services;
+-      }
+-
+-      vchi_service_release(instance->handle);
+-
+-      *out_instance = instance;
+-
+-      return 0;
+-
+-err_close_services:
+-      vchi_service_close(instance->handle);
+-      destroy_workqueue(instance->bulk_wq);
+-err_free:
+-      vfree(instance->bulk_scratch);
+-      kfree(instance);
+-      return -ENODEV;
+-}
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -0,0 +1,1921 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ *
++ * V4L2 driver MMAL vchiq interface code
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/completion.h>
++#include <linux/vmalloc.h>
++#include <asm/cacheflush.h>
++#include <media/videobuf2-vmalloc.h>
++
++#include "mmal-common.h"
++#include "mmal-vchiq.h"
++#include "mmal-msg.h"
++
++#define USE_VCHIQ_ARM
++#include "interface/vchi/vchi.h"
++
++MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface");
++MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.0.1");
++
++/* maximum number of components supported */
++#define VCHIQ_MMAL_MAX_COMPONENTS 4
++
++/*#define FULL_MSG_DUMP 1*/
++
++#ifdef DEBUG
++static const char *const msg_type_names[] = {
++      "UNKNOWN",
++      "QUIT",
++      "SERVICE_CLOSED",
++      "GET_VERSION",
++      "COMPONENT_CREATE",
++      "COMPONENT_DESTROY",
++      "COMPONENT_ENABLE",
++      "COMPONENT_DISABLE",
++      "PORT_INFO_GET",
++      "PORT_INFO_SET",
++      "PORT_ACTION",
++      "BUFFER_FROM_HOST",
++      "BUFFER_TO_HOST",
++      "GET_STATS",
++      "PORT_PARAMETER_SET",
++      "PORT_PARAMETER_GET",
++      "EVENT_TO_HOST",
++      "GET_CORE_STATS_FOR_PORT",
++      "OPAQUE_ALLOCATOR",
++      "CONSUME_MEM",
++      "LMK",
++      "OPAQUE_ALLOCATOR_DESC",
++      "DRM_GET_LHS32",
++      "DRM_GET_TIME",
++      "BUFFER_FROM_HOST_ZEROLEN",
++      "PORT_FLUSH",
++      "HOST_LOG",
++};
++#endif
++
++static const char *const port_action_type_names[] = {
++      "UNKNOWN",
++      "ENABLE",
++      "DISABLE",
++      "FLUSH",
++      "CONNECT",
++      "DISCONNECT",
++      "SET_REQUIREMENTS",
++};
++
++#if defined(DEBUG)
++#if defined(FULL_MSG_DUMP)
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
++      do {                                                            \
++              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
++                       msg_type_names[(MSG)->h.type],                 \
++                       (MSG)->h.type, (MSG_LEN));                     \
++              print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
++                             16, 4, (MSG),                            \
++                             sizeof(struct mmal_msg_header), 1);      \
++              print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
++                             16, 4,                                   \
++                             ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
++                             (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
++      } while (0)
++#else
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
++      {                                                               \
++              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
++                       msg_type_names[(MSG)->h.type],                 \
++                       (MSG)->h.type, (MSG_LEN));                     \
++      }
++#endif
++#else
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
++#endif
++
++struct vchiq_mmal_instance;
++
++/* normal message context */
++struct mmal_msg_context {
++      struct vchiq_mmal_instance *instance;
++
++      /* Index in the context_map idr so that we can find the
++       * mmal_msg_context again when servicing the VCHI reply.
++       */
++      int handle;
++
++      union {
++              struct {
++                      /* work struct for buffer_cb callback */
++                      struct work_struct work;
++                      /* work struct for deferred callback */
++                      struct work_struct buffer_to_host_work;
++                      /* mmal instance */
++                      struct vchiq_mmal_instance *instance;
++                      /* mmal port */
++                      struct vchiq_mmal_port *port;
++                      /* actual buffer used to store bulk reply */
++                      struct mmal_buffer *buffer;
++                      /* amount of buffer used */
++                      unsigned long buffer_used;
++                      /* MMAL buffer flags */
++                      u32 mmal_flags;
++                      /* Presentation and Decode timestamps */
++                      s64 pts;
++                      s64 dts;
++
++                      int status;     /* context status */
++
++              } bulk;         /* bulk data */
++
++              struct {
++                      /* message handle to release */
++                      VCHI_HELD_MSG_T msg_handle;
++                      /* pointer to received message */
++                      struct mmal_msg *msg;
++                      /* received message length */
++                      u32 msg_len;
++                      /* completion upon reply */
++                      struct completion cmplt;
++              } sync;         /* synchronous response */
++      } u;
++
++};
++
++struct vchiq_mmal_instance {
++      VCHI_SERVICE_HANDLE_T handle;
++
++      /* ensure serialised access to service */
++      struct mutex vchiq_mutex;
++
++      /* vmalloc page to receive scratch bulk xfers into */
++      void *bulk_scratch;
++
++      struct idr context_map;
++      /* protect accesses to context_map */
++      struct mutex context_map_lock;
++
++      /* component to use next */
++      int component_idx;
++      struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
++
++      /* ordered workqueue to process all bulk operations */
++      struct workqueue_struct *bulk_wq;
++};
++
++static struct mmal_msg_context *
++get_msg_context(struct vchiq_mmal_instance *instance)
++{
++      struct mmal_msg_context *msg_context;
++      int handle;
++
++      /* todo: should this be allocated from a pool to avoid kzalloc */
++      msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
++
++      if (!msg_context)
++              return ERR_PTR(-ENOMEM);
++
++      /* Create an ID that will be passed along with our message so
++       * that when we service the VCHI reply, we can look up what
++       * message is being replied to.
++       */
++      mutex_lock(&instance->context_map_lock);
++      handle = idr_alloc(&instance->context_map, msg_context,
++                         0, 0, GFP_KERNEL);
++      mutex_unlock(&instance->context_map_lock);
++
++      if (handle < 0) {
++              kfree(msg_context);
++              return ERR_PTR(handle);
++      }
++
++      msg_context->instance = instance;
++      msg_context->handle = handle;
++
++      return msg_context;
++}
++
++static struct mmal_msg_context *
++lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
++{
++      return idr_find(&instance->context_map, handle);
++}
++
++static void
++release_msg_context(struct mmal_msg_context *msg_context)
++{
++      struct vchiq_mmal_instance *instance = msg_context->instance;
++
++      mutex_lock(&instance->context_map_lock);
++      idr_remove(&instance->context_map, msg_context->handle);
++      mutex_unlock(&instance->context_map_lock);
++      kfree(msg_context);
++}
++
++/* deals with receipt of event to host message */
++static void event_to_host_cb(struct vchiq_mmal_instance *instance,
++                           struct mmal_msg *msg, u32 msg_len)
++{
++      pr_debug("unhandled event\n");
++      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
++               msg->u.event_to_host.client_component,
++               msg->u.event_to_host.port_type,
++               msg->u.event_to_host.port_num,
++               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
++}
++
++/* workqueue scheduled callback
++ *
++ * we do this because it is important we do not call any other vchiq
++ * sync calls from witin the message delivery thread
++ */
++static void buffer_work_cb(struct work_struct *work)
++{
++      struct mmal_msg_context *msg_context =
++              container_of(work, struct mmal_msg_context, u.bulk.work);
++
++      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
++
++      msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
++                                          msg_context->u.bulk.port,
++                                          msg_context->u.bulk.status,
++                                          msg_context->u.bulk.buffer,
++                                          msg_context->u.bulk.buffer_used,
++                                          msg_context->u.bulk.mmal_flags,
++                                          msg_context->u.bulk.dts,
++                                          msg_context->u.bulk.pts);
++}
++
++/* workqueue scheduled callback to handle receiving buffers
++ *
++ * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
++ * If we block in the service_callback context then we can't process the
++ * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
++ * vchi_bulk_queue_receive() call to complete.
++ */
++static void buffer_to_host_work_cb(struct work_struct *work)
++{
++      struct mmal_msg_context *msg_context =
++              container_of(work, struct mmal_msg_context,
++                           u.bulk.buffer_to_host_work);
++      struct vchiq_mmal_instance *instance = msg_context->instance;
++      unsigned long len = msg_context->u.bulk.buffer_used;
++      int ret;
++
++      if (!len)
++              /* Dummy receive to ensure the buffers remain in order */
++              len = 8;
++      /* queue the bulk submission */
++      vchi_service_use(instance->handle);
++      ret = vchi_bulk_queue_receive(instance->handle,
++                                    msg_context->u.bulk.buffer->buffer,
++                                    /* Actual receive needs to be a multiple
++                                     * of 4 bytes
++                                     */
++                                    (len + 3) & ~3,
++                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
++                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
++                                    msg_context);
++
++      vchi_service_release(instance->handle);
++
++      if (ret != 0)
++              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
++                     __func__, msg_context, ret);
++}
++
++/* enqueue a bulk receive for a given message context */
++static int bulk_receive(struct vchiq_mmal_instance *instance,
++                      struct mmal_msg *msg,
++                      struct mmal_msg_context *msg_context)
++{
++      unsigned long rd_len;
++
++      rd_len = msg->u.buffer_from_host.buffer_header.length;
++
++      if (!msg_context->u.bulk.buffer) {
++              pr_err("bulk.buffer not configured - error in buffer_from_host\n");
++
++              /* todo: this is a serious error, we should never have
++               * committed a buffer_to_host operation to the mmal
++               * port without the buffer to back it up (underflow
++               * handling) and there is no obvious way to deal with
++               * this - how is the mmal servie going to react when
++               * we fail to do the xfer and reschedule a buffer when
++               * it arrives? perhaps a starved flag to indicate a
++               * waiting bulk receive?
++               */
++
++              return -EINVAL;
++      }
++
++      /* ensure we do not overrun the available buffer */
++      if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
++              rd_len = msg_context->u.bulk.buffer->buffer_size;
++              pr_warn("short read as not enough receive buffer space\n");
++              /* todo: is this the correct response, what happens to
++               * the rest of the message data?
++               */
++      }
++
++      /* store length */
++      msg_context->u.bulk.buffer_used = rd_len;
++      msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
++      msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
++
++      queue_work(msg_context->instance->bulk_wq,
++                 &msg_context->u.bulk.buffer_to_host_work);
++
++      return 0;
++}
++
++/* data in message, memcpy from packet into output buffer */
++static int inline_receive(struct vchiq_mmal_instance *instance,
++                        struct mmal_msg *msg,
++                        struct mmal_msg_context *msg_context)
++{
++      memcpy(msg_context->u.bulk.buffer->buffer,
++             msg->u.buffer_from_host.short_data,
++             msg->u.buffer_from_host.payload_in_message);
++
++      msg_context->u.bulk.buffer_used =
++          msg->u.buffer_from_host.payload_in_message;
++
++      return 0;
++}
++
++/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
++static int
++buffer_from_host(struct vchiq_mmal_instance *instance,
++               struct vchiq_mmal_port *port, struct mmal_buffer *buf)
++{
++      struct mmal_msg_context *msg_context;
++      struct mmal_msg m;
++      int ret;
++
++      if (!port->enabled)
++              return -EINVAL;
++
++      pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
++
++      /* get context */
++      if (!buf->msg_context) {
++              pr_err("%s: msg_context not allocated, buf %p\n", __func__,
++                     buf);
++              return -EINVAL;
++      }
++      msg_context = buf->msg_context;
++
++      /* store bulk message context for when data arrives */
++      msg_context->u.bulk.instance = instance;
++      msg_context->u.bulk.port = port;
++      msg_context->u.bulk.buffer = buf;
++      msg_context->u.bulk.buffer_used = 0;
++
++      /* initialise work structure ready to schedule callback */
++      INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
++      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
++                buffer_to_host_work_cb);
++
++      atomic_inc(&port->buffers_with_vpu);
++
++      /* prep the buffer from host message */
++      memset(&m, 0xbc, sizeof(m));    /* just to make debug clearer */
++
++      m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
++      m.h.magic = MMAL_MAGIC;
++      m.h.context = msg_context->handle;
++      m.h.status = 0;
++
++      /* drvbuf is our private data passed back */
++      m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
++      m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
++      m.u.buffer_from_host.drvbuf.port_handle = port->handle;
++      m.u.buffer_from_host.drvbuf.client_context = msg_context->handle;
++
++      /* buffer header */
++      m.u.buffer_from_host.buffer_header.cmd = 0;
++      m.u.buffer_from_host.buffer_header.data =
++              (u32)(unsigned long)buf->buffer;
++      m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
++      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
++      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
++      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
++      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
++      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
++
++      /* clear buffer type sepecific data */
++      memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
++             sizeof(m.u.buffer_from_host.buffer_header_type_specific));
++
++      /* no payload in message */
++      m.u.buffer_from_host.payload_in_message = 0;
++
++      vchi_service_use(instance->handle);
++
++      ret = vchi_queue_kernel_message(instance->handle,
++                                      &m,
++                                      sizeof(struct mmal_msg_header) +
++                                      sizeof(m.u.buffer_from_host));
++
++      vchi_service_release(instance->handle);
++
++      return ret;
++}
++
++/* deals with receipt of buffer to host message */
++static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
++                            struct mmal_msg *msg, u32 msg_len)
++{
++      struct mmal_msg_context *msg_context;
++      u32 handle;
++
++      pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
++               __func__, instance, msg, msg_len);
++
++      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
++              handle = msg->u.buffer_from_host.drvbuf.client_context;
++              msg_context = lookup_msg_context(instance, handle);
++
++              if (!msg_context) {
++                      pr_err("drvbuf.client_context(%u) is invalid\n",
++                             handle);
++                      return;
++              }
++      } else {
++              pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
++              return;
++      }
++
++      msg_context->u.bulk.mmal_flags =
++                              msg->u.buffer_from_host.buffer_header.flags;
++
++      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
++              /* message reception had an error */
++              pr_warn("error %d in reply\n", msg->h.status);
++
++              msg_context->u.bulk.status = msg->h.status;
++
++      } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
++              /* empty buffer */
++              if (msg->u.buffer_from_host.buffer_header.flags &
++                  MMAL_BUFFER_HEADER_FLAG_EOS) {
++                      msg_context->u.bulk.status =
++                          bulk_receive(instance, msg, msg_context);
++                      if (msg_context->u.bulk.status == 0)
++                              return; /* successful bulk submission, bulk
++                                       * completion will trigger callback
++                                       */
++              } else {
++                      /* do callback with empty buffer - not EOS though */
++                      msg_context->u.bulk.status = 0;
++                      msg_context->u.bulk.buffer_used = 0;
++              }
++      } else if (msg->u.buffer_from_host.payload_in_message == 0) {
++              /* data is not in message, queue a bulk receive */
++              msg_context->u.bulk.status =
++                  bulk_receive(instance, msg, msg_context);
++              if (msg_context->u.bulk.status == 0)
++                      return; /* successful bulk submission, bulk
++                               * completion will trigger callback
++                               */
++
++              /* failed to submit buffer, this will end badly */
++              pr_err("error %d on bulk submission\n",
++                     msg_context->u.bulk.status);
++
++      } else if (msg->u.buffer_from_host.payload_in_message <=
++                 MMAL_VC_SHORT_DATA) {
++              /* data payload within message */
++              msg_context->u.bulk.status = inline_receive(instance, msg,
++                                                          msg_context);
++      } else {
++              pr_err("message with invalid short payload\n");
++
++              /* signal error */
++              msg_context->u.bulk.status = -EINVAL;
++              msg_context->u.bulk.buffer_used =
++                  msg->u.buffer_from_host.payload_in_message;
++      }
++
++      /* schedule the port callback */
++      schedule_work(&msg_context->u.bulk.work);
++}
++
++static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
++                          struct mmal_msg_context *msg_context)
++{
++      msg_context->u.bulk.status = 0;
++
++      /* schedule the port callback */
++      schedule_work(&msg_context->u.bulk.work);
++}
++
++static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
++                        struct mmal_msg_context *msg_context)
++{
++      pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
++
++      msg_context->u.bulk.status = -EINTR;
++
++      schedule_work(&msg_context->u.bulk.work);
++}
++
++/* incoming event service callback */
++static void service_callback(void *param,
++                           const VCHI_CALLBACK_REASON_T reason,
++                           void *bulk_ctx)
++{
++      struct vchiq_mmal_instance *instance = param;
++      int status;
++      u32 msg_len;
++      struct mmal_msg *msg;
++      VCHI_HELD_MSG_T msg_handle;
++      struct mmal_msg_context *msg_context;
++
++      if (!instance) {
++              pr_err("Message callback passed NULL instance\n");
++              return;
++      }
++
++      switch (reason) {
++      case VCHI_CALLBACK_MSG_AVAILABLE:
++              status = vchi_msg_hold(instance->handle, (void **)&msg,
++                                     &msg_len, VCHI_FLAGS_NONE, &msg_handle);
++              if (status) {
++                      pr_err("Unable to dequeue a message (%d)\n", status);
++                      break;
++              }
++
++              DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
++
++              /* handling is different for buffer messages */
++              switch (msg->h.type) {
++              case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
++                      vchi_held_msg_release(&msg_handle);
++                      break;
++
++              case MMAL_MSG_TYPE_EVENT_TO_HOST:
++                      event_to_host_cb(instance, msg, msg_len);
++                      vchi_held_msg_release(&msg_handle);
++
++                      break;
++
++              case MMAL_MSG_TYPE_BUFFER_TO_HOST:
++                      buffer_to_host_cb(instance, msg, msg_len);
++                      vchi_held_msg_release(&msg_handle);
++                      break;
++
++              default:
++                      /* messages dependent on header context to complete */
++                      if (!msg->h.context) {
++                              pr_err("received message context was null!\n");
++                              vchi_held_msg_release(&msg_handle);
++                              break;
++                      }
++
++                      msg_context = lookup_msg_context(instance,
++                                                       msg->h.context);
++                      if (!msg_context) {
++                              pr_err("received invalid message context %u!\n",
++                                     msg->h.context);
++                              vchi_held_msg_release(&msg_handle);
++                              break;
++                      }
++
++                      /* fill in context values */
++                      msg_context->u.sync.msg_handle = msg_handle;
++                      msg_context->u.sync.msg = msg;
++                      msg_context->u.sync.msg_len = msg_len;
++
++                      /* todo: should this check (completion_done()
++                       * == 1) for no one waiting? or do we need a
++                       * flag to tell us the completion has been
++                       * interrupted so we can free the message and
++                       * its context. This probably also solves the
++                       * message arriving after interruption todo
++                       * below
++                       */
++
++                      /* complete message so caller knows it happened */
++                      complete(&msg_context->u.sync.cmplt);
++                      break;
++              }
++
++              break;
++
++      case VCHI_CALLBACK_BULK_RECEIVED:
++              bulk_receive_cb(instance, bulk_ctx);
++              break;
++
++      case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
++              bulk_abort_cb(instance, bulk_ctx);
++              break;
++
++      case VCHI_CALLBACK_SERVICE_CLOSED:
++              /* TODO: consider if this requires action if received when
++               * driver is not explicitly closing the service
++               */
++              break;
++
++      default:
++              pr_err("Received unhandled message reason %d\n", reason);
++              break;
++      }
++}
++
++static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
++                                   struct mmal_msg *msg,
++                                   unsigned int payload_len,
++                                   struct mmal_msg **msg_out,
++                                   VCHI_HELD_MSG_T *msg_handle_out)
++{
++      struct mmal_msg_context *msg_context;
++      int ret;
++      unsigned long timeout;
++
++      /* payload size must not cause message to exceed max size */
++      if (payload_len >
++          (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
++              pr_err("payload length %d exceeds max:%d\n", payload_len,
++                     (int)(MMAL_MSG_MAX_SIZE -
++                          sizeof(struct mmal_msg_header)));
++              return -EINVAL;
++      }
++
++      msg_context = get_msg_context(instance);
++      if (IS_ERR(msg_context))
++              return PTR_ERR(msg_context);
++
++      init_completion(&msg_context->u.sync.cmplt);
++
++      msg->h.magic = MMAL_MAGIC;
++      msg->h.context = msg_context->handle;
++      msg->h.status = 0;
++
++      DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
++                   ">>> sync message");
++
++      vchi_service_use(instance->handle);
++
++      ret = vchi_queue_kernel_message(instance->handle,
++                                      msg,
++                                      sizeof(struct mmal_msg_header) +
++                                      payload_len);
++
++      vchi_service_release(instance->handle);
++
++      if (ret) {
++              pr_err("error %d queuing message\n", ret);
++              release_msg_context(msg_context);
++              return ret;
++      }
++
++      timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
++                                            3 * HZ);
++      if (timeout == 0) {
++              pr_err("timed out waiting for sync completion\n");
++              ret = -ETIME;
++              /* todo: what happens if the message arrives after aborting */
++              release_msg_context(msg_context);
++              return ret;
++      }
++
++      *msg_out = msg_context->u.sync.msg;
++      *msg_handle_out = msg_context->u.sync.msg_handle;
++      release_msg_context(msg_context);
++
++      return 0;
++}
++
++static void dump_port_info(struct vchiq_mmal_port *port)
++{
++      pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
++
++      pr_debug("buffer minimum num:%d size:%d align:%d\n",
++               port->minimum_buffer.num,
++               port->minimum_buffer.size, port->minimum_buffer.alignment);
++
++      pr_debug("buffer recommended num:%d size:%d align:%d\n",
++               port->recommended_buffer.num,
++               port->recommended_buffer.size,
++               port->recommended_buffer.alignment);
++
++      pr_debug("buffer current values num:%d size:%d align:%d\n",
++               port->current_buffer.num,
++               port->current_buffer.size, port->current_buffer.alignment);
++
++      pr_debug("elementary stream: type:%d encoding:0x%x variant:0x%x\n",
++               port->format.type,
++               port->format.encoding, port->format.encoding_variant);
++
++      pr_debug("                  bitrate:%d flags:0x%x\n",
++               port->format.bitrate, port->format.flags);
++
++      if (port->format.type == MMAL_ES_TYPE_VIDEO) {
++              pr_debug
++                  ("es video format: width:%d height:%d colourspace:0x%x\n",
++                   port->es.video.width, port->es.video.height,
++                   port->es.video.color_space);
++
++              pr_debug("               : crop xywh %d,%d,%d,%d\n",
++                       port->es.video.crop.x,
++                       port->es.video.crop.y,
++                       port->es.video.crop.width, port->es.video.crop.height);
++              pr_debug("               : framerate %d/%d  aspect %d/%d\n",
++                       port->es.video.frame_rate.num,
++                       port->es.video.frame_rate.den,
++                       port->es.video.par.num, port->es.video.par.den);
++      }
++}
++
++static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
++{
++      /* todo do readonly fields need setting at all? */
++      p->type = port->type;
++      p->index = port->index;
++      p->index_all = 0;
++      p->is_enabled = port->enabled;
++      p->buffer_num_min = port->minimum_buffer.num;
++      p->buffer_size_min = port->minimum_buffer.size;
++      p->buffer_alignment_min = port->minimum_buffer.alignment;
++      p->buffer_num_recommended = port->recommended_buffer.num;
++      p->buffer_size_recommended = port->recommended_buffer.size;
++
++      /* only three writable fields in a port */
++      p->buffer_num = port->current_buffer.num;
++      p->buffer_size = port->current_buffer.size;
++      p->userdata = (u32)(unsigned long)port;
++}
++
++static int port_info_set(struct vchiq_mmal_instance *instance,
++                       struct vchiq_mmal_port *port)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      pr_debug("setting port info port %p\n", port);
++      if (!port)
++              return -1;
++      dump_port_info(port);
++
++      m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
++
++      m.u.port_info_set.component_handle = port->component->handle;
++      m.u.port_info_set.port_type = port->type;
++      m.u.port_info_set.port_index = port->index;
++
++      port_to_mmal_msg(port, &m.u.port_info_set.port);
++
++      /* elementary stream format setup */
++      m.u.port_info_set.format.type = port->format.type;
++      m.u.port_info_set.format.encoding = port->format.encoding;
++      m.u.port_info_set.format.encoding_variant =
++          port->format.encoding_variant;
++      m.u.port_info_set.format.bitrate = port->format.bitrate;
++      m.u.port_info_set.format.flags = port->format.flags;
++
++      memcpy(&m.u.port_info_set.es, &port->es,
++             sizeof(union mmal_es_specific_format));
++
++      m.u.port_info_set.format.extradata_size = port->format.extradata_size;
++      memcpy(&m.u.port_info_set.extradata, port->format.extradata,
++             port->format.extradata_size);
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_info_set),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      /* return operation status */
++      ret = -rmsg->u.port_info_get_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
++               port->component->handle, port->handle);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* use port info get message to retrieve port information */
++static int port_info_get(struct vchiq_mmal_instance *instance,
++                       struct vchiq_mmal_port *port)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      /* port info time */
++      m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
++      m.u.port_info_get.component_handle = port->component->handle;
++      m.u.port_info_get.port_type = port->type;
++      m.u.port_info_get.index = port->index;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_info_get),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      /* return operation status */
++      ret = -rmsg->u.port_info_get_reply.status;
++      if (ret != MMAL_MSG_STATUS_SUCCESS)
++              goto release_msg;
++
++      if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
++              port->enabled = false;
++      else
++              port->enabled = true;
++
++      /* copy the values out of the message */
++      port->handle = rmsg->u.port_info_get_reply.port_handle;
++
++      /* port type and index cached to use on port info set because
++       * it does not use a port handle
++       */
++      port->type = rmsg->u.port_info_get_reply.port_type;
++      port->index = rmsg->u.port_info_get_reply.port_index;
++
++      port->minimum_buffer.num =
++          rmsg->u.port_info_get_reply.port.buffer_num_min;
++      port->minimum_buffer.size =
++          rmsg->u.port_info_get_reply.port.buffer_size_min;
++      port->minimum_buffer.alignment =
++          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
++
++      port->recommended_buffer.alignment =
++          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
++      port->recommended_buffer.num =
++          rmsg->u.port_info_get_reply.port.buffer_num_recommended;
++
++      port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
++      port->current_buffer.size =
++          rmsg->u.port_info_get_reply.port.buffer_size;
++
++      /* stream format */
++      port->format.type = rmsg->u.port_info_get_reply.format.type;
++      port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
++      port->format.encoding_variant =
++          rmsg->u.port_info_get_reply.format.encoding_variant;
++      port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
++      port->format.flags = rmsg->u.port_info_get_reply.format.flags;
++
++      /* elementary stream format */
++      memcpy(&port->es,
++             &rmsg->u.port_info_get_reply.es,
++             sizeof(union mmal_es_specific_format));
++      port->format.es = &port->es;
++
++      port->format.extradata_size =
++          rmsg->u.port_info_get_reply.format.extradata_size;
++      memcpy(port->format.extradata,
++             rmsg->u.port_info_get_reply.extradata,
++             port->format.extradata_size);
++
++      pr_debug("received port info\n");
++      dump_port_info(port);
++
++release_msg:
++
++      pr_debug("%s:result:%d component:0x%x port:%d\n",
++               __func__, ret, port->component->handle, port->handle);
++
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* create comonent on vc */
++static int create_component(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_component *component,
++                          const char *name)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      /* build component create message */
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
++      m.u.component_create.client_component = (u32)(unsigned long)component;
++      strncpy(m.u.component_create.name, name,
++              sizeof(m.u.component_create.name));
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_create),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_create_reply.status;
++      if (ret != MMAL_MSG_STATUS_SUCCESS)
++              goto release_msg;
++
++      /* a valid component response received */
++      component->handle = rmsg->u.component_create_reply.component_handle;
++      component->inputs = rmsg->u.component_create_reply.input_num;
++      component->outputs = rmsg->u.component_create_reply.output_num;
++      component->clocks = rmsg->u.component_create_reply.clock_num;
++
++      pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
++               component->handle,
++               component->inputs, component->outputs, component->clocks);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* destroys a component on vc */
++static int destroy_component(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_component *component)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
++      m.u.component_destroy.component_handle = component->handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_destroy),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_destroy_reply.status;
++
++release_msg:
++
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* enable a component on vc */
++static int enable_component(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_component *component)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
++      m.u.component_enable.component_handle = component->handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_enable),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_enable_reply.status;
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* disable a component on vc */
++static int disable_component(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_component *component)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
++      m.u.component_disable.component_handle = component->handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_disable),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_disable_reply.status;
++
++release_msg:
++
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* get version of mmal implementation */
++static int get_version(struct vchiq_mmal_instance *instance,
++                     u32 *major_out, u32 *minor_out)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_GET_VERSION;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.version),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      *major_out = rmsg->u.version.major;
++      *minor_out = rmsg->u.version.minor;
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* do a port action with a port as a parameter */
++static int port_action_port(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_port *port,
++                          enum mmal_msg_port_action_type action_type)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
++      m.u.port_action_port.component_handle = port->component->handle;
++      m.u.port_action_port.port_handle = port->handle;
++      m.u.port_action_port.action = action_type;
++
++      port_to_mmal_msg(port, &m.u.port_action_port.port);
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_action_port),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_action_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
++               __func__,
++               ret, port->component->handle, port->handle,
++               port_action_type_names[action_type], action_type);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* do a port action with handles as parameters */
++static int port_action_handle(struct vchiq_mmal_instance *instance,
++                            struct vchiq_mmal_port *port,
++                            enum mmal_msg_port_action_type action_type,
++                            u32 connect_component_handle,
++                            u32 connect_port_handle)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
++
++      m.u.port_action_handle.component_handle = port->component->handle;
++      m.u.port_action_handle.port_handle = port->handle;
++      m.u.port_action_handle.action = action_type;
++
++      m.u.port_action_handle.connect_component_handle =
++          connect_component_handle;
++      m.u.port_action_handle.connect_port_handle = connect_port_handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_action_handle),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_action_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n",
++               __func__,
++               ret, port->component->handle, port->handle,
++               port_action_type_names[action_type],
++               action_type, connect_component_handle, connect_port_handle);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++static int port_parameter_set(struct vchiq_mmal_instance *instance,
++                            struct vchiq_mmal_port *port,
++                            u32 parameter_id, void *value, u32 value_size)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
++
++      m.u.port_parameter_set.component_handle = port->component->handle;
++      m.u.port_parameter_set.port_handle = port->handle;
++      m.u.port_parameter_set.id = parameter_id;
++      m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
++      memcpy(&m.u.port_parameter_set.value, value, value_size);
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      (4 * sizeof(u32)) + value_size,
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_parameter_set_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
++               __func__,
++               ret, port->component->handle, port->handle, parameter_id);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++static int port_parameter_get(struct vchiq_mmal_instance *instance,
++                            struct vchiq_mmal_port *port,
++                            u32 parameter_id, void *value, u32 *value_size)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
++
++      m.u.port_parameter_get.component_handle = port->component->handle;
++      m.u.port_parameter_get.port_handle = port->handle;
++      m.u.port_parameter_get.id = parameter_id;
++      m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(struct
++                                             mmal_msg_port_parameter_get),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
++              /* got an unexpected message type in reply */
++              pr_err("Incorrect reply type %d\n", rmsg->h.type);
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_parameter_get_reply.status;
++      /* port_parameter_get_reply.size includes the header,
++       * whilst *value_size doesn't.
++       */
++      rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32));
++
++      if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) {
++              /* Copy only as much as we have space for
++               * but report true size of parameter
++               */
++              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
++                     *value_size);
++              *value_size = rmsg->u.port_parameter_get_reply.size;
++      } else {
++              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
++                     rmsg->u.port_parameter_get_reply.size);
++      }
++
++      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
++               ret, port->component->handle, port->handle, parameter_id);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* disables a port and drains buffers from it */
++static int port_disable(struct vchiq_mmal_instance *instance,
++                      struct vchiq_mmal_port *port)
++{
++      int ret;
++      struct list_head *q, *buf_head;
++      unsigned long flags = 0;
++
++      if (!port->enabled)
++              return 0;
++
++      port->enabled = false;
++
++      ret = port_action_port(instance, port,
++                             MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
++      if (ret == 0) {
++              /*
++               * Drain all queued buffers on port. This should only
++               * apply to buffers that have been queued before the port
++               * has been enabled. If the port has been enabled and buffers
++               * passed, then the buffers should have been removed from this
++               * list, and we should get the relevant callbacks via VCHIQ
++               * to release the buffers.
++               */
++              spin_lock_irqsave(&port->slock, flags);
++
++              list_for_each_safe(buf_head, q, &port->buffers) {
++                      struct mmal_buffer *mmalbuf;
++
++                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
++                                           list);
++                      list_del(buf_head);
++                      if (port->buffer_cb)
++                              port->buffer_cb(instance,
++                                              port, 0, mmalbuf, 0, 0,
++                                              MMAL_TIME_UNKNOWN,
++                                              MMAL_TIME_UNKNOWN);
++              }
++
++              spin_unlock_irqrestore(&port->slock, flags);
++
++              ret = port_info_get(instance, port);
++      }
++
++      return ret;
++}
++
++/* enable a port */
++static int port_enable(struct vchiq_mmal_instance *instance,
++                     struct vchiq_mmal_port *port)
++{
++      unsigned int hdr_count;
++      struct list_head *q, *buf_head;
++      int ret;
++
++      if (port->enabled)
++              return 0;
++
++      ret = port_action_port(instance, port,
++                             MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
++      if (ret)
++              goto done;
++
++      port->enabled = true;
++
++      if (port->buffer_cb) {
++              /* send buffer headers to videocore */
++              hdr_count = 1;
++              list_for_each_safe(buf_head, q, &port->buffers) {
++                      struct mmal_buffer *mmalbuf;
++
++                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
++                                           list);
++                      ret = buffer_from_host(instance, port, mmalbuf);
++                      if (ret)
++                              goto done;
++
++                      list_del(buf_head);
++                      hdr_count++;
++                      if (hdr_count > port->current_buffer.num)
++                              break;
++              }
++      }
++
++      ret = port_info_get(instance, port);
++
++done:
++      return ret;
++}
++
++/* ------------------------------------------------------------------
++ * Exported API
++ *------------------------------------------------------------------
++ */
++
++int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
++                             struct vchiq_mmal_port *port)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = port_info_set(instance, port);
++      if (ret)
++              goto release_unlock;
++
++      /* read what has actually been set */
++      ret = port_info_get(instance, port);
++
++release_unlock:
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format);
++
++int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter, void *value, u32 value_size)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = port_parameter_set(instance, port, parameter, value, value_size);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
++
++int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter, void *value, u32 *value_size)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = port_parameter_get(instance, port, parameter, value, value_size);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get);
++
++/* enable a port
++ *
++ * enables a port and queues buffers for satisfying callbacks if we
++ * provide a callback handler
++ */
++int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
++                         struct vchiq_mmal_port *port,
++                         vchiq_mmal_buffer_cb buffer_cb)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      /* already enabled - noop */
++      if (port->enabled) {
++              ret = 0;
++              goto unlock;
++      }
++
++      port->buffer_cb = buffer_cb;
++
++      ret = port_enable(instance, port);
++
++unlock:
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable);
++
++int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_port *port)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (!port->enabled) {
++              mutex_unlock(&instance->vchiq_mutex);
++              return 0;
++      }
++
++      ret = port_disable(instance, port);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable);
++
++/* ports will be connected in a tunneled manner so data buffers
++ * are not handled by client.
++ */
++int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
++                                 struct vchiq_mmal_port *src,
++                                 struct vchiq_mmal_port *dst)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      /* disconnect ports if connected */
++      if (src->connected) {
++              ret = port_disable(instance, src);
++              if (ret) {
++                      pr_err("failed disabling src port(%d)\n", ret);
++                      goto release_unlock;
++              }
++
++              /* do not need to disable the destination port as they
++               * are connected and it is done automatically
++               */
++
++              ret = port_action_handle(instance, src,
++                                       MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
++                                       src->connected->component->handle,
++                                       src->connected->handle);
++              if (ret < 0) {
++                      pr_err("failed disconnecting src port\n");
++                      goto release_unlock;
++              }
++              src->connected->enabled = false;
++              src->connected = NULL;
++      }
++
++      if (!dst) {
++              /* do not make new connection */
++              ret = 0;
++              pr_debug("not making new connection\n");
++              goto release_unlock;
++      }
++
++      /* copy src port format to dst */
++      dst->format.encoding = src->format.encoding;
++      dst->es.video.width = src->es.video.width;
++      dst->es.video.height = src->es.video.height;
++      dst->es.video.crop.x = src->es.video.crop.x;
++      dst->es.video.crop.y = src->es.video.crop.y;
++      dst->es.video.crop.width = src->es.video.crop.width;
++      dst->es.video.crop.height = src->es.video.crop.height;
++      dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
++      dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
++
++      /* set new format */
++      ret = port_info_set(instance, dst);
++      if (ret) {
++              pr_debug("setting port info failed\n");
++              goto release_unlock;
++      }
++
++      /* read what has actually been set */
++      ret = port_info_get(instance, dst);
++      if (ret) {
++              pr_debug("read back port info failed\n");
++              goto release_unlock;
++      }
++
++      /* connect two ports together */
++      ret = port_action_handle(instance, src,
++                               MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
++                               dst->component->handle, dst->handle);
++      if (ret < 0) {
++              pr_debug("connecting port %d:%d to %d:%d failed\n",
++                       src->component->handle, src->handle,
++                       dst->component->handle, dst->handle);
++              goto release_unlock;
++      }
++      src->connected = dst;
++
++release_unlock:
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_connect_tunnel);
++
++int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_port *port,
++                           struct mmal_buffer *buffer)
++{
++      unsigned long flags = 0;
++      int ret;
++
++      ret = buffer_from_host(instance, port, buffer);
++      if (ret == -EINVAL) {
++              /* Port is disabled. Queue for when it is enabled. */
++              spin_lock_irqsave(&port->slock, flags);
++              list_add_tail(&buffer->list, &port->buffers);
++              spin_unlock_irqrestore(&port->slock, flags);
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_submit_buffer);
++
++int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
++                        struct mmal_buffer *buf)
++{
++      struct mmal_msg_context *msg_context = get_msg_context(instance);
++
++      if (IS_ERR(msg_context))
++              return (PTR_ERR(msg_context));
++
++      buf->msg_context = msg_context;
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
++
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
++{
++      struct mmal_msg_context *msg_context = buf->msg_context;
++
++      if (msg_context)
++              release_msg_context(msg_context);
++      buf->msg_context = NULL;
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
++
++/* Initialise a mmal component and its ports
++ *
++ */
++int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
++                            const char *name,
++                            struct vchiq_mmal_component **component_out)
++{
++      int ret;
++      int idx;                /* port index */
++      struct vchiq_mmal_component *component;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
++              ret = -EINVAL;  /* todo is this correct error? */
++              goto unlock;
++      }
++
++      component = &instance->component[instance->component_idx];
++
++      ret = create_component(instance, component, name);
++      if (ret < 0) {
++              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
++                     __func__, ret);
++              goto unlock;
++      }
++
++      /* ports info needs gathering */
++      component->control.type = MMAL_PORT_TYPE_CONTROL;
++      component->control.index = 0;
++      component->control.component = component;
++      spin_lock_init(&component->control.slock);
++      INIT_LIST_HEAD(&component->control.buffers);
++      ret = port_info_get(instance, &component->control);
++      if (ret < 0)
++              goto release_component;
++
++      for (idx = 0; idx < component->inputs; idx++) {
++              component->input[idx].type = MMAL_PORT_TYPE_INPUT;
++              component->input[idx].index = idx;
++              component->input[idx].component = component;
++              spin_lock_init(&component->input[idx].slock);
++              INIT_LIST_HEAD(&component->input[idx].buffers);
++              ret = port_info_get(instance, &component->input[idx]);
++              if (ret < 0)
++                      goto release_component;
++      }
++
++      for (idx = 0; idx < component->outputs; idx++) {
++              component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
++              component->output[idx].index = idx;
++              component->output[idx].component = component;
++              spin_lock_init(&component->output[idx].slock);
++              INIT_LIST_HEAD(&component->output[idx].buffers);
++              ret = port_info_get(instance, &component->output[idx]);
++              if (ret < 0)
++                      goto release_component;
++      }
++
++      for (idx = 0; idx < component->clocks; idx++) {
++              component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
++              component->clock[idx].index = idx;
++              component->clock[idx].component = component;
++              spin_lock_init(&component->clock[idx].slock);
++              INIT_LIST_HEAD(&component->clock[idx].buffers);
++              ret = port_info_get(instance, &component->clock[idx]);
++              if (ret < 0)
++                      goto release_component;
++      }
++
++      instance->component_idx++;
++
++      *component_out = component;
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return 0;
++
++release_component:
++      destroy_component(instance, component);
++unlock:
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_init);
++
++/*
++ * cause a mmal component to be destroyed
++ */
++int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_component *component)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (component->enabled)
++              ret = disable_component(instance, component);
++
++      ret = destroy_component(instance, component);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise);
++
++/*
++ * cause a mmal component to be enabled
++ */
++int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
++                              struct vchiq_mmal_component *component)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (component->enabled) {
++              mutex_unlock(&instance->vchiq_mutex);
++              return 0;
++      }
++
++      ret = enable_component(instance, component);
++      if (ret == 0)
++              component->enabled = true;
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable);
++
++/*
++ * cause a mmal component to be enabled
++ */
++int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
++                               struct vchiq_mmal_component *component)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (!component->enabled) {
++              mutex_unlock(&instance->vchiq_mutex);
++              return 0;
++      }
++
++      ret = disable_component(instance, component);
++      if (ret == 0)
++              component->enabled = false;
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable);
++
++int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
++                     u32 *major_out, u32 *minor_out)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = get_version(instance, major_out, minor_out);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_version);
++
++int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
++{
++      int status = 0;
++
++      if (!instance)
++              return -EINVAL;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      vchi_service_use(instance->handle);
++
++      status = vchi_service_close(instance->handle);
++      if (status != 0)
++              pr_err("mmal-vchiq: VCHIQ close failed\n");
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      flush_workqueue(instance->bulk_wq);
++      destroy_workqueue(instance->bulk_wq);
++
++      vfree(instance->bulk_scratch);
++
++      idr_destroy(&instance->context_map);
++
++      kfree(instance);
++
++      return status;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_finalise);
++
++int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
++{
++      int status;
++      struct vchiq_mmal_instance *instance;
++      static VCHI_CONNECTION_T *vchi_connection;
++      static VCHI_INSTANCE_T vchi_instance;
++      SERVICE_CREATION_T params = {
++              .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
++              .service_id             = VC_MMAL_SERVER_NAME,
++              .connection             = vchi_connection,
++              .rx_fifo_size           = 0,
++              .tx_fifo_size           = 0,
++              .callback               = service_callback,
++              .callback_param         = NULL,
++              .want_unaligned_bulk_rx = 1,
++              .want_unaligned_bulk_tx = 1,
++              .want_crc               = 0
++      };
++
++      /* compile time checks to ensure structure size as they are
++       * directly (de)serialised from memory.
++       */
++
++      /* ensure the header structure has packed to the correct size */
++      BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
++
++      /* ensure message structure does not exceed maximum length */
++      BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
++
++      /* mmal port struct is correct size */
++      BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
++
++      /* create a vchi instance */
++      status = vchi_initialise(&vchi_instance);
++      if (status) {
++              pr_err("Failed to initialise VCHI instance (status=%d)\n",
++                     status);
++              return -EIO;
++      }
++
++      status = vchi_connect(NULL, 0, vchi_instance);
++      if (status) {
++              pr_err("Failed to connect VCHI instance (status=%d)\n", status);
++              return -EIO;
++      }
++
++      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++
++      if (!instance)
++              return -ENOMEM;
++
++      mutex_init(&instance->vchiq_mutex);
++
++      instance->bulk_scratch = vmalloc(PAGE_SIZE);
++
++      mutex_init(&instance->context_map_lock);
++      idr_init_base(&instance->context_map, 1);
++
++      params.callback_param = instance;
++
++      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
++                                                  WQ_MEM_RECLAIM);
++      if (!instance->bulk_wq)
++              goto err_free;
++
++      status = vchi_service_open(vchi_instance, &params, &instance->handle);
++      if (status) {
++              pr_err("Failed to open VCHI service connection (status=%d)\n",
++                     status);
++              goto err_close_services;
++      }
++
++      vchi_service_release(instance->handle);
++
++      *out_instance = instance;
++
++      return 0;
++
++err_close_services:
++      vchi_service_close(instance->handle);
++      destroy_workqueue(instance->bulk_wq);
++err_free:
++      vfree(instance->bulk_scratch);
++      kfree(instance);
++      return -ENODEV;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_init);
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- *
+- * MMAL structures
+- *
+- */
+-#ifndef MMAL_COMMON_H
+-#define MMAL_COMMON_H
+-
+-#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
+-#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
+-
+-/** Special value signalling that time is not known */
+-#define MMAL_TIME_UNKNOWN BIT_ULL(63)
+-
+-struct mmal_msg_context;
+-
+-/* mapping between v4l and mmal video modes */
+-struct mmal_fmt {
+-      char  *name;
+-      u32   fourcc;          /* v4l2 format id */
+-      int   flags;           /* v4l2 flags field */
+-      u32   mmal;
+-      int   depth;
+-      u32   mmal_component;  /* MMAL component index to be used to encode */
+-      u32   ybbp;            /* depth of first Y plane for planar formats */
+-      bool  remove_padding;  /* Does the GPU have to remove padding,
+-                              * or can we do hide padding via bytesperline.
+-                              */
+-};
+-
+-/* buffer for one video frame */
+-struct mmal_buffer {
+-      /* v4l buffer data -- must be first */
+-      struct vb2_v4l2_buffer  vb;
+-
+-      /* list of buffers available */
+-      struct list_head        list;
+-
+-      void *buffer; /* buffer pointer */
+-      unsigned long buffer_size; /* size of allocated buffer */
+-
+-      struct mmal_msg_context *msg_context;
+-};
+-
+-/* */
+-struct mmal_colourfx {
+-      s32 enable;
+-      u32 u;
+-      u32 v;
+-};
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-#ifndef MMAL_ENCODINGS_H
+-#define MMAL_ENCODINGS_H
+-
+-#define MMAL_ENCODING_H264             MMAL_FOURCC('H', '2', '6', '4')
+-#define MMAL_ENCODING_H263             MMAL_FOURCC('H', '2', '6', '3')
+-#define MMAL_ENCODING_MP4V             MMAL_FOURCC('M', 'P', '4', 'V')
+-#define MMAL_ENCODING_MP2V             MMAL_FOURCC('M', 'P', '2', 'V')
+-#define MMAL_ENCODING_MP1V             MMAL_FOURCC('M', 'P', '1', 'V')
+-#define MMAL_ENCODING_WMV3             MMAL_FOURCC('W', 'M', 'V', '3')
+-#define MMAL_ENCODING_WMV2             MMAL_FOURCC('W', 'M', 'V', '2')
+-#define MMAL_ENCODING_WMV1             MMAL_FOURCC('W', 'M', 'V', '1')
+-#define MMAL_ENCODING_WVC1             MMAL_FOURCC('W', 'V', 'C', '1')
+-#define MMAL_ENCODING_VP8              MMAL_FOURCC('V', 'P', '8', ' ')
+-#define MMAL_ENCODING_VP7              MMAL_FOURCC('V', 'P', '7', ' ')
+-#define MMAL_ENCODING_VP6              MMAL_FOURCC('V', 'P', '6', ' ')
+-#define MMAL_ENCODING_THEORA           MMAL_FOURCC('T', 'H', 'E', 'O')
+-#define MMAL_ENCODING_SPARK            MMAL_FOURCC('S', 'P', 'R', 'K')
+-#define MMAL_ENCODING_MJPEG            MMAL_FOURCC('M', 'J', 'P', 'G')
+-
+-#define MMAL_ENCODING_JPEG             MMAL_FOURCC('J', 'P', 'E', 'G')
+-#define MMAL_ENCODING_GIF              MMAL_FOURCC('G', 'I', 'F', ' ')
+-#define MMAL_ENCODING_PNG              MMAL_FOURCC('P', 'N', 'G', ' ')
+-#define MMAL_ENCODING_PPM              MMAL_FOURCC('P', 'P', 'M', ' ')
+-#define MMAL_ENCODING_TGA              MMAL_FOURCC('T', 'G', 'A', ' ')
+-#define MMAL_ENCODING_BMP              MMAL_FOURCC('B', 'M', 'P', ' ')
+-
+-#define MMAL_ENCODING_I420             MMAL_FOURCC('I', '4', '2', '0')
+-#define MMAL_ENCODING_I420_SLICE       MMAL_FOURCC('S', '4', '2', '0')
+-#define MMAL_ENCODING_YV12             MMAL_FOURCC('Y', 'V', '1', '2')
+-#define MMAL_ENCODING_I422             MMAL_FOURCC('I', '4', '2', '2')
+-#define MMAL_ENCODING_I422_SLICE       MMAL_FOURCC('S', '4', '2', '2')
+-#define MMAL_ENCODING_YUYV             MMAL_FOURCC('Y', 'U', 'Y', 'V')
+-#define MMAL_ENCODING_YVYU             MMAL_FOURCC('Y', 'V', 'Y', 'U')
+-#define MMAL_ENCODING_UYVY             MMAL_FOURCC('U', 'Y', 'V', 'Y')
+-#define MMAL_ENCODING_VYUY             MMAL_FOURCC('V', 'Y', 'U', 'Y')
+-#define MMAL_ENCODING_NV12             MMAL_FOURCC('N', 'V', '1', '2')
+-#define MMAL_ENCODING_NV21             MMAL_FOURCC('N', 'V', '2', '1')
+-#define MMAL_ENCODING_ARGB             MMAL_FOURCC('A', 'R', 'G', 'B')
+-#define MMAL_ENCODING_RGBA             MMAL_FOURCC('R', 'G', 'B', 'A')
+-#define MMAL_ENCODING_ABGR             MMAL_FOURCC('A', 'B', 'G', 'R')
+-#define MMAL_ENCODING_BGRA             MMAL_FOURCC('B', 'G', 'R', 'A')
+-#define MMAL_ENCODING_RGB16            MMAL_FOURCC('R', 'G', 'B', '2')
+-#define MMAL_ENCODING_RGB24            MMAL_FOURCC('R', 'G', 'B', '3')
+-#define MMAL_ENCODING_RGB32            MMAL_FOURCC('R', 'G', 'B', '4')
+-#define MMAL_ENCODING_BGR16            MMAL_FOURCC('B', 'G', 'R', '2')
+-#define MMAL_ENCODING_BGR24            MMAL_FOURCC('B', 'G', 'R', '3')
+-#define MMAL_ENCODING_BGR32            MMAL_FOURCC('B', 'G', 'R', '4')
+-
+-/** SAND Video (YUVUV128) format, native format understood by VideoCore.
+- * This format is *not* opaque - if requested you will receive full frames
+- * of YUV_UV video.
+- */
+-#define MMAL_ENCODING_YUVUV128         MMAL_FOURCC('S', 'A', 'N', 'D')
+-
+-/** VideoCore opaque image format, image handles are returned to
+- * the host but not the actual image data.
+- */
+-#define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
+-
+-/** An EGL image handle
+- */
+-#define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
+-
+-/* }@ */
+-
+-/** \name Pre-defined audio encodings */
+-/* @{ */
+-#define MMAL_ENCODING_PCM_UNSIGNED_BE  MMAL_FOURCC('P', 'C', 'M', 'U')
+-#define MMAL_ENCODING_PCM_UNSIGNED_LE  MMAL_FOURCC('p', 'c', 'm', 'u')
+-#define MMAL_ENCODING_PCM_SIGNED_BE    MMAL_FOURCC('P', 'C', 'M', 'S')
+-#define MMAL_ENCODING_PCM_SIGNED_LE    MMAL_FOURCC('p', 'c', 'm', 's')
+-#define MMAL_ENCODING_PCM_FLOAT_BE     MMAL_FOURCC('P', 'C', 'M', 'F')
+-#define MMAL_ENCODING_PCM_FLOAT_LE     MMAL_FOURCC('p', 'c', 'm', 'f')
+-
+-/* Pre-defined H264 encoding variants */
+-
+-/** ISO 14496-10 Annex B byte stream format */
+-#define MMAL_ENCODING_VARIANT_H264_DEFAULT   0
+-/** ISO 14496-15 AVC stream format */
+-#define MMAL_ENCODING_VARIANT_H264_AVC1      MMAL_FOURCC('A', 'V', 'C', '1')
+-/** Implicitly delineated NAL units without emulation prevention */
+-#define MMAL_ENCODING_VARIANT_H264_RAW       MMAL_FOURCC('R', 'A', 'W', ' ')
+-
+-/** \defgroup MmalColorSpace List of pre-defined video color spaces
+- * This defines a list of common color spaces. This list isn't exhaustive and
+- * is only provided as a convenience to avoid clients having to use FourCC
+- * codes directly. However components are allowed to define and use their own
+- * FourCC codes.
+- */
+-/* @{ */
+-
+-/** Unknown color space */
+-#define MMAL_COLOR_SPACE_UNKNOWN       0
+-/** ITU-R BT.601-5 [SDTV] */
+-#define MMAL_COLOR_SPACE_ITUR_BT601    MMAL_FOURCC('Y', '6', '0', '1')
+-/** ITU-R BT.709-3 [HDTV] */
+-#define MMAL_COLOR_SPACE_ITUR_BT709    MMAL_FOURCC('Y', '7', '0', '9')
+-/** JPEG JFIF */
+-#define MMAL_COLOR_SPACE_JPEG_JFIF     MMAL_FOURCC('Y', 'J', 'F', 'I')
+-/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
+-#define MMAL_COLOR_SPACE_FCC           MMAL_FOURCC('Y', 'F', 'C', 'C')
+-/** Society of Motion Picture and Television Engineers 240M (1999) */
+-#define MMAL_COLOR_SPACE_SMPTE240M     MMAL_FOURCC('Y', '2', '4', '0')
+-/** ITU-R BT.470-2 System M */
+-#define MMAL_COLOR_SPACE_BT470_2_M     MMAL_FOURCC('Y', '_', '_', 'M')
+-/** ITU-R BT.470-2 System BG */
+-#define MMAL_COLOR_SPACE_BT470_2_BG    MMAL_FOURCC('Y', '_', 'B', 'G')
+-/** JPEG JFIF, but with 16..255 luma */
+-#define MMAL_COLOR_SPACE_JFIF_Y16_255  MMAL_FOURCC('Y', 'Y', '1', '6')
+-/* @} MmalColorSpace List */
+-
+-#endif /* MMAL_ENCODINGS_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-#ifndef MMAL_MSG_COMMON_H
+-#define MMAL_MSG_COMMON_H
+-
+-enum mmal_msg_status {
+-      MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
+-      MMAL_MSG_STATUS_ENOMEM,      /**< Out of memory */
+-      MMAL_MSG_STATUS_ENOSPC,      /**< Out of resources other than memory */
+-      MMAL_MSG_STATUS_EINVAL,      /**< Argument is invalid */
+-      MMAL_MSG_STATUS_ENOSYS,      /**< Function not implemented */
+-      MMAL_MSG_STATUS_ENOENT,      /**< No such file or directory */
+-      MMAL_MSG_STATUS_ENXIO,       /**< No such device or address */
+-      MMAL_MSG_STATUS_EIO,         /**< I/O error */
+-      MMAL_MSG_STATUS_ESPIPE,      /**< Illegal seek */
+-      MMAL_MSG_STATUS_ECORRUPT,    /**< Data is corrupt \attention */
+-      MMAL_MSG_STATUS_ENOTREADY,   /**< Component is not ready */
+-      MMAL_MSG_STATUS_ECONFIG,     /**< Component is not configured */
+-      MMAL_MSG_STATUS_EISCONN,     /**< Port is already connected */
+-      MMAL_MSG_STATUS_ENOTCONN,    /**< Port is disconnected */
+-      MMAL_MSG_STATUS_EAGAIN,      /**< Resource temporarily unavailable. */
+-      MMAL_MSG_STATUS_EFAULT,      /**< Bad address */
+-};
+-
+-struct mmal_rect {
+-      s32 x;      /**< x coordinate (from left) */
+-      s32 y;      /**< y coordinate (from top) */
+-      s32 width;  /**< width */
+-      s32 height; /**< height */
+-};
+-
+-struct mmal_rational {
+-      s32 num;    /**< Numerator */
+-      s32 den;    /**< Denominator */
+-};
+-
+-#endif /* MMAL_MSG_COMMON_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-#ifndef MMAL_MSG_FORMAT_H
+-#define MMAL_MSG_FORMAT_H
+-
+-#include "mmal-msg-common.h"
+-
+-/* MMAL_ES_FORMAT_T */
+-
+-struct mmal_audio_format {
+-      u32 channels;           /* Number of audio channels */
+-      u32 sample_rate;        /* Sample rate */
+-
+-      u32 bits_per_sample;    /* Bits per sample */
+-      u32 block_align;        /* Size of a block of data */
+-};
+-
+-struct mmal_video_format {
+-      u32 width;              /* Width of frame in pixels */
+-      u32 height;             /* Height of frame in rows of pixels */
+-      struct mmal_rect crop;  /* Visible region of the frame */
+-      struct mmal_rational frame_rate;        /* Frame rate */
+-      struct mmal_rational par;               /* Pixel aspect ratio */
+-
+-      /*
+-       * FourCC specifying the color space of the video stream. See the
+-       * MmalColorSpace "pre-defined color spaces" for some examples.
+-       */
+-      u32 color_space;
+-};
+-
+-struct mmal_subpicture_format {
+-      u32 x_offset;
+-      u32 y_offset;
+-};
+-
+-union mmal_es_specific_format {
+-      struct mmal_audio_format audio;
+-      struct mmal_video_format video;
+-      struct mmal_subpicture_format subpicture;
+-};
+-
+-/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
+-struct mmal_es_format_local {
+-      u32 type;       /* enum mmal_es_type */
+-
+-      u32 encoding;   /* FourCC specifying encoding of the elementary
+-                       * stream.
+-                       */
+-      u32 encoding_variant;   /* FourCC specifying the specific
+-                               * encoding variant of the elementary
+-                               * stream.
+-                               */
+-
+-      union mmal_es_specific_format *es;      /* Type specific
+-                                               * information for the
+-                                               * elementary stream
+-                                               */
+-
+-      u32 bitrate;    /* Bitrate in bits per second */
+-      u32 flags;      /* Flags describing properties of the elementary
+-                       * stream.
+-                       */
+-
+-      u32 extradata_size;     /* Size of the codec specific data */
+-      u8  *extradata;         /* Codec specific data */
+-};
+-
+-/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
+-struct mmal_es_format {
+-      u32 type;       /* enum mmal_es_type */
+-
+-      u32 encoding;   /* FourCC specifying encoding of the elementary
+-                       * stream.
+-                       */
+-      u32 encoding_variant;   /* FourCC specifying the specific
+-                               * encoding variant of the elementary
+-                               * stream.
+-                               */
+-
+-      u32 es; /* Type specific
+-               * information for the
+-               * elementary stream
+-               */
+-
+-      u32 bitrate;    /* Bitrate in bits per second */
+-      u32 flags;      /* Flags describing properties of the elementary
+-                       * stream.
+-                       */
+-
+-      u32 extradata_size;     /* Size of the codec specific data */
+-      u32 extradata;          /* Codec specific data */
+-};
+-
+-#endif /* MMAL_MSG_FORMAT_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
++++ /dev/null
+@@ -1,109 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-/* MMAL_PORT_TYPE_T */
+-enum mmal_port_type {
+-      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
+-      MMAL_PORT_TYPE_CONTROL,         /* Control port */
+-      MMAL_PORT_TYPE_INPUT,           /* Input port */
+-      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
+-      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
+-};
+-
+-/* The port is pass-through and doesn't need buffer headers allocated */
+-#define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
+-/*
+- *The port wants to allocate the buffer payloads.
+- * This signals a preference that payload allocation should be done
+- * on this port for efficiency reasons.
+- */
+-#define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
+-/*
+- * The port supports format change events.
+- * This applies to input ports and is used to let the client know
+- * whether the port supports being reconfigured via a format
+- * change event (i.e. without having to disable the port).
+- */
+-#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
+-
+-/*
+- * mmal port structure (MMAL_PORT_T)
+- *
+- * most elements are informational only, the pointer values for
+- * interogation messages are generally provided as additional
+- * structures within the message. When used to set values only the
+- * buffer_num, buffer_size and userdata parameters are writable.
+- */
+-struct mmal_port {
+-      u32 priv;       /* Private member used by the framework */
+-      u32 name;       /* Port name. Used for debugging purposes (RO) */
+-
+-      u32 type;       /* Type of the port (RO) enum mmal_port_type */
+-      u16 index;      /* Index of the port in its type list (RO) */
+-      u16 index_all;  /* Index of the port in the list of all ports (RO) */
+-
+-      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
+-      u32 format;     /* Format of the elementary stream */
+-
+-      u32 buffer_num_min;     /* Minimum number of buffers the port
+-                               *   requires (RO).  This is set by the
+-                               *   component.
+-                               */
+-
+-      u32 buffer_size_min;    /* Minimum size of buffers the port
+-                               * requires (RO).  This is set by the
+-                               * component.
+-                               */
+-
+-      u32 buffer_alignment_min;/* Minimum alignment requirement for
+-                                * the buffers (RO).  A value of
+-                                * zero means no special alignment
+-                                * requirements.  This is set by the
+-                                * component.
+-                                */
+-
+-      u32 buffer_num_recommended;     /* Number of buffers the port
+-                                       * recommends for optimal
+-                                       * performance (RO).  A value of
+-                                       * zero means no special
+-                                       * recommendation.  This is set
+-                                       * by the component.
+-                                       */
+-
+-      u32 buffer_size_recommended;    /* Size of buffers the port
+-                                       * recommends for optimal
+-                                       * performance (RO).  A value of
+-                                       * zero means no special
+-                                       * recommendation.  This is set
+-                                       * by the component.
+-                                       */
+-
+-      u32 buffer_num; /* Actual number of buffers the port will use.
+-                       * This is set by the client.
+-                       */
+-
+-      u32 buffer_size; /* Actual maximum size of the buffers that
+-                        * will be sent to the port. This is set by
+-                        * the client.
+-                        */
+-
+-      u32 component;  /* Component this port belongs to (Read Only) */
+-
+-      u32 userdata;   /* Field reserved for use by the client */
+-
+-      u32 capabilities;       /* Flags describing the capabilities of a
+-                               * port (RO).  Bitwise combination of \ref
+-                               * portcapabilities "Port capabilities"
+-                               * values.
+-                               */
+-};
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ /dev/null
+@@ -1,406 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-/*
+- * all the data structures which serialise the MMAL protocol. note
+- * these are directly mapped onto the recived message data.
+- *
+- * BEWARE: They seem to *assume* pointers are u32 and that there is no
+- * structure padding!
+- *
+- * NOTE: this implementation uses kernel types to ensure sizes. Rather
+- * than assigning values to enums to force their size the
+- * implementation uses fixed size types and not the enums (though the
+- * comments have the actual enum type
+- */
+-#ifndef MMAL_MSG_H
+-#define MMAL_MSG_H
+-
+-#define VC_MMAL_VER 15
+-#define VC_MMAL_MIN_VER 10
+-#define VC_MMAL_SERVER_NAME  MAKE_FOURCC("mmal")
+-
+-/* max total message size is 512 bytes */
+-#define MMAL_MSG_MAX_SIZE 512
+-/* with six 32bit header elements max payload is therefore 488 bytes */
+-#define MMAL_MSG_MAX_PAYLOAD 488
+-
+-#include "mmal-msg-common.h"
+-#include "mmal-msg-format.h"
+-#include "mmal-msg-port.h"
+-
+-enum mmal_msg_type {
+-      MMAL_MSG_TYPE_QUIT = 1,
+-      MMAL_MSG_TYPE_SERVICE_CLOSED,
+-      MMAL_MSG_TYPE_GET_VERSION,
+-      MMAL_MSG_TYPE_COMPONENT_CREATE,
+-      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
+-      MMAL_MSG_TYPE_COMPONENT_ENABLE,
+-      MMAL_MSG_TYPE_COMPONENT_DISABLE,
+-      MMAL_MSG_TYPE_PORT_INFO_GET,
+-      MMAL_MSG_TYPE_PORT_INFO_SET,
+-      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
+-      MMAL_MSG_TYPE_BUFFER_FROM_HOST,
+-      MMAL_MSG_TYPE_BUFFER_TO_HOST,
+-      MMAL_MSG_TYPE_GET_STATS,
+-      MMAL_MSG_TYPE_PORT_PARAMETER_SET,
+-      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
+-      MMAL_MSG_TYPE_EVENT_TO_HOST,
+-      MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
+-      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
+-      MMAL_MSG_TYPE_CONSUME_MEM,
+-      MMAL_MSG_TYPE_LMK,                      /* 20 */
+-      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
+-      MMAL_MSG_TYPE_DRM_GET_LHS32,
+-      MMAL_MSG_TYPE_DRM_GET_TIME,
+-      MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
+-      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
+-      MMAL_MSG_TYPE_HOST_LOG,
+-      MMAL_MSG_TYPE_MSG_LAST
+-};
+-
+-/* port action request messages differ depending on the action type */
+-enum mmal_msg_port_action_type {
+-      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
+-      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
+-      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
+-      MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
+-};
+-
+-struct mmal_msg_header {
+-      u32 magic;
+-      u32 type;       /* enum mmal_msg_type */
+-
+-      /* Opaque handle to the control service */
+-      u32 control_service;
+-
+-      u32 context;    /* a u32 per message context */
+-      u32 status;     /* The status of the vchiq operation */
+-      u32 padding;
+-};
+-
+-/* Send from VC to host to report version */
+-struct mmal_msg_version {
+-      u32 flags;
+-      u32 major;
+-      u32 minor;
+-      u32 minimum;
+-};
+-
+-/* request to VC to create component */
+-struct mmal_msg_component_create {
+-      u32 client_component;   /* component context */
+-      char name[128];
+-      u32 pid;                /* For debug */
+-};
+-
+-/* reply from VC to component creation request */
+-struct mmal_msg_component_create_reply {
+-      u32 status;     /* enum mmal_msg_status - how does this differ to
+-                       * the one in the header?
+-                       */
+-      u32 component_handle; /* VideoCore handle for component */
+-      u32 input_num;        /* Number of input ports */
+-      u32 output_num;       /* Number of output ports */
+-      u32 clock_num;        /* Number of clock ports */
+-};
+-
+-/* request to VC to destroy a component */
+-struct mmal_msg_component_destroy {
+-      u32 component_handle;
+-};
+-
+-struct mmal_msg_component_destroy_reply {
+-      u32 status; /* The component destruction status */
+-};
+-
+-/* request and reply to VC to enable a component */
+-struct mmal_msg_component_enable {
+-      u32 component_handle;
+-};
+-
+-struct mmal_msg_component_enable_reply {
+-      u32 status; /* The component enable status */
+-};
+-
+-/* request and reply to VC to disable a component */
+-struct mmal_msg_component_disable {
+-      u32 component_handle;
+-};
+-
+-struct mmal_msg_component_disable_reply {
+-      u32 status; /* The component disable status */
+-};
+-
+-/* request to VC to get port information */
+-struct mmal_msg_port_info_get {
+-      u32 component_handle;  /* component handle port is associated with */
+-      u32 port_type;         /* enum mmal_msg_port_type */
+-      u32 index;             /* port index to query */
+-};
+-
+-/* reply from VC to get port info request */
+-struct mmal_msg_port_info_get_reply {
+-      u32 status;             /* enum mmal_msg_status */
+-      u32 component_handle;   /* component handle port is associated with */
+-      u32 port_type;          /* enum mmal_msg_port_type */
+-      u32 port_index;         /* port indexed in query */
+-      s32 found;              /* unused */
+-      u32 port_handle;        /* Handle to use for this port */
+-      struct mmal_port port;
+-      struct mmal_es_format format; /* elementary stream format */
+-      union mmal_es_specific_format es; /* es type specific data */
+-      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
+-};
+-
+-/* request to VC to set port information */
+-struct mmal_msg_port_info_set {
+-      u32 component_handle;
+-      u32 port_type;          /* enum mmal_msg_port_type */
+-      u32 port_index;         /* port indexed in query */
+-      struct mmal_port port;
+-      struct mmal_es_format format;
+-      union mmal_es_specific_format es;
+-      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
+-};
+-
+-/* reply from VC to port info set request */
+-struct mmal_msg_port_info_set_reply {
+-      u32 status;
+-      u32 component_handle;   /* component handle port is associated with */
+-      u32 port_type;          /* enum mmal_msg_port_type */
+-      u32 index;              /* port indexed in query */
+-      s32 found;              /* unused */
+-      u32 port_handle;        /* Handle to use for this port */
+-      struct mmal_port port;
+-      struct mmal_es_format format;
+-      union mmal_es_specific_format es;
+-      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
+-};
+-
+-/* port action requests that take a mmal_port as a parameter */
+-struct mmal_msg_port_action_port {
+-      u32 component_handle;
+-      u32 port_handle;
+-      u32 action;             /* enum mmal_msg_port_action_type */
+-      struct mmal_port port;
+-};
+-
+-/* port action requests that take handles as a parameter */
+-struct mmal_msg_port_action_handle {
+-      u32 component_handle;
+-      u32 port_handle;
+-      u32 action;             /* enum mmal_msg_port_action_type */
+-      u32 connect_component_handle;
+-      u32 connect_port_handle;
+-};
+-
+-struct mmal_msg_port_action_reply {
+-      u32 status;     /* The port action operation status */
+-};
+-
+-/* MMAL buffer transfer */
+-
+-/* Size of space reserved in a buffer message for short messages. */
+-#define MMAL_VC_SHORT_DATA 128
+-
+-/* Signals that the current payload is the end of the stream of data */
+-#define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
+-/* Signals that the start of the current payload starts a frame */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
+-/* Signals that the end of the current payload ends a frame */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
+-/* Signals that the current payload contains only complete frames (>1) */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
+-      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
+-       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
+-/* Signals that the current payload is a keyframe (i.e. self decodable) */
+-#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
+-/*
+- * Signals a discontinuity in the stream of data (e.g. after a seek).
+- * Can be used for instance by a decoder to reset its state
+- */
+-#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
+-/*
+- * Signals a buffer containing some kind of config data for the component
+- * (e.g. codec config data)
+- */
+-#define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
+-/* Signals an encrypted payload */
+-#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
+-/* Signals a buffer containing side information */
+-#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
+-/*
+- * Signals a buffer which is the snapshot/postview image from a stills
+- * capture
+- */
+-#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
+-/* Signals a buffer which contains data known to be corrupted */
+-#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
+-/* Signals that a buffer failed to be transmitted */
+-#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
+-
+-struct mmal_driver_buffer {
+-      u32 magic;
+-      u32 component_handle;
+-      u32 port_handle;
+-      u32 client_context;
+-};
+-
+-/* buffer header */
+-struct mmal_buffer_header {
+-      u32 next;       /* next header */
+-      u32 priv;       /* framework private data */
+-      u32 cmd;
+-      u32 data;
+-      u32 alloc_size;
+-      u32 length;
+-      u32 offset;
+-      u32 flags;
+-      s64 pts;
+-      s64 dts;
+-      u32 type;
+-      u32 user_data;
+-};
+-
+-struct mmal_buffer_header_type_specific {
+-      union {
+-              struct {
+-              u32 planes;
+-              u32 offset[4];
+-              u32 pitch[4];
+-              u32 flags;
+-              } video;
+-      } u;
+-};
+-
+-struct mmal_msg_buffer_from_host {
+-      /*
+-       *The front 32 bytes of the buffer header are copied
+-       * back to us in the reply to allow for context. This
+-       * area is used to store two mmal_driver_buffer structures to
+-       * allow for multiple concurrent service users.
+-       */
+-      /* control data */
+-      struct mmal_driver_buffer drvbuf;
+-
+-      /* referenced control data for passthrough buffer management */
+-      struct mmal_driver_buffer drvbuf_ref;
+-      struct mmal_buffer_header buffer_header; /* buffer header itself */
+-      struct mmal_buffer_header_type_specific buffer_header_type_specific;
+-      s32 is_zero_copy;
+-      s32 has_reference;
+-
+-      /* allows short data to be xfered in control message */
+-      u32 payload_in_message;
+-      u8 short_data[MMAL_VC_SHORT_DATA];
+-};
+-
+-/* port parameter setting */
+-
+-#define MMAL_WORKER_PORT_PARAMETER_SPACE      96
+-
+-struct mmal_msg_port_parameter_set {
+-      u32 component_handle;   /* component */
+-      u32 port_handle;        /* port */
+-      u32 id;                 /* Parameter ID  */
+-      u32 size;               /* Parameter size */
+-      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+-};
+-
+-struct mmal_msg_port_parameter_set_reply {
+-      u32 status;     /* enum mmal_msg_status todo: how does this
+-                       * differ to the one in the header?
+-                       */
+-};
+-
+-/* port parameter getting */
+-
+-struct mmal_msg_port_parameter_get {
+-      u32 component_handle;   /* component */
+-      u32 port_handle;        /* port */
+-      u32 id;                 /* Parameter ID  */
+-      u32 size;               /* Parameter size */
+-};
+-
+-struct mmal_msg_port_parameter_get_reply {
+-      u32 status;             /* Status of mmal_port_parameter_get call */
+-      u32 id;                 /* Parameter ID  */
+-      u32 size;               /* Parameter size */
+-      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+-};
+-
+-/* event messages */
+-#define MMAL_WORKER_EVENT_SPACE 256
+-
+-struct mmal_msg_event_to_host {
+-      u32 client_component;   /* component context */
+-
+-      u32 port_type;
+-      u32 port_num;
+-
+-      u32 cmd;
+-      u32 length;
+-      u8 data[MMAL_WORKER_EVENT_SPACE];
+-      u32 delayed_buffer;
+-};
+-
+-/* all mmal messages are serialised through this structure */
+-struct mmal_msg {
+-      /* header */
+-      struct mmal_msg_header h;
+-      /* payload */
+-      union {
+-              struct mmal_msg_version version;
+-
+-              struct mmal_msg_component_create component_create;
+-              struct mmal_msg_component_create_reply component_create_reply;
+-
+-              struct mmal_msg_component_destroy component_destroy;
+-              struct mmal_msg_component_destroy_reply component_destroy_reply;
+-
+-              struct mmal_msg_component_enable component_enable;
+-              struct mmal_msg_component_enable_reply component_enable_reply;
+-
+-              struct mmal_msg_component_disable component_disable;
+-              struct mmal_msg_component_disable_reply component_disable_reply;
+-
+-              struct mmal_msg_port_info_get port_info_get;
+-              struct mmal_msg_port_info_get_reply port_info_get_reply;
+-
+-              struct mmal_msg_port_info_set port_info_set;
+-              struct mmal_msg_port_info_set_reply port_info_set_reply;
+-
+-              struct mmal_msg_port_action_port port_action_port;
+-              struct mmal_msg_port_action_handle port_action_handle;
+-              struct mmal_msg_port_action_reply port_action_reply;
+-
+-              struct mmal_msg_buffer_from_host buffer_from_host;
+-
+-              struct mmal_msg_port_parameter_set port_parameter_set;
+-              struct mmal_msg_port_parameter_set_reply
+-                      port_parameter_set_reply;
+-              struct mmal_msg_port_parameter_get
+-                      port_parameter_get;
+-              struct mmal_msg_port_parameter_get_reply
+-                      port_parameter_get_reply;
+-
+-              struct mmal_msg_event_to_host event_to_host;
+-
+-              u8 payload[MMAL_MSG_MAX_PAYLOAD];
+-      } u;
+-};
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ /dev/null
+@@ -1,755 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-/* common parameters */
+-
+-/** @name Parameter groups
+- * Parameters are divided into groups, and then allocated sequentially within
+- * a group using an enum.
+- * @{
+- */
+-
+-#ifndef MMAL_PARAMETERS_H
+-#define MMAL_PARAMETERS_H
+-
+-/** Common parameter ID group, used with many types of component. */
+-#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
+-/** Camera-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
+-/** Video-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
+-/** Audio-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
+-/** Clock-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
+-/** Miracast-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
+-
+-/* Common parameters */
+-enum mmal_parameter_common_type {
+-      /**< Never a valid parameter ID */
+-      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
+-
+-              /**< MMAL_PARAMETER_ENCODING_T */
+-      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
+-              /**< MMAL_PARAMETER_URI_T */
+-      MMAL_PARAMETER_URI,
+-              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
+-      MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
+-              /** MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ZERO_COPY,
+-              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
+-      MMAL_PARAMETER_BUFFER_REQUIREMENTS,
+-              /**< MMAL_PARAMETER_STATISTICS_T */
+-      MMAL_PARAMETER_STATISTICS,
+-              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
+-      MMAL_PARAMETER_CORE_STATISTICS,
+-              /**< MMAL_PARAMETER_MEM_USAGE_T */
+-      MMAL_PARAMETER_MEM_USAGE,
+-              /**< MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
+-              /**< MMAL_PARAMETER_SEEK_T */
+-      MMAL_PARAMETER_SEEK,
+-              /**< MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_POWERMON_ENABLE,
+-              /**< MMAL_PARAMETER_LOGGING_T */
+-      MMAL_PARAMETER_LOGGING,
+-              /**< MMAL_PARAMETER_UINT64_T */
+-      MMAL_PARAMETER_SYSTEM_TIME,
+-              /**< MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_NO_IMAGE_PADDING,
+-};
+-
+-/* camera parameters */
+-
+-enum mmal_parameter_camera_type {
+-      /* 0 */
+-              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
+-      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
+-              MMAL_PARAMETER_GROUP_CAMERA,
+-              /**< Unused? */
+-      MMAL_PARAMETER_CAPTURE_QUALITY,
+-              /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_ROTATION,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_EXIF_DISABLE,
+-              /**< @ref MMAL_PARAMETER_EXIF_T */
+-      MMAL_PARAMETER_EXIF,
+-              /**< @ref MMAL_PARAM_AWBMODE_T */
+-      MMAL_PARAMETER_AWB_MODE,
+-              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
+-      MMAL_PARAMETER_IMAGE_EFFECT,
+-              /**< @ref MMAL_PARAMETER_COLOURFX_T */
+-      MMAL_PARAMETER_COLOUR_EFFECT,
+-              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
+-      MMAL_PARAMETER_FLICKER_AVOID,
+-              /**< @ref MMAL_PARAMETER_FLASH_T */
+-      MMAL_PARAMETER_FLASH,
+-              /**< @ref MMAL_PARAMETER_REDEYE_T */
+-      MMAL_PARAMETER_REDEYE,
+-              /**< @ref MMAL_PARAMETER_FOCUS_T */
+-      MMAL_PARAMETER_FOCUS,
+-              /**< Unused? */
+-      MMAL_PARAMETER_FOCAL_LENGTHS,
+-              /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_EXPOSURE_COMP,
+-              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
+-      MMAL_PARAMETER_ZOOM,
+-              /**< @ref MMAL_PARAMETER_MIRROR_T */
+-      MMAL_PARAMETER_MIRROR,
+-
+-      /* 0x10 */
+-              /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CAMERA_NUM,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_CAPTURE,
+-              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
+-      MMAL_PARAMETER_EXPOSURE_MODE,
+-              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
+-      MMAL_PARAMETER_EXP_METERING_MODE,
+-              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
+-      MMAL_PARAMETER_FOCUS_STATUS,
+-              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
+-      MMAL_PARAMETER_CAMERA_CONFIG,
+-              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
+-      MMAL_PARAMETER_CAPTURE_STATUS,
+-              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
+-      MMAL_PARAMETER_FACE_TRACK,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
+-              /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_JPEG_Q_FACTOR,
+-              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
+-      MMAL_PARAMETER_FRAME_RATE,
+-              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
+-      MMAL_PARAMETER_USE_STC,
+-              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
+-      MMAL_PARAMETER_CAMERA_INFO,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_STABILISATION,
+-              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
+-      MMAL_PARAMETER_FACE_TRACK_RESULTS,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
+-
+-      /* 0x20 */
+-              /**< @ref MMAL_PARAMETER_URI_T */
+-      MMAL_PARAMETER_DPF_FILE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ENABLE_DPF_FILE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
+-              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
+-      MMAL_PARAMETER_CAPTURE_MODE,
+-              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
+-      MMAL_PARAMETER_FOCUS_REGIONS,
+-              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
+-      MMAL_PARAMETER_INPUT_CROP,
+-              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
+-      MMAL_PARAMETER_SENSOR_INFORMATION,
+-              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
+-      MMAL_PARAMETER_FLASH_SELECT,
+-              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
+-      MMAL_PARAMETER_FIELD_OF_VIEW,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
+-              /**< @ref MMAL_PARAMETER_DRC_T */
+-      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
+-              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
+-      MMAL_PARAMETER_ALGORITHM_CONTROL,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_SHARPNESS,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_CONTRAST,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_BRIGHTNESS,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_SATURATION,
+-
+-      /* 0x30 */
+-              /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_ISO,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ANTISHAKE,
+-              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
+-      MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
+-              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
+-              /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CAMERA_MIN_ISO,
+-              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
+-      MMAL_PARAMETER_CAMERA_USE_CASE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_CAPTURE_STATS_PASS,
+-              /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
+-              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ENABLE_REGISTER_FILE,
+-              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
+-              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
+-      MMAL_PARAMETER_CONFIGFILE_REGISTERS,
+-              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
+-      MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_JPEG_ATTACH_LOG,
+-              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
+-      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
+-              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
+-      MMAL_PARAMETER_FPS_RANGE,
+-              /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
+-
+-      /* 0x40 */
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_FLASH_REQUIRED,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_SW_SATURATION_DISABLE,
+-      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_SHUTTER_SPEED,
+-              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
+-      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
+-};
+-
+-struct mmal_parameter_rational {
+-      s32 num;    /**< Numerator */
+-      s32 den;    /**< Denominator */
+-};
+-
+-enum mmal_parameter_camera_config_timestamp_mode {
+-      MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
+-      MMAL_PARAM_TIMESTAMP_MODE_RAW_STC,  /* Use the raw STC value
+-                                           * for the frame timestamp
+-                                           */
+-      MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
+-                                            * but subtract the
+-                                            * timestamp of the first
+-                                            * frame sent to give a
+-                                            * zero based timestamp.
+-                                            */
+-};
+-
+-struct mmal_parameter_fps_range {
+-      /**< Low end of the permitted framerate range */
+-      struct mmal_parameter_rational  fps_low;
+-      /**< High end of the permitted framerate range */
+-      struct mmal_parameter_rational  fps_high;
+-};
+-
+-/* camera configuration parameter */
+-struct mmal_parameter_camera_config {
+-      /* Parameters for setting up the image pools */
+-      u32 max_stills_w; /* Max size of stills capture */
+-      u32 max_stills_h;
+-      u32 stills_yuv422; /* Allow YUV422 stills capture */
+-      u32 one_shot_stills; /* Continuous or one shot stills captures. */
+-
+-      u32 max_preview_video_w; /* Max size of the preview or video
+-                                * capture frames
+-                                */
+-      u32 max_preview_video_h;
+-      u32 num_preview_video_frames;
+-
+-      /** Sets the height of the circular buffer for stills capture. */
+-      u32 stills_capture_circular_buffer_height;
+-
+-      /** Allows preview/encode to resume as fast as possible after the stills
+-       * input frame has been received, and then processes the still frame in
+-       * the background whilst preview/encode has resumed.
+-       * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
+-       */
+-      u32 fast_preview_resume;
+-
+-      /** Selects algorithm for timestamping frames if
+-       * there is no clock component connected.
+-       * enum mmal_parameter_camera_config_timestamp_mode
+-       */
+-      s32 use_stc_timestamp;
+-};
+-
+-enum mmal_parameter_exposuremode {
+-      MMAL_PARAM_EXPOSUREMODE_OFF,
+-      MMAL_PARAM_EXPOSUREMODE_AUTO,
+-      MMAL_PARAM_EXPOSUREMODE_NIGHT,
+-      MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
+-      MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
+-      MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
+-      MMAL_PARAM_EXPOSUREMODE_SPORTS,
+-      MMAL_PARAM_EXPOSUREMODE_SNOW,
+-      MMAL_PARAM_EXPOSUREMODE_BEACH,
+-      MMAL_PARAM_EXPOSUREMODE_VERYLONG,
+-      MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
+-      MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
+-      MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
+-};
+-
+-enum mmal_parameter_exposuremeteringmode {
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
+-};
+-
+-enum mmal_parameter_awbmode {
+-      MMAL_PARAM_AWBMODE_OFF,
+-      MMAL_PARAM_AWBMODE_AUTO,
+-      MMAL_PARAM_AWBMODE_SUNLIGHT,
+-      MMAL_PARAM_AWBMODE_CLOUDY,
+-      MMAL_PARAM_AWBMODE_SHADE,
+-      MMAL_PARAM_AWBMODE_TUNGSTEN,
+-      MMAL_PARAM_AWBMODE_FLUORESCENT,
+-      MMAL_PARAM_AWBMODE_INCANDESCENT,
+-      MMAL_PARAM_AWBMODE_FLASH,
+-      MMAL_PARAM_AWBMODE_HORIZON,
+-};
+-
+-enum mmal_parameter_imagefx {
+-      MMAL_PARAM_IMAGEFX_NONE,
+-      MMAL_PARAM_IMAGEFX_NEGATIVE,
+-      MMAL_PARAM_IMAGEFX_SOLARIZE,
+-      MMAL_PARAM_IMAGEFX_POSTERIZE,
+-      MMAL_PARAM_IMAGEFX_WHITEBOARD,
+-      MMAL_PARAM_IMAGEFX_BLACKBOARD,
+-      MMAL_PARAM_IMAGEFX_SKETCH,
+-      MMAL_PARAM_IMAGEFX_DENOISE,
+-      MMAL_PARAM_IMAGEFX_EMBOSS,
+-      MMAL_PARAM_IMAGEFX_OILPAINT,
+-      MMAL_PARAM_IMAGEFX_HATCH,
+-      MMAL_PARAM_IMAGEFX_GPEN,
+-      MMAL_PARAM_IMAGEFX_PASTEL,
+-      MMAL_PARAM_IMAGEFX_WATERCOLOUR,
+-      MMAL_PARAM_IMAGEFX_FILM,
+-      MMAL_PARAM_IMAGEFX_BLUR,
+-      MMAL_PARAM_IMAGEFX_SATURATION,
+-      MMAL_PARAM_IMAGEFX_COLOURSWAP,
+-      MMAL_PARAM_IMAGEFX_WASHEDOUT,
+-      MMAL_PARAM_IMAGEFX_POSTERISE,
+-      MMAL_PARAM_IMAGEFX_COLOURPOINT,
+-      MMAL_PARAM_IMAGEFX_COLOURBALANCE,
+-      MMAL_PARAM_IMAGEFX_CARTOON,
+-};
+-
+-enum MMAL_PARAM_FLICKERAVOID_T {
+-      MMAL_PARAM_FLICKERAVOID_OFF,
+-      MMAL_PARAM_FLICKERAVOID_AUTO,
+-      MMAL_PARAM_FLICKERAVOID_50HZ,
+-      MMAL_PARAM_FLICKERAVOID_60HZ,
+-      MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
+-};
+-
+-struct mmal_parameter_awbgains {
+-      struct mmal_parameter_rational r_gain;  /**< Red gain */
+-      struct mmal_parameter_rational b_gain;  /**< Blue gain */
+-};
+-
+-/** Manner of video rate control */
+-enum mmal_parameter_rate_control_mode {
+-      MMAL_VIDEO_RATECONTROL_DEFAULT,
+-      MMAL_VIDEO_RATECONTROL_VARIABLE,
+-      MMAL_VIDEO_RATECONTROL_CONSTANT,
+-      MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
+-      MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
+-};
+-
+-enum mmal_video_profile {
+-      MMAL_VIDEO_PROFILE_H263_BASELINE,
+-      MMAL_VIDEO_PROFILE_H263_H320CODING,
+-      MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
+-      MMAL_VIDEO_PROFILE_H263_ISWV2,
+-      MMAL_VIDEO_PROFILE_H263_ISWV3,
+-      MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
+-      MMAL_VIDEO_PROFILE_H263_INTERNET,
+-      MMAL_VIDEO_PROFILE_H263_INTERLACE,
+-      MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
+-      MMAL_VIDEO_PROFILE_MP4V_CORE,
+-      MMAL_VIDEO_PROFILE_MP4V_MAIN,
+-      MMAL_VIDEO_PROFILE_MP4V_NBIT,
+-      MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
+-      MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
+-      MMAL_VIDEO_PROFILE_MP4V_HYBRID,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
+-      MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
+-      MMAL_VIDEO_PROFILE_H264_BASELINE,
+-      MMAL_VIDEO_PROFILE_H264_MAIN,
+-      MMAL_VIDEO_PROFILE_H264_EXTENDED,
+-      MMAL_VIDEO_PROFILE_H264_HIGH,
+-      MMAL_VIDEO_PROFILE_H264_HIGH10,
+-      MMAL_VIDEO_PROFILE_H264_HIGH422,
+-      MMAL_VIDEO_PROFILE_H264_HIGH444,
+-      MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
+-      MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
+-};
+-
+-enum mmal_video_level {
+-      MMAL_VIDEO_LEVEL_H263_10,
+-      MMAL_VIDEO_LEVEL_H263_20,
+-      MMAL_VIDEO_LEVEL_H263_30,
+-      MMAL_VIDEO_LEVEL_H263_40,
+-      MMAL_VIDEO_LEVEL_H263_45,
+-      MMAL_VIDEO_LEVEL_H263_50,
+-      MMAL_VIDEO_LEVEL_H263_60,
+-      MMAL_VIDEO_LEVEL_H263_70,
+-      MMAL_VIDEO_LEVEL_MP4V_0,
+-      MMAL_VIDEO_LEVEL_MP4V_0b,
+-      MMAL_VIDEO_LEVEL_MP4V_1,
+-      MMAL_VIDEO_LEVEL_MP4V_2,
+-      MMAL_VIDEO_LEVEL_MP4V_3,
+-      MMAL_VIDEO_LEVEL_MP4V_4,
+-      MMAL_VIDEO_LEVEL_MP4V_4a,
+-      MMAL_VIDEO_LEVEL_MP4V_5,
+-      MMAL_VIDEO_LEVEL_MP4V_6,
+-      MMAL_VIDEO_LEVEL_H264_1,
+-      MMAL_VIDEO_LEVEL_H264_1b,
+-      MMAL_VIDEO_LEVEL_H264_11,
+-      MMAL_VIDEO_LEVEL_H264_12,
+-      MMAL_VIDEO_LEVEL_H264_13,
+-      MMAL_VIDEO_LEVEL_H264_2,
+-      MMAL_VIDEO_LEVEL_H264_21,
+-      MMAL_VIDEO_LEVEL_H264_22,
+-      MMAL_VIDEO_LEVEL_H264_3,
+-      MMAL_VIDEO_LEVEL_H264_31,
+-      MMAL_VIDEO_LEVEL_H264_32,
+-      MMAL_VIDEO_LEVEL_H264_4,
+-      MMAL_VIDEO_LEVEL_H264_41,
+-      MMAL_VIDEO_LEVEL_H264_42,
+-      MMAL_VIDEO_LEVEL_H264_5,
+-      MMAL_VIDEO_LEVEL_H264_51,
+-      MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
+-};
+-
+-struct mmal_parameter_video_profile {
+-      enum mmal_video_profile profile;
+-      enum mmal_video_level level;
+-};
+-
+-/* video parameters */
+-
+-enum mmal_parameter_video_type {
+-      /** @ref MMAL_DISPLAYREGION_T */
+-      MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
+-      MMAL_PARAMETER_SUPPORTED_PROFILES,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
+-      MMAL_PARAMETER_PROFILE,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_INTRAPERIOD,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
+-      MMAL_PARAMETER_RATECONTROL,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
+-      MMAL_PARAMETER_NALUNITFORMAT,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T.
+-       * Setting the value to zero resets to the default (one slice per
+-       * frame).
+-       */
+-      MMAL_PARAMETER_MB_ROWS_PER_SLICE,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
+-      MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
+-      MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
+-      MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
+-      MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
+-      /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
+-      MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
+-      MMAL_PARAMETER_VIDEO_BIT_RATE,
+-
+-      /** @ref MMAL_PARAMETER_FRAME_RATE_T */
+-      MMAL_PARAMETER_VIDEO_FRAME_RATE,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
+-
+-      MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
+-      /** @ref MMAL_PARAMETER_UINT32_T.
+-       * Changing this parameter from the default can reduce frame rate
+-       * because image buffers need to be re-pitched.
+-       */
+-      MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T.
+-       * Changing this parameter from the default can reduce frame rate
+-       * because image buffers need to be re-pitched.
+-       */
+-      MMAL_PARAMETER_VIDEO_ALIGN_VERT,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
+-
+-      /**< @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
+-
+-      /**< @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
+-
+-      /* H264 specific parameters */
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
+-      MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
+-      MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
+-
+-      /** @ref MMAL_PARAMETER_BYTES_T */
+-      MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3,
+-
+-      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS,
+-
+-      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
+-
+-      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
+-};
+-
+-/** Valid mirror modes */
+-enum mmal_parameter_mirror {
+-      MMAL_PARAM_MIRROR_NONE,
+-      MMAL_PARAM_MIRROR_VERTICAL,
+-      MMAL_PARAM_MIRROR_HORIZONTAL,
+-      MMAL_PARAM_MIRROR_BOTH,
+-};
+-
+-enum mmal_parameter_displaytransform {
+-      MMAL_DISPLAY_ROT0 = 0,
+-      MMAL_DISPLAY_MIRROR_ROT0 = 1,
+-      MMAL_DISPLAY_MIRROR_ROT180 = 2,
+-      MMAL_DISPLAY_ROT180 = 3,
+-      MMAL_DISPLAY_MIRROR_ROT90 = 4,
+-      MMAL_DISPLAY_ROT270 = 5,
+-      MMAL_DISPLAY_ROT90 = 6,
+-      MMAL_DISPLAY_MIRROR_ROT270 = 7,
+-};
+-
+-enum mmal_parameter_displaymode {
+-      MMAL_DISPLAY_MODE_FILL = 0,
+-      MMAL_DISPLAY_MODE_LETTERBOX = 1,
+-};
+-
+-enum mmal_parameter_displayset {
+-      MMAL_DISPLAY_SET_NONE = 0,
+-      MMAL_DISPLAY_SET_NUM = 1,
+-      MMAL_DISPLAY_SET_FULLSCREEN = 2,
+-      MMAL_DISPLAY_SET_TRANSFORM = 4,
+-      MMAL_DISPLAY_SET_DEST_RECT = 8,
+-      MMAL_DISPLAY_SET_SRC_RECT = 0x10,
+-      MMAL_DISPLAY_SET_MODE = 0x20,
+-      MMAL_DISPLAY_SET_PIXEL = 0x40,
+-      MMAL_DISPLAY_SET_NOASPECT = 0x80,
+-      MMAL_DISPLAY_SET_LAYER = 0x100,
+-      MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
+-      MMAL_DISPLAY_SET_ALPHA = 0x400,
+-};
+-
+-/* rectangle, used lots so it gets its own struct */
+-struct vchiq_mmal_rect {
+-      s32 x;
+-      s32 y;
+-      s32 width;
+-      s32 height;
+-};
+-
+-struct mmal_parameter_displayregion {
+-      /** Bitfield that indicates which fields are set and should be
+-       * used. All other fields will maintain their current value.
+-       * \ref MMAL_DISPLAYSET_T defines the bits that can be
+-       * combined.
+-       */
+-      u32 set;
+-
+-      /** Describes the display output device, with 0 typically
+-       * being a directly connected LCD display.  The actual values
+-       * will depend on the hardware.  Code using hard-wired numbers
+-       * (e.g. 2) is certain to fail.
+-       */
+-
+-      u32 display_num;
+-      /** Indicates that we are using the full device screen area,
+-       * rather than a window of the display.  If zero, then
+-       * dest_rect is used to specify a region of the display to
+-       * use.
+-       */
+-
+-      s32 fullscreen;
+-      /** Indicates any rotation or flipping used to map frames onto
+-       * the natural display orientation.
+-       */
+-      u32 transform; /* enum mmal_parameter_displaytransform */
+-
+-      /** Where to display the frame within the screen, if
+-       * fullscreen is zero.
+-       */
+-      struct vchiq_mmal_rect dest_rect;
+-
+-      /** Indicates which area of the frame to display. If all
+-       * values are zero, the whole frame will be used.
+-       */
+-      struct vchiq_mmal_rect src_rect;
+-
+-      /** If set to non-zero, indicates that any display scaling
+-       * should disregard the aspect ratio of the frame region being
+-       * displayed.
+-       */
+-      s32 noaspect;
+-
+-      /** Indicates how the image should be scaled to fit the
+-       * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
+-       * that the image should fill the screen by potentially
+-       * cropping the frames.  Setting \code mode \endcode to \code
+-       * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
+-       * source region should be displayed and black bars added if
+-       * necessary.
+-       */
+-      u32 mode; /* enum mmal_parameter_displaymode */
+-
+-      /** If non-zero, defines the width of a source pixel relative
+-       * to \code pixel_y \endcode.  If zero, then pixels default to
+-       * being square.
+-       */
+-      u32 pixel_x;
+-
+-      /** If non-zero, defines the height of a source pixel relative
+-       * to \code pixel_x \endcode.  If zero, then pixels default to
+-       * being square.
+-       */
+-      u32 pixel_y;
+-
+-      /** Sets the relative depth of the images, with greater values
+-       * being in front of smaller values.
+-       */
+-      u32 layer;
+-
+-      /** Set to non-zero to ensure copy protection is used on
+-       * output.
+-       */
+-      s32 copyprotect_required;
+-
+-      /** Level of opacity of the layer, where zero is fully
+-       * transparent and 255 is fully opaque.
+-       */
+-      u32 alpha;
+-};
+-
+-#define MMAL_MAX_IMAGEFX_PARAMETERS 5
+-
+-struct mmal_parameter_imagefx_parameters {
+-      enum mmal_parameter_imagefx effect;
+-      u32 num_effect_params;
+-      u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
+-};
+-
+-#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4
+-#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2
+-#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16
+-
+-struct mmal_parameter_camera_info_camera_t {
+-      u32    port_id;
+-      u32    max_width;
+-      u32    max_height;
+-      u32    lens_present;
+-      u8     camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN];
+-};
+-
+-enum mmal_parameter_camera_info_flash_type_t {
+-      /* Make values explicit to ensure they match values in config ini */
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0,
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED   = 1,
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2,
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF
+-};
+-
+-struct mmal_parameter_camera_info_flash_t {
+-      enum mmal_parameter_camera_info_flash_type_t flash_type;
+-};
+-
+-struct mmal_parameter_camera_info_t {
+-      u32                            num_cameras;
+-      u32                            num_flashes;
+-      struct mmal_parameter_camera_info_camera_t
+-                              cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
+-      struct mmal_parameter_camera_info_flash_t
+-                              flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
+-};
+-
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- *
+- * MMAL interface to VCHIQ message passing
+- */
+-
+-#ifndef MMAL_VCHIQ_H
+-#define MMAL_VCHIQ_H
+-
+-#include "mmal-msg-format.h"
+-
+-#define MAX_PORT_COUNT 4
+-
+-/* Maximum size of the format extradata. */
+-#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
+-
+-struct vchiq_mmal_instance;
+-
+-enum vchiq_mmal_es_type {
+-      MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
+-      MMAL_ES_TYPE_CONTROL,     /**< Elementary stream of control commands */
+-      MMAL_ES_TYPE_AUDIO,       /**< Audio elementary stream */
+-      MMAL_ES_TYPE_VIDEO,       /**< Video elementary stream */
+-      MMAL_ES_TYPE_SUBPICTURE   /**< Sub-picture elementary stream */
+-};
+-
+-struct vchiq_mmal_port_buffer {
+-      unsigned int num; /* number of buffers */
+-      u32 size; /* size of buffers */
+-      u32 alignment; /* alignment of buffers */
+-};
+-
+-struct vchiq_mmal_port;
+-
+-typedef void (*vchiq_mmal_buffer_cb)(
+-              struct vchiq_mmal_instance  *instance,
+-              struct vchiq_mmal_port *port,
+-              int status, struct mmal_buffer *buffer,
+-              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
+-
+-struct vchiq_mmal_port {
+-      bool enabled;
+-      u32 handle;
+-      u32 type; /* port type, cached to use on port info set */
+-      u32 index; /* port index, cached to use on port info set */
+-
+-      /* component port belongs to, allows simple deref */
+-      struct vchiq_mmal_component *component;
+-
+-      struct vchiq_mmal_port *connected; /* port conencted to */
+-
+-      /* buffer info */
+-      struct vchiq_mmal_port_buffer minimum_buffer;
+-      struct vchiq_mmal_port_buffer recommended_buffer;
+-      struct vchiq_mmal_port_buffer current_buffer;
+-
+-      /* stream format */
+-      struct mmal_es_format_local format;
+-      /* elementary stream format */
+-      union mmal_es_specific_format es;
+-
+-      /* data buffers to fill */
+-      struct list_head buffers;
+-      /* lock to serialise adding and removing buffers from list */
+-      spinlock_t slock;
+-
+-      /* Count of buffers the VPU has yet to return */
+-      atomic_t buffers_with_vpu;
+-      /* callback on buffer completion */
+-      vchiq_mmal_buffer_cb buffer_cb;
+-      /* callback context */
+-      void *cb_ctx;
+-};
+-
+-struct vchiq_mmal_component {
+-      bool enabled;
+-      u32 handle;  /* VideoCore handle for component */
+-      u32 inputs;  /* Number of input ports */
+-      u32 outputs; /* Number of output ports */
+-      u32 clocks;  /* Number of clock ports */
+-      struct vchiq_mmal_port control; /* control port */
+-      struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
+-      struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
+-      struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
+-};
+-
+-int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
+-int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
+-
+-/* Initialise a mmal component and its ports
+- *
+- */
+-int vchiq_mmal_component_init(
+-              struct vchiq_mmal_instance *instance,
+-              const char *name,
+-              struct vchiq_mmal_component **component_out);
+-
+-int vchiq_mmal_component_finalise(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_component *component);
+-
+-int vchiq_mmal_component_enable(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_component *component);
+-
+-int vchiq_mmal_component_disable(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_component *component);
+-
+-/* enable a mmal port
+- *
+- * enables a port and if a buffer callback provided enque buffer
+- * headers as appropriate for the port.
+- */
+-int vchiq_mmal_port_enable(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_port *port,
+-              vchiq_mmal_buffer_cb buffer_cb);
+-
+-/* disable a port
+- *
+- * disable a port will dequeue any pending buffers
+- */
+-int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_port *port);
+-
+-int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter,
+-                                void *value,
+-                                u32 value_size);
+-
+-int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter,
+-                                void *value,
+-                                u32 *value_size);
+-
+-int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
+-                             struct vchiq_mmal_port *port);
+-
+-int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
+-                                 struct vchiq_mmal_port *src,
+-                                 struct vchiq_mmal_port *dst);
+-
+-int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
+-                     u32 *major_out,
+-                     u32 *minor_out);
+-
+-int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_port *port,
+-                           struct mmal_buffer *buf);
+-
+-int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+-                        struct mmal_buffer *buf);
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
+-#endif /* MMAL_VCHIQ_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -0,0 +1,61 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ *
++ * MMAL structures
++ *
++ */
++#ifndef MMAL_COMMON_H
++#define MMAL_COMMON_H
++
++#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
++#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
++
++/** Special value signalling that time is not known */
++#define MMAL_TIME_UNKNOWN BIT_ULL(63)
++
++struct mmal_msg_context;
++
++/* mapping between v4l and mmal video modes */
++struct mmal_fmt {
++      char  *name;
++      u32   fourcc;          /* v4l2 format id */
++      int   flags;           /* v4l2 flags field */
++      u32   mmal;
++      int   depth;
++      u32   mmal_component;  /* MMAL component index to be used to encode */
++      u32   ybbp;            /* depth of first Y plane for planar formats */
++      bool  remove_padding;  /* Does the GPU have to remove padding,
++                              * or can we do hide padding via bytesperline.
++                              */
++};
++
++/* buffer for one video frame */
++struct mmal_buffer {
++      /* v4l buffer data -- must be first */
++      struct vb2_v4l2_buffer  vb;
++
++      /* list of buffers available */
++      struct list_head        list;
++
++      void *buffer; /* buffer pointer */
++      unsigned long buffer_size; /* size of allocated buffer */
++
++      struct mmal_msg_context *msg_context;
++};
++
++/* */
++struct mmal_colourfx {
++      s32 enable;
++      u32 u;
++      u32 v;
++};
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
+@@ -0,0 +1,124 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++#ifndef MMAL_ENCODINGS_H
++#define MMAL_ENCODINGS_H
++
++#define MMAL_ENCODING_H264             MMAL_FOURCC('H', '2', '6', '4')
++#define MMAL_ENCODING_H263             MMAL_FOURCC('H', '2', '6', '3')
++#define MMAL_ENCODING_MP4V             MMAL_FOURCC('M', 'P', '4', 'V')
++#define MMAL_ENCODING_MP2V             MMAL_FOURCC('M', 'P', '2', 'V')
++#define MMAL_ENCODING_MP1V             MMAL_FOURCC('M', 'P', '1', 'V')
++#define MMAL_ENCODING_WMV3             MMAL_FOURCC('W', 'M', 'V', '3')
++#define MMAL_ENCODING_WMV2             MMAL_FOURCC('W', 'M', 'V', '2')
++#define MMAL_ENCODING_WMV1             MMAL_FOURCC('W', 'M', 'V', '1')
++#define MMAL_ENCODING_WVC1             MMAL_FOURCC('W', 'V', 'C', '1')
++#define MMAL_ENCODING_VP8              MMAL_FOURCC('V', 'P', '8', ' ')
++#define MMAL_ENCODING_VP7              MMAL_FOURCC('V', 'P', '7', ' ')
++#define MMAL_ENCODING_VP6              MMAL_FOURCC('V', 'P', '6', ' ')
++#define MMAL_ENCODING_THEORA           MMAL_FOURCC('T', 'H', 'E', 'O')
++#define MMAL_ENCODING_SPARK            MMAL_FOURCC('S', 'P', 'R', 'K')
++#define MMAL_ENCODING_MJPEG            MMAL_FOURCC('M', 'J', 'P', 'G')
++
++#define MMAL_ENCODING_JPEG             MMAL_FOURCC('J', 'P', 'E', 'G')
++#define MMAL_ENCODING_GIF              MMAL_FOURCC('G', 'I', 'F', ' ')
++#define MMAL_ENCODING_PNG              MMAL_FOURCC('P', 'N', 'G', ' ')
++#define MMAL_ENCODING_PPM              MMAL_FOURCC('P', 'P', 'M', ' ')
++#define MMAL_ENCODING_TGA              MMAL_FOURCC('T', 'G', 'A', ' ')
++#define MMAL_ENCODING_BMP              MMAL_FOURCC('B', 'M', 'P', ' ')
++
++#define MMAL_ENCODING_I420             MMAL_FOURCC('I', '4', '2', '0')
++#define MMAL_ENCODING_I420_SLICE       MMAL_FOURCC('S', '4', '2', '0')
++#define MMAL_ENCODING_YV12             MMAL_FOURCC('Y', 'V', '1', '2')
++#define MMAL_ENCODING_I422             MMAL_FOURCC('I', '4', '2', '2')
++#define MMAL_ENCODING_I422_SLICE       MMAL_FOURCC('S', '4', '2', '2')
++#define MMAL_ENCODING_YUYV             MMAL_FOURCC('Y', 'U', 'Y', 'V')
++#define MMAL_ENCODING_YVYU             MMAL_FOURCC('Y', 'V', 'Y', 'U')
++#define MMAL_ENCODING_UYVY             MMAL_FOURCC('U', 'Y', 'V', 'Y')
++#define MMAL_ENCODING_VYUY             MMAL_FOURCC('V', 'Y', 'U', 'Y')
++#define MMAL_ENCODING_NV12             MMAL_FOURCC('N', 'V', '1', '2')
++#define MMAL_ENCODING_NV21             MMAL_FOURCC('N', 'V', '2', '1')
++#define MMAL_ENCODING_ARGB             MMAL_FOURCC('A', 'R', 'G', 'B')
++#define MMAL_ENCODING_RGBA             MMAL_FOURCC('R', 'G', 'B', 'A')
++#define MMAL_ENCODING_ABGR             MMAL_FOURCC('A', 'B', 'G', 'R')
++#define MMAL_ENCODING_BGRA             MMAL_FOURCC('B', 'G', 'R', 'A')
++#define MMAL_ENCODING_RGB16            MMAL_FOURCC('R', 'G', 'B', '2')
++#define MMAL_ENCODING_RGB24            MMAL_FOURCC('R', 'G', 'B', '3')
++#define MMAL_ENCODING_RGB32            MMAL_FOURCC('R', 'G', 'B', '4')
++#define MMAL_ENCODING_BGR16            MMAL_FOURCC('B', 'G', 'R', '2')
++#define MMAL_ENCODING_BGR24            MMAL_FOURCC('B', 'G', 'R', '3')
++#define MMAL_ENCODING_BGR32            MMAL_FOURCC('B', 'G', 'R', '4')
++
++/** SAND Video (YUVUV128) format, native format understood by VideoCore.
++ * This format is *not* opaque - if requested you will receive full frames
++ * of YUV_UV video.
++ */
++#define MMAL_ENCODING_YUVUV128         MMAL_FOURCC('S', 'A', 'N', 'D')
++
++/** VideoCore opaque image format, image handles are returned to
++ * the host but not the actual image data.
++ */
++#define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
++
++/** An EGL image handle
++ */
++#define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
++
++/* }@ */
++
++/** \name Pre-defined audio encodings */
++/* @{ */
++#define MMAL_ENCODING_PCM_UNSIGNED_BE  MMAL_FOURCC('P', 'C', 'M', 'U')
++#define MMAL_ENCODING_PCM_UNSIGNED_LE  MMAL_FOURCC('p', 'c', 'm', 'u')
++#define MMAL_ENCODING_PCM_SIGNED_BE    MMAL_FOURCC('P', 'C', 'M', 'S')
++#define MMAL_ENCODING_PCM_SIGNED_LE    MMAL_FOURCC('p', 'c', 'm', 's')
++#define MMAL_ENCODING_PCM_FLOAT_BE     MMAL_FOURCC('P', 'C', 'M', 'F')
++#define MMAL_ENCODING_PCM_FLOAT_LE     MMAL_FOURCC('p', 'c', 'm', 'f')
++
++/* Pre-defined H264 encoding variants */
++
++/** ISO 14496-10 Annex B byte stream format */
++#define MMAL_ENCODING_VARIANT_H264_DEFAULT   0
++/** ISO 14496-15 AVC stream format */
++#define MMAL_ENCODING_VARIANT_H264_AVC1      MMAL_FOURCC('A', 'V', 'C', '1')
++/** Implicitly delineated NAL units without emulation prevention */
++#define MMAL_ENCODING_VARIANT_H264_RAW       MMAL_FOURCC('R', 'A', 'W', ' ')
++
++/** \defgroup MmalColorSpace List of pre-defined video color spaces
++ * This defines a list of common color spaces. This list isn't exhaustive and
++ * is only provided as a convenience to avoid clients having to use FourCC
++ * codes directly. However components are allowed to define and use their own
++ * FourCC codes.
++ */
++/* @{ */
++
++/** Unknown color space */
++#define MMAL_COLOR_SPACE_UNKNOWN       0
++/** ITU-R BT.601-5 [SDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT601    MMAL_FOURCC('Y', '6', '0', '1')
++/** ITU-R BT.709-3 [HDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT709    MMAL_FOURCC('Y', '7', '0', '9')
++/** JPEG JFIF */
++#define MMAL_COLOR_SPACE_JPEG_JFIF     MMAL_FOURCC('Y', 'J', 'F', 'I')
++/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
++#define MMAL_COLOR_SPACE_FCC           MMAL_FOURCC('Y', 'F', 'C', 'C')
++/** Society of Motion Picture and Television Engineers 240M (1999) */
++#define MMAL_COLOR_SPACE_SMPTE240M     MMAL_FOURCC('Y', '2', '4', '0')
++/** ITU-R BT.470-2 System M */
++#define MMAL_COLOR_SPACE_BT470_2_M     MMAL_FOURCC('Y', '_', '_', 'M')
++/** ITU-R BT.470-2 System BG */
++#define MMAL_COLOR_SPACE_BT470_2_BG    MMAL_FOURCC('Y', '_', 'B', 'G')
++/** JPEG JFIF, but with 16..255 luma */
++#define MMAL_COLOR_SPACE_JFIF_Y16_255  MMAL_FOURCC('Y', 'Y', '1', '6')
++/* @} MmalColorSpace List */
++
++#endif /* MMAL_ENCODINGS_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h
+@@ -0,0 +1,48 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++#ifndef MMAL_MSG_COMMON_H
++#define MMAL_MSG_COMMON_H
++
++enum mmal_msg_status {
++      MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
++      MMAL_MSG_STATUS_ENOMEM,      /**< Out of memory */
++      MMAL_MSG_STATUS_ENOSPC,      /**< Out of resources other than memory */
++      MMAL_MSG_STATUS_EINVAL,      /**< Argument is invalid */
++      MMAL_MSG_STATUS_ENOSYS,      /**< Function not implemented */
++      MMAL_MSG_STATUS_ENOENT,      /**< No such file or directory */
++      MMAL_MSG_STATUS_ENXIO,       /**< No such device or address */
++      MMAL_MSG_STATUS_EIO,         /**< I/O error */
++      MMAL_MSG_STATUS_ESPIPE,      /**< Illegal seek */
++      MMAL_MSG_STATUS_ECORRUPT,    /**< Data is corrupt \attention */
++      MMAL_MSG_STATUS_ENOTREADY,   /**< Component is not ready */
++      MMAL_MSG_STATUS_ECONFIG,     /**< Component is not configured */
++      MMAL_MSG_STATUS_EISCONN,     /**< Port is already connected */
++      MMAL_MSG_STATUS_ENOTCONN,    /**< Port is disconnected */
++      MMAL_MSG_STATUS_EAGAIN,      /**< Resource temporarily unavailable. */
++      MMAL_MSG_STATUS_EFAULT,      /**< Bad address */
++};
++
++struct mmal_rect {
++      s32 x;      /**< x coordinate (from left) */
++      s32 y;      /**< y coordinate (from top) */
++      s32 width;  /**< width */
++      s32 height; /**< height */
++};
++
++struct mmal_rational {
++      s32 num;    /**< Numerator */
++      s32 den;    /**< Denominator */
++};
++
++#endif /* MMAL_MSG_COMMON_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h
+@@ -0,0 +1,106 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++#ifndef MMAL_MSG_FORMAT_H
++#define MMAL_MSG_FORMAT_H
++
++#include "mmal-msg-common.h"
++
++/* MMAL_ES_FORMAT_T */
++
++struct mmal_audio_format {
++      u32 channels;           /* Number of audio channels */
++      u32 sample_rate;        /* Sample rate */
++
++      u32 bits_per_sample;    /* Bits per sample */
++      u32 block_align;        /* Size of a block of data */
++};
++
++struct mmal_video_format {
++      u32 width;              /* Width of frame in pixels */
++      u32 height;             /* Height of frame in rows of pixels */
++      struct mmal_rect crop;  /* Visible region of the frame */
++      struct mmal_rational frame_rate;        /* Frame rate */
++      struct mmal_rational par;               /* Pixel aspect ratio */
++
++      /*
++       * FourCC specifying the color space of the video stream. See the
++       * MmalColorSpace "pre-defined color spaces" for some examples.
++       */
++      u32 color_space;
++};
++
++struct mmal_subpicture_format {
++      u32 x_offset;
++      u32 y_offset;
++};
++
++union mmal_es_specific_format {
++      struct mmal_audio_format audio;
++      struct mmal_video_format video;
++      struct mmal_subpicture_format subpicture;
++};
++
++/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
++struct mmal_es_format_local {
++      u32 type;       /* enum mmal_es_type */
++
++      u32 encoding;   /* FourCC specifying encoding of the elementary
++                       * stream.
++                       */
++      u32 encoding_variant;   /* FourCC specifying the specific
++                               * encoding variant of the elementary
++                               * stream.
++                               */
++
++      union mmal_es_specific_format *es;      /* Type specific
++                                               * information for the
++                                               * elementary stream
++                                               */
++
++      u32 bitrate;    /* Bitrate in bits per second */
++      u32 flags;      /* Flags describing properties of the elementary
++                       * stream.
++                       */
++
++      u32 extradata_size;     /* Size of the codec specific data */
++      u8  *extradata;         /* Codec specific data */
++};
++
++/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
++struct mmal_es_format {
++      u32 type;       /* enum mmal_es_type */
++
++      u32 encoding;   /* FourCC specifying encoding of the elementary
++                       * stream.
++                       */
++      u32 encoding_variant;   /* FourCC specifying the specific
++                               * encoding variant of the elementary
++                               * stream.
++                               */
++
++      u32 es; /* Type specific
++               * information for the
++               * elementary stream
++               */
++
++      u32 bitrate;    /* Bitrate in bits per second */
++      u32 flags;      /* Flags describing properties of the elementary
++                       * stream.
++                       */
++
++      u32 extradata_size;     /* Size of the codec specific data */
++      u32 extradata;          /* Codec specific data */
++};
++
++#endif /* MMAL_MSG_FORMAT_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h
+@@ -0,0 +1,109 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++/* MMAL_PORT_TYPE_T */
++enum mmal_port_type {
++      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
++      MMAL_PORT_TYPE_CONTROL,         /* Control port */
++      MMAL_PORT_TYPE_INPUT,           /* Input port */
++      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
++      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
++};
++
++/* The port is pass-through and doesn't need buffer headers allocated */
++#define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
++/*
++ *The port wants to allocate the buffer payloads.
++ * This signals a preference that payload allocation should be done
++ * on this port for efficiency reasons.
++ */
++#define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
++/*
++ * The port supports format change events.
++ * This applies to input ports and is used to let the client know
++ * whether the port supports being reconfigured via a format
++ * change event (i.e. without having to disable the port).
++ */
++#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
++
++/*
++ * mmal port structure (MMAL_PORT_T)
++ *
++ * most elements are informational only, the pointer values for
++ * interogation messages are generally provided as additional
++ * structures within the message. When used to set values only the
++ * buffer_num, buffer_size and userdata parameters are writable.
++ */
++struct mmal_port {
++      u32 priv;       /* Private member used by the framework */
++      u32 name;       /* Port name. Used for debugging purposes (RO) */
++
++      u32 type;       /* Type of the port (RO) enum mmal_port_type */
++      u16 index;      /* Index of the port in its type list (RO) */
++      u16 index_all;  /* Index of the port in the list of all ports (RO) */
++
++      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
++      u32 format;     /* Format of the elementary stream */
++
++      u32 buffer_num_min;     /* Minimum number of buffers the port
++                               *   requires (RO).  This is set by the
++                               *   component.
++                               */
++
++      u32 buffer_size_min;    /* Minimum size of buffers the port
++                               * requires (RO).  This is set by the
++                               * component.
++                               */
++
++      u32 buffer_alignment_min;/* Minimum alignment requirement for
++                                * the buffers (RO).  A value of
++                                * zero means no special alignment
++                                * requirements.  This is set by the
++                                * component.
++                                */
++
++      u32 buffer_num_recommended;     /* Number of buffers the port
++                                       * recommends for optimal
++                                       * performance (RO).  A value of
++                                       * zero means no special
++                                       * recommendation.  This is set
++                                       * by the component.
++                                       */
++
++      u32 buffer_size_recommended;    /* Size of buffers the port
++                                       * recommends for optimal
++                                       * performance (RO).  A value of
++                                       * zero means no special
++                                       * recommendation.  This is set
++                                       * by the component.
++                                       */
++
++      u32 buffer_num; /* Actual number of buffers the port will use.
++                       * This is set by the client.
++                       */
++
++      u32 buffer_size; /* Actual maximum size of the buffers that
++                        * will be sent to the port. This is set by
++                        * the client.
++                        */
++
++      u32 component;  /* Component this port belongs to (Read Only) */
++
++      u32 userdata;   /* Field reserved for use by the client */
++
++      u32 capabilities;       /* Flags describing the capabilities of a
++                               * port (RO).  Bitwise combination of \ref
++                               * portcapabilities "Port capabilities"
++                               * values.
++                               */
++};
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
+@@ -0,0 +1,406 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++/*
++ * all the data structures which serialise the MMAL protocol. note
++ * these are directly mapped onto the recived message data.
++ *
++ * BEWARE: They seem to *assume* pointers are u32 and that there is no
++ * structure padding!
++ *
++ * NOTE: this implementation uses kernel types to ensure sizes. Rather
++ * than assigning values to enums to force their size the
++ * implementation uses fixed size types and not the enums (though the
++ * comments have the actual enum type
++ */
++#ifndef MMAL_MSG_H
++#define MMAL_MSG_H
++
++#define VC_MMAL_VER 15
++#define VC_MMAL_MIN_VER 10
++#define VC_MMAL_SERVER_NAME  MAKE_FOURCC("mmal")
++
++/* max total message size is 512 bytes */
++#define MMAL_MSG_MAX_SIZE 512
++/* with six 32bit header elements max payload is therefore 488 bytes */
++#define MMAL_MSG_MAX_PAYLOAD 488
++
++#include "mmal-msg-common.h"
++#include "mmal-msg-format.h"
++#include "mmal-msg-port.h"
++
++enum mmal_msg_type {
++      MMAL_MSG_TYPE_QUIT = 1,
++      MMAL_MSG_TYPE_SERVICE_CLOSED,
++      MMAL_MSG_TYPE_GET_VERSION,
++      MMAL_MSG_TYPE_COMPONENT_CREATE,
++      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
++      MMAL_MSG_TYPE_COMPONENT_ENABLE,
++      MMAL_MSG_TYPE_COMPONENT_DISABLE,
++      MMAL_MSG_TYPE_PORT_INFO_GET,
++      MMAL_MSG_TYPE_PORT_INFO_SET,
++      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
++      MMAL_MSG_TYPE_BUFFER_FROM_HOST,
++      MMAL_MSG_TYPE_BUFFER_TO_HOST,
++      MMAL_MSG_TYPE_GET_STATS,
++      MMAL_MSG_TYPE_PORT_PARAMETER_SET,
++      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
++      MMAL_MSG_TYPE_EVENT_TO_HOST,
++      MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
++      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
++      MMAL_MSG_TYPE_CONSUME_MEM,
++      MMAL_MSG_TYPE_LMK,                      /* 20 */
++      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
++      MMAL_MSG_TYPE_DRM_GET_LHS32,
++      MMAL_MSG_TYPE_DRM_GET_TIME,
++      MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
++      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
++      MMAL_MSG_TYPE_HOST_LOG,
++      MMAL_MSG_TYPE_MSG_LAST
++};
++
++/* port action request messages differ depending on the action type */
++enum mmal_msg_port_action_type {
++      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
++      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
++      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
++      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
++      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
++      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
++      MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
++};
++
++struct mmal_msg_header {
++      u32 magic;
++      u32 type;       /* enum mmal_msg_type */
++
++      /* Opaque handle to the control service */
++      u32 control_service;
++
++      u32 context;    /* a u32 per message context */
++      u32 status;     /* The status of the vchiq operation */
++      u32 padding;
++};
++
++/* Send from VC to host to report version */
++struct mmal_msg_version {
++      u32 flags;
++      u32 major;
++      u32 minor;
++      u32 minimum;
++};
++
++/* request to VC to create component */
++struct mmal_msg_component_create {
++      u32 client_component;   /* component context */
++      char name[128];
++      u32 pid;                /* For debug */
++};
++
++/* reply from VC to component creation request */
++struct mmal_msg_component_create_reply {
++      u32 status;     /* enum mmal_msg_status - how does this differ to
++                       * the one in the header?
++                       */
++      u32 component_handle; /* VideoCore handle for component */
++      u32 input_num;        /* Number of input ports */
++      u32 output_num;       /* Number of output ports */
++      u32 clock_num;        /* Number of clock ports */
++};
++
++/* request to VC to destroy a component */
++struct mmal_msg_component_destroy {
++      u32 component_handle;
++};
++
++struct mmal_msg_component_destroy_reply {
++      u32 status; /* The component destruction status */
++};
++
++/* request and reply to VC to enable a component */
++struct mmal_msg_component_enable {
++      u32 component_handle;
++};
++
++struct mmal_msg_component_enable_reply {
++      u32 status; /* The component enable status */
++};
++
++/* request and reply to VC to disable a component */
++struct mmal_msg_component_disable {
++      u32 component_handle;
++};
++
++struct mmal_msg_component_disable_reply {
++      u32 status; /* The component disable status */
++};
++
++/* request to VC to get port information */
++struct mmal_msg_port_info_get {
++      u32 component_handle;  /* component handle port is associated with */
++      u32 port_type;         /* enum mmal_msg_port_type */
++      u32 index;             /* port index to query */
++};
++
++/* reply from VC to get port info request */
++struct mmal_msg_port_info_get_reply {
++      u32 status;             /* enum mmal_msg_status */
++      u32 component_handle;   /* component handle port is associated with */
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 port_index;         /* port indexed in query */
++      s32 found;              /* unused */
++      u32 port_handle;        /* Handle to use for this port */
++      struct mmal_port port;
++      struct mmal_es_format format; /* elementary stream format */
++      union mmal_es_specific_format es; /* es type specific data */
++      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
++};
++
++/* request to VC to set port information */
++struct mmal_msg_port_info_set {
++      u32 component_handle;
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 port_index;         /* port indexed in query */
++      struct mmal_port port;
++      struct mmal_es_format format;
++      union mmal_es_specific_format es;
++      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
++};
++
++/* reply from VC to port info set request */
++struct mmal_msg_port_info_set_reply {
++      u32 status;
++      u32 component_handle;   /* component handle port is associated with */
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 index;              /* port indexed in query */
++      s32 found;              /* unused */
++      u32 port_handle;        /* Handle to use for this port */
++      struct mmal_port port;
++      struct mmal_es_format format;
++      union mmal_es_specific_format es;
++      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
++};
++
++/* port action requests that take a mmal_port as a parameter */
++struct mmal_msg_port_action_port {
++      u32 component_handle;
++      u32 port_handle;
++      u32 action;             /* enum mmal_msg_port_action_type */
++      struct mmal_port port;
++};
++
++/* port action requests that take handles as a parameter */
++struct mmal_msg_port_action_handle {
++      u32 component_handle;
++      u32 port_handle;
++      u32 action;             /* enum mmal_msg_port_action_type */
++      u32 connect_component_handle;
++      u32 connect_port_handle;
++};
++
++struct mmal_msg_port_action_reply {
++      u32 status;     /* The port action operation status */
++};
++
++/* MMAL buffer transfer */
++
++/* Size of space reserved in a buffer message for short messages. */
++#define MMAL_VC_SHORT_DATA 128
++
++/* Signals that the current payload is the end of the stream of data */
++#define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
++/* Signals that the start of the current payload starts a frame */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
++/* Signals that the end of the current payload ends a frame */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
++/* Signals that the current payload contains only complete frames (>1) */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
++      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
++       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
++/* Signals that the current payload is a keyframe (i.e. self decodable) */
++#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
++/*
++ * Signals a discontinuity in the stream of data (e.g. after a seek).
++ * Can be used for instance by a decoder to reset its state
++ */
++#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
++/*
++ * Signals a buffer containing some kind of config data for the component
++ * (e.g. codec config data)
++ */
++#define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
++/* Signals an encrypted payload */
++#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
++/* Signals a buffer containing side information */
++#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
++/*
++ * Signals a buffer which is the snapshot/postview image from a stills
++ * capture
++ */
++#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
++/* Signals a buffer which contains data known to be corrupted */
++#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
++/* Signals that a buffer failed to be transmitted */
++#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
++
++struct mmal_driver_buffer {
++      u32 magic;
++      u32 component_handle;
++      u32 port_handle;
++      u32 client_context;
++};
++
++/* buffer header */
++struct mmal_buffer_header {
++      u32 next;       /* next header */
++      u32 priv;       /* framework private data */
++      u32 cmd;
++      u32 data;
++      u32 alloc_size;
++      u32 length;
++      u32 offset;
++      u32 flags;
++      s64 pts;
++      s64 dts;
++      u32 type;
++      u32 user_data;
++};
++
++struct mmal_buffer_header_type_specific {
++      union {
++              struct {
++              u32 planes;
++              u32 offset[4];
++              u32 pitch[4];
++              u32 flags;
++              } video;
++      } u;
++};
++
++struct mmal_msg_buffer_from_host {
++      /*
++       *The front 32 bytes of the buffer header are copied
++       * back to us in the reply to allow for context. This
++       * area is used to store two mmal_driver_buffer structures to
++       * allow for multiple concurrent service users.
++       */
++      /* control data */
++      struct mmal_driver_buffer drvbuf;
++
++      /* referenced control data for passthrough buffer management */
++      struct mmal_driver_buffer drvbuf_ref;
++      struct mmal_buffer_header buffer_header; /* buffer header itself */
++      struct mmal_buffer_header_type_specific buffer_header_type_specific;
++      s32 is_zero_copy;
++      s32 has_reference;
++
++      /* allows short data to be xfered in control message */
++      u32 payload_in_message;
++      u8 short_data[MMAL_VC_SHORT_DATA];
++};
++
++/* port parameter setting */
++
++#define MMAL_WORKER_PORT_PARAMETER_SPACE      96
++
++struct mmal_msg_port_parameter_set {
++      u32 component_handle;   /* component */
++      u32 port_handle;        /* port */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
++      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
++};
++
++struct mmal_msg_port_parameter_set_reply {
++      u32 status;     /* enum mmal_msg_status todo: how does this
++                       * differ to the one in the header?
++                       */
++};
++
++/* port parameter getting */
++
++struct mmal_msg_port_parameter_get {
++      u32 component_handle;   /* component */
++      u32 port_handle;        /* port */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
++};
++
++struct mmal_msg_port_parameter_get_reply {
++      u32 status;             /* Status of mmal_port_parameter_get call */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
++      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
++};
++
++/* event messages */
++#define MMAL_WORKER_EVENT_SPACE 256
++
++struct mmal_msg_event_to_host {
++      u32 client_component;   /* component context */
++
++      u32 port_type;
++      u32 port_num;
++
++      u32 cmd;
++      u32 length;
++      u8 data[MMAL_WORKER_EVENT_SPACE];
++      u32 delayed_buffer;
++};
++
++/* all mmal messages are serialised through this structure */
++struct mmal_msg {
++      /* header */
++      struct mmal_msg_header h;
++      /* payload */
++      union {
++              struct mmal_msg_version version;
++
++              struct mmal_msg_component_create component_create;
++              struct mmal_msg_component_create_reply component_create_reply;
++
++              struct mmal_msg_component_destroy component_destroy;
++              struct mmal_msg_component_destroy_reply component_destroy_reply;
++
++              struct mmal_msg_component_enable component_enable;
++              struct mmal_msg_component_enable_reply component_enable_reply;
++
++              struct mmal_msg_component_disable component_disable;
++              struct mmal_msg_component_disable_reply component_disable_reply;
++
++              struct mmal_msg_port_info_get port_info_get;
++              struct mmal_msg_port_info_get_reply port_info_get_reply;
++
++              struct mmal_msg_port_info_set port_info_set;
++              struct mmal_msg_port_info_set_reply port_info_set_reply;
++
++              struct mmal_msg_port_action_port port_action_port;
++              struct mmal_msg_port_action_handle port_action_handle;
++              struct mmal_msg_port_action_reply port_action_reply;
++
++              struct mmal_msg_buffer_from_host buffer_from_host;
++
++              struct mmal_msg_port_parameter_set port_parameter_set;
++              struct mmal_msg_port_parameter_set_reply
++                      port_parameter_set_reply;
++              struct mmal_msg_port_parameter_get
++                      port_parameter_get;
++              struct mmal_msg_port_parameter_get_reply
++                      port_parameter_get_reply;
++
++              struct mmal_msg_event_to_host event_to_host;
++
++              u8 payload[MMAL_MSG_MAX_PAYLOAD];
++      } u;
++};
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
+@@ -0,0 +1,755 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++/* common parameters */
++
++/** @name Parameter groups
++ * Parameters are divided into groups, and then allocated sequentially within
++ * a group using an enum.
++ * @{
++ */
++
++#ifndef MMAL_PARAMETERS_H
++#define MMAL_PARAMETERS_H
++
++/** Common parameter ID group, used with many types of component. */
++#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
++/** Camera-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
++/** Video-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
++/** Audio-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
++/** Clock-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
++/** Miracast-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
++
++/* Common parameters */
++enum mmal_parameter_common_type {
++      /**< Never a valid parameter ID */
++      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
++
++              /**< MMAL_PARAMETER_ENCODING_T */
++      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++              /**< MMAL_PARAMETER_URI_T */
++      MMAL_PARAMETER_URI,
++              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
++      MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
++              /** MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ZERO_COPY,
++              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
++      MMAL_PARAMETER_BUFFER_REQUIREMENTS,
++              /**< MMAL_PARAMETER_STATISTICS_T */
++      MMAL_PARAMETER_STATISTICS,
++              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
++      MMAL_PARAMETER_CORE_STATISTICS,
++              /**< MMAL_PARAMETER_MEM_USAGE_T */
++      MMAL_PARAMETER_MEM_USAGE,
++              /**< MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
++              /**< MMAL_PARAMETER_SEEK_T */
++      MMAL_PARAMETER_SEEK,
++              /**< MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_POWERMON_ENABLE,
++              /**< MMAL_PARAMETER_LOGGING_T */
++      MMAL_PARAMETER_LOGGING,
++              /**< MMAL_PARAMETER_UINT64_T */
++      MMAL_PARAMETER_SYSTEM_TIME,
++              /**< MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_NO_IMAGE_PADDING,
++};
++
++/* camera parameters */
++
++enum mmal_parameter_camera_type {
++      /* 0 */
++              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
++      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
++              MMAL_PARAMETER_GROUP_CAMERA,
++              /**< Unused? */
++      MMAL_PARAMETER_CAPTURE_QUALITY,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_ROTATION,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_EXIF_DISABLE,
++              /**< @ref MMAL_PARAMETER_EXIF_T */
++      MMAL_PARAMETER_EXIF,
++              /**< @ref MMAL_PARAM_AWBMODE_T */
++      MMAL_PARAMETER_AWB_MODE,
++              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
++      MMAL_PARAMETER_IMAGE_EFFECT,
++              /**< @ref MMAL_PARAMETER_COLOURFX_T */
++      MMAL_PARAMETER_COLOUR_EFFECT,
++              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
++      MMAL_PARAMETER_FLICKER_AVOID,
++              /**< @ref MMAL_PARAMETER_FLASH_T */
++      MMAL_PARAMETER_FLASH,
++              /**< @ref MMAL_PARAMETER_REDEYE_T */
++      MMAL_PARAMETER_REDEYE,
++              /**< @ref MMAL_PARAMETER_FOCUS_T */
++      MMAL_PARAMETER_FOCUS,
++              /**< Unused? */
++      MMAL_PARAMETER_FOCAL_LENGTHS,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_EXPOSURE_COMP,
++              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
++      MMAL_PARAMETER_ZOOM,
++              /**< @ref MMAL_PARAMETER_MIRROR_T */
++      MMAL_PARAMETER_MIRROR,
++
++      /* 0x10 */
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_CAMERA_NUM,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_CAPTURE,
++              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
++      MMAL_PARAMETER_EXPOSURE_MODE,
++              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
++      MMAL_PARAMETER_EXP_METERING_MODE,
++              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
++      MMAL_PARAMETER_FOCUS_STATUS,
++              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
++      MMAL_PARAMETER_CAMERA_CONFIG,
++              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
++      MMAL_PARAMETER_CAPTURE_STATUS,
++              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
++      MMAL_PARAMETER_FACE_TRACK,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_JPEG_Q_FACTOR,
++              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
++      MMAL_PARAMETER_FRAME_RATE,
++              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
++      MMAL_PARAMETER_USE_STC,
++              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
++      MMAL_PARAMETER_CAMERA_INFO,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_STABILISATION,
++              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
++      MMAL_PARAMETER_FACE_TRACK_RESULTS,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
++
++      /* 0x20 */
++              /**< @ref MMAL_PARAMETER_URI_T */
++      MMAL_PARAMETER_DPF_FILE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_DPF_FILE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
++              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
++      MMAL_PARAMETER_CAPTURE_MODE,
++              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
++      MMAL_PARAMETER_FOCUS_REGIONS,
++              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
++      MMAL_PARAMETER_INPUT_CROP,
++              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
++      MMAL_PARAMETER_SENSOR_INFORMATION,
++              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
++      MMAL_PARAMETER_FLASH_SELECT,
++              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
++      MMAL_PARAMETER_FIELD_OF_VIEW,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
++              /**< @ref MMAL_PARAMETER_DRC_T */
++      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
++              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
++      MMAL_PARAMETER_ALGORITHM_CONTROL,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_SHARPNESS,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_CONTRAST,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_BRIGHTNESS,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_SATURATION,
++
++      /* 0x30 */
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_ISO,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ANTISHAKE,
++              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
++      MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
++              /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_CAMERA_MIN_ISO,
++              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
++      MMAL_PARAMETER_CAMERA_USE_CASE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_CAPTURE_STATS_PASS,
++              /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_REGISTER_FILE,
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
++              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
++      MMAL_PARAMETER_CONFIGFILE_REGISTERS,
++              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
++      MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_JPEG_ATTACH_LOG,
++              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
++      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
++              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
++      MMAL_PARAMETER_FPS_RANGE,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
++
++      /* 0x40 */
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_FLASH_REQUIRED,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_SW_SATURATION_DISABLE,
++      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_SHUTTER_SPEED,
++              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
++      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
++};
++
++struct mmal_parameter_rational {
++      s32 num;    /**< Numerator */
++      s32 den;    /**< Denominator */
++};
++
++enum mmal_parameter_camera_config_timestamp_mode {
++      MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
++      MMAL_PARAM_TIMESTAMP_MODE_RAW_STC,  /* Use the raw STC value
++                                           * for the frame timestamp
++                                           */
++      MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
++                                            * but subtract the
++                                            * timestamp of the first
++                                            * frame sent to give a
++                                            * zero based timestamp.
++                                            */
++};
++
++struct mmal_parameter_fps_range {
++      /**< Low end of the permitted framerate range */
++      struct mmal_parameter_rational  fps_low;
++      /**< High end of the permitted framerate range */
++      struct mmal_parameter_rational  fps_high;
++};
++
++/* camera configuration parameter */
++struct mmal_parameter_camera_config {
++      /* Parameters for setting up the image pools */
++      u32 max_stills_w; /* Max size of stills capture */
++      u32 max_stills_h;
++      u32 stills_yuv422; /* Allow YUV422 stills capture */
++      u32 one_shot_stills; /* Continuous or one shot stills captures. */
++
++      u32 max_preview_video_w; /* Max size of the preview or video
++                                * capture frames
++                                */
++      u32 max_preview_video_h;
++      u32 num_preview_video_frames;
++
++      /** Sets the height of the circular buffer for stills capture. */
++      u32 stills_capture_circular_buffer_height;
++
++      /** Allows preview/encode to resume as fast as possible after the stills
++       * input frame has been received, and then processes the still frame in
++       * the background whilst preview/encode has resumed.
++       * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
++       */
++      u32 fast_preview_resume;
++
++      /** Selects algorithm for timestamping frames if
++       * there is no clock component connected.
++       * enum mmal_parameter_camera_config_timestamp_mode
++       */
++      s32 use_stc_timestamp;
++};
++
++enum mmal_parameter_exposuremode {
++      MMAL_PARAM_EXPOSUREMODE_OFF,
++      MMAL_PARAM_EXPOSUREMODE_AUTO,
++      MMAL_PARAM_EXPOSUREMODE_NIGHT,
++      MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
++      MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
++      MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
++      MMAL_PARAM_EXPOSUREMODE_SPORTS,
++      MMAL_PARAM_EXPOSUREMODE_SNOW,
++      MMAL_PARAM_EXPOSUREMODE_BEACH,
++      MMAL_PARAM_EXPOSUREMODE_VERYLONG,
++      MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
++      MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
++      MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
++};
++
++enum mmal_parameter_exposuremeteringmode {
++      MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
++      MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
++      MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
++      MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
++};
++
++enum mmal_parameter_awbmode {
++      MMAL_PARAM_AWBMODE_OFF,
++      MMAL_PARAM_AWBMODE_AUTO,
++      MMAL_PARAM_AWBMODE_SUNLIGHT,
++      MMAL_PARAM_AWBMODE_CLOUDY,
++      MMAL_PARAM_AWBMODE_SHADE,
++      MMAL_PARAM_AWBMODE_TUNGSTEN,
++      MMAL_PARAM_AWBMODE_FLUORESCENT,
++      MMAL_PARAM_AWBMODE_INCANDESCENT,
++      MMAL_PARAM_AWBMODE_FLASH,
++      MMAL_PARAM_AWBMODE_HORIZON,
++};
++
++enum mmal_parameter_imagefx {
++      MMAL_PARAM_IMAGEFX_NONE,
++      MMAL_PARAM_IMAGEFX_NEGATIVE,
++      MMAL_PARAM_IMAGEFX_SOLARIZE,
++      MMAL_PARAM_IMAGEFX_POSTERIZE,
++      MMAL_PARAM_IMAGEFX_WHITEBOARD,
++      MMAL_PARAM_IMAGEFX_BLACKBOARD,
++      MMAL_PARAM_IMAGEFX_SKETCH,
++      MMAL_PARAM_IMAGEFX_DENOISE,
++      MMAL_PARAM_IMAGEFX_EMBOSS,
++      MMAL_PARAM_IMAGEFX_OILPAINT,
++      MMAL_PARAM_IMAGEFX_HATCH,
++      MMAL_PARAM_IMAGEFX_GPEN,
++      MMAL_PARAM_IMAGEFX_PASTEL,
++      MMAL_PARAM_IMAGEFX_WATERCOLOUR,
++      MMAL_PARAM_IMAGEFX_FILM,
++      MMAL_PARAM_IMAGEFX_BLUR,
++      MMAL_PARAM_IMAGEFX_SATURATION,
++      MMAL_PARAM_IMAGEFX_COLOURSWAP,
++      MMAL_PARAM_IMAGEFX_WASHEDOUT,
++      MMAL_PARAM_IMAGEFX_POSTERISE,
++      MMAL_PARAM_IMAGEFX_COLOURPOINT,
++      MMAL_PARAM_IMAGEFX_COLOURBALANCE,
++      MMAL_PARAM_IMAGEFX_CARTOON,
++};
++
++enum MMAL_PARAM_FLICKERAVOID_T {
++      MMAL_PARAM_FLICKERAVOID_OFF,
++      MMAL_PARAM_FLICKERAVOID_AUTO,
++      MMAL_PARAM_FLICKERAVOID_50HZ,
++      MMAL_PARAM_FLICKERAVOID_60HZ,
++      MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
++};
++
++struct mmal_parameter_awbgains {
++      struct mmal_parameter_rational r_gain;  /**< Red gain */
++      struct mmal_parameter_rational b_gain;  /**< Blue gain */
++};
++
++/** Manner of video rate control */
++enum mmal_parameter_rate_control_mode {
++      MMAL_VIDEO_RATECONTROL_DEFAULT,
++      MMAL_VIDEO_RATECONTROL_VARIABLE,
++      MMAL_VIDEO_RATECONTROL_CONSTANT,
++      MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
++      MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
++};
++
++enum mmal_video_profile {
++      MMAL_VIDEO_PROFILE_H263_BASELINE,
++      MMAL_VIDEO_PROFILE_H263_H320CODING,
++      MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
++      MMAL_VIDEO_PROFILE_H263_ISWV2,
++      MMAL_VIDEO_PROFILE_H263_ISWV3,
++      MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
++      MMAL_VIDEO_PROFILE_H263_INTERNET,
++      MMAL_VIDEO_PROFILE_H263_INTERLACE,
++      MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
++      MMAL_VIDEO_PROFILE_MP4V_CORE,
++      MMAL_VIDEO_PROFILE_MP4V_MAIN,
++      MMAL_VIDEO_PROFILE_MP4V_NBIT,
++      MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
++      MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
++      MMAL_VIDEO_PROFILE_MP4V_HYBRID,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
++      MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
++      MMAL_VIDEO_PROFILE_H264_BASELINE,
++      MMAL_VIDEO_PROFILE_H264_MAIN,
++      MMAL_VIDEO_PROFILE_H264_EXTENDED,
++      MMAL_VIDEO_PROFILE_H264_HIGH,
++      MMAL_VIDEO_PROFILE_H264_HIGH10,
++      MMAL_VIDEO_PROFILE_H264_HIGH422,
++      MMAL_VIDEO_PROFILE_H264_HIGH444,
++      MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
++      MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
++};
++
++enum mmal_video_level {
++      MMAL_VIDEO_LEVEL_H263_10,
++      MMAL_VIDEO_LEVEL_H263_20,
++      MMAL_VIDEO_LEVEL_H263_30,
++      MMAL_VIDEO_LEVEL_H263_40,
++      MMAL_VIDEO_LEVEL_H263_45,
++      MMAL_VIDEO_LEVEL_H263_50,
++      MMAL_VIDEO_LEVEL_H263_60,
++      MMAL_VIDEO_LEVEL_H263_70,
++      MMAL_VIDEO_LEVEL_MP4V_0,
++      MMAL_VIDEO_LEVEL_MP4V_0b,
++      MMAL_VIDEO_LEVEL_MP4V_1,
++      MMAL_VIDEO_LEVEL_MP4V_2,
++      MMAL_VIDEO_LEVEL_MP4V_3,
++      MMAL_VIDEO_LEVEL_MP4V_4,
++      MMAL_VIDEO_LEVEL_MP4V_4a,
++      MMAL_VIDEO_LEVEL_MP4V_5,
++      MMAL_VIDEO_LEVEL_MP4V_6,
++      MMAL_VIDEO_LEVEL_H264_1,
++      MMAL_VIDEO_LEVEL_H264_1b,
++      MMAL_VIDEO_LEVEL_H264_11,
++      MMAL_VIDEO_LEVEL_H264_12,
++      MMAL_VIDEO_LEVEL_H264_13,
++      MMAL_VIDEO_LEVEL_H264_2,
++      MMAL_VIDEO_LEVEL_H264_21,
++      MMAL_VIDEO_LEVEL_H264_22,
++      MMAL_VIDEO_LEVEL_H264_3,
++      MMAL_VIDEO_LEVEL_H264_31,
++      MMAL_VIDEO_LEVEL_H264_32,
++      MMAL_VIDEO_LEVEL_H264_4,
++      MMAL_VIDEO_LEVEL_H264_41,
++      MMAL_VIDEO_LEVEL_H264_42,
++      MMAL_VIDEO_LEVEL_H264_5,
++      MMAL_VIDEO_LEVEL_H264_51,
++      MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
++};
++
++struct mmal_parameter_video_profile {
++      enum mmal_video_profile profile;
++      enum mmal_video_level level;
++};
++
++/* video parameters */
++
++enum mmal_parameter_video_type {
++      /** @ref MMAL_DISPLAYREGION_T */
++      MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
++
++      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
++      MMAL_PARAMETER_SUPPORTED_PROFILES,
++
++      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
++      MMAL_PARAMETER_PROFILE,
++
++      /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_INTRAPERIOD,
++
++      /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
++      MMAL_PARAMETER_RATECONTROL,
++
++      /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
++      MMAL_PARAMETER_NALUNITFORMAT,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
++
++      /** @ref MMAL_PARAMETER_UINT32_T.
++       * Setting the value to zero resets to the default (one slice per
++       * frame).
++       */
++      MMAL_PARAMETER_MB_ROWS_PER_SLICE,
++
++      /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
++      MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
++
++      /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
++      MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
++
++      /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
++      MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
++      MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
++      /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
++      MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
++      MMAL_PARAMETER_VIDEO_BIT_RATE,
++
++      /** @ref MMAL_PARAMETER_FRAME_RATE_T */
++      MMAL_PARAMETER_VIDEO_FRAME_RATE,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
++
++      /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
++
++      MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
++      /** @ref MMAL_PARAMETER_UINT32_T.
++       * Changing this parameter from the default can reduce frame rate
++       * because image buffers need to be re-pitched.
++       */
++      MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
++
++      /** @ref MMAL_PARAMETER_UINT32_T.
++       * Changing this parameter from the default can reduce frame rate
++       * because image buffers need to be re-pitched.
++       */
++      MMAL_PARAMETER_VIDEO_ALIGN_VERT,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
++
++      /**< @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
++
++      /**< @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
++
++      /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
++
++      /* H264 specific parameters */
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
++
++      /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
++
++      /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
++      MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
++
++      /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
++      MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
++
++      /** @ref MMAL_PARAMETER_BYTES_T */
++      MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3,
++
++      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS,
++
++      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
++
++      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
++};
++
++/** Valid mirror modes */
++enum mmal_parameter_mirror {
++      MMAL_PARAM_MIRROR_NONE,
++      MMAL_PARAM_MIRROR_VERTICAL,
++      MMAL_PARAM_MIRROR_HORIZONTAL,
++      MMAL_PARAM_MIRROR_BOTH,
++};
++
++enum mmal_parameter_displaytransform {
++      MMAL_DISPLAY_ROT0 = 0,
++      MMAL_DISPLAY_MIRROR_ROT0 = 1,
++      MMAL_DISPLAY_MIRROR_ROT180 = 2,
++      MMAL_DISPLAY_ROT180 = 3,
++      MMAL_DISPLAY_MIRROR_ROT90 = 4,
++      MMAL_DISPLAY_ROT270 = 5,
++      MMAL_DISPLAY_ROT90 = 6,
++      MMAL_DISPLAY_MIRROR_ROT270 = 7,
++};
++
++enum mmal_parameter_displaymode {
++      MMAL_DISPLAY_MODE_FILL = 0,
++      MMAL_DISPLAY_MODE_LETTERBOX = 1,
++};
++
++enum mmal_parameter_displayset {
++      MMAL_DISPLAY_SET_NONE = 0,
++      MMAL_DISPLAY_SET_NUM = 1,
++      MMAL_DISPLAY_SET_FULLSCREEN = 2,
++      MMAL_DISPLAY_SET_TRANSFORM = 4,
++      MMAL_DISPLAY_SET_DEST_RECT = 8,
++      MMAL_DISPLAY_SET_SRC_RECT = 0x10,
++      MMAL_DISPLAY_SET_MODE = 0x20,
++      MMAL_DISPLAY_SET_PIXEL = 0x40,
++      MMAL_DISPLAY_SET_NOASPECT = 0x80,
++      MMAL_DISPLAY_SET_LAYER = 0x100,
++      MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
++      MMAL_DISPLAY_SET_ALPHA = 0x400,
++};
++
++/* rectangle, used lots so it gets its own struct */
++struct vchiq_mmal_rect {
++      s32 x;
++      s32 y;
++      s32 width;
++      s32 height;
++};
++
++struct mmal_parameter_displayregion {
++      /** Bitfield that indicates which fields are set and should be
++       * used. All other fields will maintain their current value.
++       * \ref MMAL_DISPLAYSET_T defines the bits that can be
++       * combined.
++       */
++      u32 set;
++
++      /** Describes the display output device, with 0 typically
++       * being a directly connected LCD display.  The actual values
++       * will depend on the hardware.  Code using hard-wired numbers
++       * (e.g. 2) is certain to fail.
++       */
++
++      u32 display_num;
++      /** Indicates that we are using the full device screen area,
++       * rather than a window of the display.  If zero, then
++       * dest_rect is used to specify a region of the display to
++       * use.
++       */
++
++      s32 fullscreen;
++      /** Indicates any rotation or flipping used to map frames onto
++       * the natural display orientation.
++       */
++      u32 transform; /* enum mmal_parameter_displaytransform */
++
++      /** Where to display the frame within the screen, if
++       * fullscreen is zero.
++       */
++      struct vchiq_mmal_rect dest_rect;
++
++      /** Indicates which area of the frame to display. If all
++       * values are zero, the whole frame will be used.
++       */
++      struct vchiq_mmal_rect src_rect;
++
++      /** If set to non-zero, indicates that any display scaling
++       * should disregard the aspect ratio of the frame region being
++       * displayed.
++       */
++      s32 noaspect;
++
++      /** Indicates how the image should be scaled to fit the
++       * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
++       * that the image should fill the screen by potentially
++       * cropping the frames.  Setting \code mode \endcode to \code
++       * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
++       * source region should be displayed and black bars added if
++       * necessary.
++       */
++      u32 mode; /* enum mmal_parameter_displaymode */
++
++      /** If non-zero, defines the width of a source pixel relative
++       * to \code pixel_y \endcode.  If zero, then pixels default to
++       * being square.
++       */
++      u32 pixel_x;
++
++      /** If non-zero, defines the height of a source pixel relative
++       * to \code pixel_x \endcode.  If zero, then pixels default to
++       * being square.
++       */
++      u32 pixel_y;
++
++      /** Sets the relative depth of the images, with greater values
++       * being in front of smaller values.
++       */
++      u32 layer;
++
++      /** Set to non-zero to ensure copy protection is used on
++       * output.
++       */
++      s32 copyprotect_required;
++
++      /** Level of opacity of the layer, where zero is fully
++       * transparent and 255 is fully opaque.
++       */
++      u32 alpha;
++};
++
++#define MMAL_MAX_IMAGEFX_PARAMETERS 5
++
++struct mmal_parameter_imagefx_parameters {
++      enum mmal_parameter_imagefx effect;
++      u32 num_effect_params;
++      u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
++};
++
++#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4
++#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2
++#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16
++
++struct mmal_parameter_camera_info_camera_t {
++      u32    port_id;
++      u32    max_width;
++      u32    max_height;
++      u32    lens_present;
++      u8     camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN];
++};
++
++enum mmal_parameter_camera_info_flash_type_t {
++      /* Make values explicit to ensure they match values in config ini */
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0,
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED   = 1,
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2,
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF
++};
++
++struct mmal_parameter_camera_info_flash_t {
++      enum mmal_parameter_camera_info_flash_type_t flash_type;
++};
++
++struct mmal_parameter_camera_info_t {
++      u32                            num_cameras;
++      u32                            num_flashes;
++      struct mmal_parameter_camera_info_camera_t
++                              cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
++      struct mmal_parameter_camera_info_flash_t
++                              flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
++};
++
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -0,0 +1,166 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ *
++ * MMAL interface to VCHIQ message passing
++ */
++
++#ifndef MMAL_VCHIQ_H
++#define MMAL_VCHIQ_H
++
++#include "mmal-msg-format.h"
++
++#define MAX_PORT_COUNT 4
++
++/* Maximum size of the format extradata. */
++#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
++
++struct vchiq_mmal_instance;
++
++enum vchiq_mmal_es_type {
++      MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
++      MMAL_ES_TYPE_CONTROL,     /**< Elementary stream of control commands */
++      MMAL_ES_TYPE_AUDIO,       /**< Audio elementary stream */
++      MMAL_ES_TYPE_VIDEO,       /**< Video elementary stream */
++      MMAL_ES_TYPE_SUBPICTURE   /**< Sub-picture elementary stream */
++};
++
++struct vchiq_mmal_port_buffer {
++      unsigned int num; /* number of buffers */
++      u32 size; /* size of buffers */
++      u32 alignment; /* alignment of buffers */
++};
++
++struct vchiq_mmal_port;
++
++typedef void (*vchiq_mmal_buffer_cb)(
++              struct vchiq_mmal_instance  *instance,
++              struct vchiq_mmal_port *port,
++              int status, struct mmal_buffer *buffer,
++              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
++
++struct vchiq_mmal_port {
++      bool enabled;
++      u32 handle;
++      u32 type; /* port type, cached to use on port info set */
++      u32 index; /* port index, cached to use on port info set */
++
++      /* component port belongs to, allows simple deref */
++      struct vchiq_mmal_component *component;
++
++      struct vchiq_mmal_port *connected; /* port conencted to */
++
++      /* buffer info */
++      struct vchiq_mmal_port_buffer minimum_buffer;
++      struct vchiq_mmal_port_buffer recommended_buffer;
++      struct vchiq_mmal_port_buffer current_buffer;
++
++      /* stream format */
++      struct mmal_es_format_local format;
++      /* elementary stream format */
++      union mmal_es_specific_format es;
++
++      /* data buffers to fill */
++      struct list_head buffers;
++      /* lock to serialise adding and removing buffers from list */
++      spinlock_t slock;
++
++      /* Count of buffers the VPU has yet to return */
++      atomic_t buffers_with_vpu;
++      /* callback on buffer completion */
++      vchiq_mmal_buffer_cb buffer_cb;
++      /* callback context */
++      void *cb_ctx;
++};
++
++struct vchiq_mmal_component {
++      bool enabled;
++      u32 handle;  /* VideoCore handle for component */
++      u32 inputs;  /* Number of input ports */
++      u32 outputs; /* Number of output ports */
++      u32 clocks;  /* Number of clock ports */
++      struct vchiq_mmal_port control; /* control port */
++      struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
++      struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
++      struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
++};
++
++int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
++int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
++
++/* Initialise a mmal component and its ports
++ *
++ */
++int vchiq_mmal_component_init(
++              struct vchiq_mmal_instance *instance,
++              const char *name,
++              struct vchiq_mmal_component **component_out);
++
++int vchiq_mmal_component_finalise(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_component *component);
++
++int vchiq_mmal_component_enable(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_component *component);
++
++int vchiq_mmal_component_disable(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_component *component);
++
++/* enable a mmal port
++ *
++ * enables a port and if a buffer callback provided enque buffer
++ * headers as appropriate for the port.
++ */
++int vchiq_mmal_port_enable(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_port *port,
++              vchiq_mmal_buffer_cb buffer_cb);
++
++/* disable a port
++ *
++ * disable a port will dequeue any pending buffers
++ */
++int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_port *port);
++
++int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter,
++                                void *value,
++                                u32 value_size);
++
++int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter,
++                                void *value,
++                                u32 *value_size);
++
++int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
++                             struct vchiq_mmal_port *port);
++
++int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
++                                 struct vchiq_mmal_port *src,
++                                 struct vchiq_mmal_port *dst);
++
++int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
++                     u32 *major_out,
++                     u32 *minor_out);
++
++int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_port *port,
++                           struct mmal_buffer *buf);
++
++int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
++                        struct mmal_buffer *buf);
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
++#endif /* MMAL_VCHIQ_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0233-staging-bcm2835-camera-Remove-amend-some-obsolete-co.patch b/target/linux/brcm2708/patches-4.19/950-0233-staging-bcm2835-camera-Remove-amend-some-obsolete-co.patch
deleted file mode 100644 (file)
index 920249e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 37ede4f6a1771b09dea6e8b2fc4d2c5f085a33f3 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 28 Sep 2018 10:22:26 +0100
-Subject: [PATCH] staging: bcm2835-camera: Remove/amend some obsolete
- comments
-
-Remove a todo which has been done.
-Remove a template line that was redundant.
-Make a comment clearer as to the non-obvious meaning of a field.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/controls.c   | 11 +----------
- 1 file changed, 1 insertion(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -965,10 +965,6 @@ static const struct bm2835_mmal_v4l2_ctr
-               &ctrl_set_value,
-               false
-       },
--/*    {
-- *            0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
-- *    },
-- */
-       {
-               V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
-               ~0x03, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
-@@ -976,11 +972,6 @@ static const struct bm2835_mmal_v4l2_ctr
-               &ctrl_set_exposure,
-               false
-       },
--/* todo this needs mixing in with set exposure
-- *    {
-- *            V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
-- *    },
-- */
-       {
-               V4L2_CID_EXPOSURE_ABSOLUTE, MMAL_CONTROL_TYPE_STD,
-               /* Units of 100usecs */
-@@ -1146,7 +1137,7 @@ static const struct bm2835_mmal_v4l2_ctr
-       },
-       {
-               V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
--              -1,     /* Min is computed at runtime */
-+              -1,     /* Min (mask) is computed at runtime */
-               V4L2_SCENE_MODE_TEXT,
-               V4L2_SCENE_MODE_NONE, 1, NULL,
-               MMAL_PARAMETER_PROFILE,
diff --git a/target/linux/brcm2708/patches-4.19/950-0233-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch b/target/linux/brcm2708/patches-4.19/950-0233-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch
new file mode 100644 (file)
index 0000000..7e4100f
--- /dev/null
@@ -0,0 +1,107 @@
+From f94642597f63c71b2ccffddd4f447190c131af56 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:51:13 +0100
+Subject: [PATCH] staging: mmal-vchiq: Allocate and free components as
+ required
+
+The existing code assumed that there would only ever be 4 components,
+and never freed the entries once used.
+Allow arbitrary creation and destruction of components.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 29 ++++++++++++-------
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  1 +
+ 2 files changed, 20 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -38,8 +38,11 @@ MODULE_AUTHOR("Dave Stevenson, <dave.ste
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION("0.0.1");
+-/* maximum number of components supported */
+-#define VCHIQ_MMAL_MAX_COMPONENTS 4
++/*
++ * maximum number of components supported.
++ * This matches the maximum permitted by default on the VPU
++ */
++#define VCHIQ_MMAL_MAX_COMPONENTS 64
+ /*#define FULL_MSG_DUMP 1*/
+@@ -174,8 +177,6 @@ struct vchiq_mmal_instance {
+       /* protect accesses to context_map */
+       struct mutex context_map_lock;
+-      /* component to use next */
+-      int component_idx;
+       struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
+       /* ordered workqueue to process all bulk operations */
+@@ -1632,18 +1633,24 @@ int vchiq_mmal_component_init(struct vch
+ {
+       int ret;
+       int idx;                /* port index */
+-      struct vchiq_mmal_component *component;
++      struct vchiq_mmal_component *component = NULL;
+       if (mutex_lock_interruptible(&instance->vchiq_mutex))
+               return -EINTR;
+-      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
++      for (idx = 0; idx < VCHIQ_MMAL_MAX_COMPONENTS; idx++) {
++              if (!instance->component[idx].in_use) {
++                      component = &instance->component[idx];
++                      component->in_use = 1;
++                      break;
++              }
++      }
++
++      if (!component) {
+               ret = -EINVAL;  /* todo is this correct error? */
+               goto unlock;
+       }
+-      component = &instance->component[instance->component_idx];
+-
+       ret = create_component(instance, component, name);
+       if (ret < 0) {
+               pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
+@@ -1694,8 +1701,6 @@ int vchiq_mmal_component_init(struct vch
+                       goto release_component;
+       }
+-      instance->component_idx++;
+-
+       *component_out = component;
+       mutex_unlock(&instance->vchiq_mutex);
+@@ -1705,6 +1710,8 @@ int vchiq_mmal_component_init(struct vch
+ release_component:
+       destroy_component(instance, component);
+ unlock:
++      if (component)
++              component->in_use = 0;
+       mutex_unlock(&instance->vchiq_mutex);
+       return ret;
+@@ -1727,6 +1734,8 @@ int vchiq_mmal_component_finalise(struct
+       ret = destroy_component(instance, component);
++      component->in_use = 0;
++
+       mutex_unlock(&instance->vchiq_mutex);
+       return ret;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -82,6 +82,7 @@ struct vchiq_mmal_port {
+ };
+ struct vchiq_mmal_component {
++      u32 in_use:1;
+       bool enabled;
+       u32 handle;  /* VideoCore handle for component */
+       u32 inputs;  /* Number of input ports */
diff --git a/target/linux/brcm2708/patches-4.19/950-0234-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch b/target/linux/brcm2708/patches-4.19/950-0234-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch
new file mode 100644 (file)
index 0000000..401b8bf
--- /dev/null
@@ -0,0 +1,93 @@
+From 3789c3b08b56f471878c493fd80a2eee776b527c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 16:20:46 +0000
+Subject: [PATCH] staging: mmal-vchiq: Avoid use of bool in structures
+
+Fixes up a checkpatch error "Avoid using bool structure members
+because of possible alignment issues".
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c  | 14 +++++++-------
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h  |  4 ++--
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -861,9 +861,9 @@ static int port_info_get(struct vchiq_mm
+               goto release_msg;
+       if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
+-              port->enabled = false;
++              port->enabled = 0;
+       else
+-              port->enabled = true;
++              port->enabled = 1;
+       /* copy the values out of the message */
+       port->handle = rmsg->u.port_info_get_reply.port_handle;
+@@ -1300,7 +1300,7 @@ static int port_disable(struct vchiq_mma
+       if (!port->enabled)
+               return 0;
+-      port->enabled = false;
++      port->enabled = 0;
+       ret = port_action_port(instance, port,
+                              MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
+@@ -1352,7 +1352,7 @@ static int port_enable(struct vchiq_mmal
+       if (ret)
+               goto done;
+-      port->enabled = true;
++      port->enabled = 1;
+       if (port->buffer_cb) {
+               /* send buffer headers to videocore */
+@@ -1524,7 +1524,7 @@ int vchiq_mmal_port_connect_tunnel(struc
+                       pr_err("failed disconnecting src port\n");
+                       goto release_unlock;
+               }
+-              src->connected->enabled = false;
++              src->connected->enabled = 0;
+               src->connected = NULL;
+       }
+@@ -1760,7 +1760,7 @@ int vchiq_mmal_component_enable(struct v
+       ret = enable_component(instance, component);
+       if (ret == 0)
+-              component->enabled = true;
++              component->enabled = 1;
+       mutex_unlock(&instance->vchiq_mutex);
+@@ -1786,7 +1786,7 @@ int vchiq_mmal_component_disable(struct
+       ret = disable_component(instance, component);
+       if (ret == 0)
+-              component->enabled = false;
++              component->enabled = 0;
+       mutex_unlock(&instance->vchiq_mutex);
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -48,7 +48,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
+               unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
+ struct vchiq_mmal_port {
+-      bool enabled;
++      u32 enabled:1;
+       u32 handle;
+       u32 type; /* port type, cached to use on port info set */
+       u32 index; /* port index, cached to use on port info set */
+@@ -83,7 +83,7 @@ struct vchiq_mmal_port {
+ struct vchiq_mmal_component {
+       u32 in_use:1;
+-      bool enabled;
++      u32 enabled:1;
+       u32 handle;  /* VideoCore handle for component */
+       u32 inputs;  /* Number of input ports */
+       u32 outputs; /* Number of output ports */
diff --git a/target/linux/brcm2708/patches-4.19/950-0234-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch b/target/linux/brcm2708/patches-4.19/950-0234-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch
deleted file mode 100644 (file)
index 1cd23da..0000000
+++ /dev/null
@@ -1,7535 +0,0 @@
-From e7723c6bcf31a440b8762e9e22497ff3fbbb7056 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:30:37 +0100
-Subject: [PATCH] staging: vc04_services: Split vchiq-mmal into a
- module
-
-In preparation for adding a video codec V4L2 module which also
-wants to use vchiq-mmal functions, split it out into an
-independent module.
-The minimum number of changes have been made to achieve this
-(eg straight moves where possible) so existing checkpatch
-errors will still be present.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/Kconfig         |  1 +
- drivers/staging/vc04_services/Makefile        |  1 +
- .../vc04_services/bcm2835-camera/Kconfig      |  2 +-
- .../vc04_services/bcm2835-camera/Makefile     |  4 ++--
- .../staging/vc04_services/vchiq-mmal/Kconfig  |  7 ++++++
- .../staging/vc04_services/vchiq-mmal/Makefile |  8 +++++++
- .../mmal-common.h                             |  0
- .../mmal-encodings.h                          |  0
- .../mmal-msg-common.h                         |  0
- .../mmal-msg-format.h                         |  0
- .../mmal-msg-port.h                           |  0
- .../{bcm2835-camera => vchiq-mmal}/mmal-msg.h |  0
- .../mmal-parameters.h                         |  0
- .../mmal-vchiq.c                              | 22 +++++++++++++++++++
- .../mmal-vchiq.h                              |  0
- 15 files changed, 42 insertions(+), 3 deletions(-)
- create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Kconfig
- create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Makefile
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-common.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-encodings.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-common.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-format.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-port.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-parameters.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.c (98%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.h (100%)
-
---- a/drivers/staging/vc04_services/Kconfig
-+++ b/drivers/staging/vc04_services/Kconfig
-@@ -21,6 +21,7 @@ config BCM2835_VCHIQ
- source "drivers/staging/vc04_services/bcm2835-audio/Kconfig"
- source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
-+source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
- endif
---- a/drivers/staging/vc04_services/Makefile
-+++ b/drivers/staging/vc04_services/Makefile
-@@ -12,6 +12,7 @@ vchiq-objs := \
- obj-$(CONFIG_SND_BCM2835)     += bcm2835-audio/
- obj-$(CONFIG_VIDEO_BCM2835)   += bcm2835-camera/
-+obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
- ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
---- a/drivers/staging/vc04_services/bcm2835-camera/Kconfig
-+++ b/drivers/staging/vc04_services/bcm2835-camera/Kconfig
-@@ -2,7 +2,7 @@ config VIDEO_BCM2835
-       tristate "BCM2835 Camera"
-       depends on MEDIA_SUPPORT
-       depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
--      select BCM2835_VCHIQ
-+      select BCM2835_VCHIQ_MMAL
-       select VIDEOBUF2_VMALLOC
-       select BTREE
-       help
---- a/drivers/staging/vc04_services/bcm2835-camera/Makefile
-+++ b/drivers/staging/vc04_services/bcm2835-camera/Makefile
-@@ -1,11 +1,11 @@
- # SPDX-License-Identifier: GPL-2.0
- bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \
-       bcm2835-camera.o \
--      controls.o \
--      mmal-vchiq.o
-+      controls.o
- obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o
- ccflags-y += \
-       -Idrivers/staging/vc04_services \
-+      -Idrivers/staging/vc04_services/vchiq-mmal \
-       -D__VCCOREVER__=0x04000000
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
-@@ -0,0 +1,7 @@
-+config BCM2835_VCHIQ_MMAL
-+      tristate "BCM2835 MMAL VCHIQ service"
-+      depends on (ARCH_BCM2835 || COMPILE_TEST)
-+      select BCM2835_VCHIQ
-+      help
-+        Enables the MMAL API over VCHIQ as used for the
-+        majority of the multimedia services on VideoCore.
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/Makefile
-@@ -0,0 +1,8 @@
-+# SPDX-License-Identifier: GPL-2.0
-+bcm2835-mmal-vchiq-objs := mmal-vchiq.o
-+
-+obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o
-+
-+ccflags-y += \
-+      -Idrivers/staging/vc04_services \
-+      -D__VCCOREVER__=0x04000000
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
-+++ /dev/null
-@@ -1,1899 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- *
-- * V4L2 driver MMAL vchiq interface code
-- */
--
--#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
--
--#include <linux/errno.h>
--#include <linux/kernel.h>
--#include <linux/mutex.h>
--#include <linux/mm.h>
--#include <linux/slab.h>
--#include <linux/completion.h>
--#include <linux/vmalloc.h>
--#include <asm/cacheflush.h>
--#include <media/videobuf2-vmalloc.h>
--
--#include "mmal-common.h"
--#include "mmal-vchiq.h"
--#include "mmal-msg.h"
--
--#define USE_VCHIQ_ARM
--#include "interface/vchi/vchi.h"
--
--/* maximum number of components supported */
--#define VCHIQ_MMAL_MAX_COMPONENTS 4
--
--/*#define FULL_MSG_DUMP 1*/
--
--#ifdef DEBUG
--static const char *const msg_type_names[] = {
--      "UNKNOWN",
--      "QUIT",
--      "SERVICE_CLOSED",
--      "GET_VERSION",
--      "COMPONENT_CREATE",
--      "COMPONENT_DESTROY",
--      "COMPONENT_ENABLE",
--      "COMPONENT_DISABLE",
--      "PORT_INFO_GET",
--      "PORT_INFO_SET",
--      "PORT_ACTION",
--      "BUFFER_FROM_HOST",
--      "BUFFER_TO_HOST",
--      "GET_STATS",
--      "PORT_PARAMETER_SET",
--      "PORT_PARAMETER_GET",
--      "EVENT_TO_HOST",
--      "GET_CORE_STATS_FOR_PORT",
--      "OPAQUE_ALLOCATOR",
--      "CONSUME_MEM",
--      "LMK",
--      "OPAQUE_ALLOCATOR_DESC",
--      "DRM_GET_LHS32",
--      "DRM_GET_TIME",
--      "BUFFER_FROM_HOST_ZEROLEN",
--      "PORT_FLUSH",
--      "HOST_LOG",
--};
--#endif
--
--static const char *const port_action_type_names[] = {
--      "UNKNOWN",
--      "ENABLE",
--      "DISABLE",
--      "FLUSH",
--      "CONNECT",
--      "DISCONNECT",
--      "SET_REQUIREMENTS",
--};
--
--#if defined(DEBUG)
--#if defined(FULL_MSG_DUMP)
--#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
--      do {                                                            \
--              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
--                       msg_type_names[(MSG)->h.type],                 \
--                       (MSG)->h.type, (MSG_LEN));                     \
--              print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
--                             16, 4, (MSG),                            \
--                             sizeof(struct mmal_msg_header), 1);      \
--              print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
--                             16, 4,                                   \
--                             ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
--                             (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
--      } while (0)
--#else
--#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
--      {                                                               \
--              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
--                       msg_type_names[(MSG)->h.type],                 \
--                       (MSG)->h.type, (MSG_LEN));                     \
--      }
--#endif
--#else
--#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
--#endif
--
--struct vchiq_mmal_instance;
--
--/* normal message context */
--struct mmal_msg_context {
--      struct vchiq_mmal_instance *instance;
--
--      /* Index in the context_map idr so that we can find the
--       * mmal_msg_context again when servicing the VCHI reply.
--       */
--      int handle;
--
--      union {
--              struct {
--                      /* work struct for buffer_cb callback */
--                      struct work_struct work;
--                      /* work struct for deferred callback */
--                      struct work_struct buffer_to_host_work;
--                      /* mmal instance */
--                      struct vchiq_mmal_instance *instance;
--                      /* mmal port */
--                      struct vchiq_mmal_port *port;
--                      /* actual buffer used to store bulk reply */
--                      struct mmal_buffer *buffer;
--                      /* amount of buffer used */
--                      unsigned long buffer_used;
--                      /* MMAL buffer flags */
--                      u32 mmal_flags;
--                      /* Presentation and Decode timestamps */
--                      s64 pts;
--                      s64 dts;
--
--                      int status;     /* context status */
--
--              } bulk;         /* bulk data */
--
--              struct {
--                      /* message handle to release */
--                      VCHI_HELD_MSG_T msg_handle;
--                      /* pointer to received message */
--                      struct mmal_msg *msg;
--                      /* received message length */
--                      u32 msg_len;
--                      /* completion upon reply */
--                      struct completion cmplt;
--              } sync;         /* synchronous response */
--      } u;
--
--};
--
--struct vchiq_mmal_instance {
--      VCHI_SERVICE_HANDLE_T handle;
--
--      /* ensure serialised access to service */
--      struct mutex vchiq_mutex;
--
--      /* vmalloc page to receive scratch bulk xfers into */
--      void *bulk_scratch;
--
--      struct idr context_map;
--      /* protect accesses to context_map */
--      struct mutex context_map_lock;
--
--      /* component to use next */
--      int component_idx;
--      struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
--
--      /* ordered workqueue to process all bulk operations */
--      struct workqueue_struct *bulk_wq;
--};
--
--static struct mmal_msg_context *
--get_msg_context(struct vchiq_mmal_instance *instance)
--{
--      struct mmal_msg_context *msg_context;
--      int handle;
--
--      /* todo: should this be allocated from a pool to avoid kzalloc */
--      msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
--
--      if (!msg_context)
--              return ERR_PTR(-ENOMEM);
--
--      /* Create an ID that will be passed along with our message so
--       * that when we service the VCHI reply, we can look up what
--       * message is being replied to.
--       */
--      mutex_lock(&instance->context_map_lock);
--      handle = idr_alloc(&instance->context_map, msg_context,
--                         0, 0, GFP_KERNEL);
--      mutex_unlock(&instance->context_map_lock);
--
--      if (handle < 0) {
--              kfree(msg_context);
--              return ERR_PTR(handle);
--      }
--
--      msg_context->instance = instance;
--      msg_context->handle = handle;
--
--      return msg_context;
--}
--
--static struct mmal_msg_context *
--lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
--{
--      return idr_find(&instance->context_map, handle);
--}
--
--static void
--release_msg_context(struct mmal_msg_context *msg_context)
--{
--      struct vchiq_mmal_instance *instance = msg_context->instance;
--
--      mutex_lock(&instance->context_map_lock);
--      idr_remove(&instance->context_map, msg_context->handle);
--      mutex_unlock(&instance->context_map_lock);
--      kfree(msg_context);
--}
--
--/* deals with receipt of event to host message */
--static void event_to_host_cb(struct vchiq_mmal_instance *instance,
--                           struct mmal_msg *msg, u32 msg_len)
--{
--      pr_debug("unhandled event\n");
--      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
--               msg->u.event_to_host.client_component,
--               msg->u.event_to_host.port_type,
--               msg->u.event_to_host.port_num,
--               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
--}
--
--/* workqueue scheduled callback
-- *
-- * we do this because it is important we do not call any other vchiq
-- * sync calls from witin the message delivery thread
-- */
--static void buffer_work_cb(struct work_struct *work)
--{
--      struct mmal_msg_context *msg_context =
--              container_of(work, struct mmal_msg_context, u.bulk.work);
--
--      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
--
--      msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
--                                          msg_context->u.bulk.port,
--                                          msg_context->u.bulk.status,
--                                          msg_context->u.bulk.buffer,
--                                          msg_context->u.bulk.buffer_used,
--                                          msg_context->u.bulk.mmal_flags,
--                                          msg_context->u.bulk.dts,
--                                          msg_context->u.bulk.pts);
--}
--
--/* workqueue scheduled callback to handle receiving buffers
-- *
-- * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
-- * If we block in the service_callback context then we can't process the
-- * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
-- * vchi_bulk_queue_receive() call to complete.
-- */
--static void buffer_to_host_work_cb(struct work_struct *work)
--{
--      struct mmal_msg_context *msg_context =
--              container_of(work, struct mmal_msg_context,
--                           u.bulk.buffer_to_host_work);
--      struct vchiq_mmal_instance *instance = msg_context->instance;
--      unsigned long len = msg_context->u.bulk.buffer_used;
--      int ret;
--
--      if (!len)
--              /* Dummy receive to ensure the buffers remain in order */
--              len = 8;
--      /* queue the bulk submission */
--      vchi_service_use(instance->handle);
--      ret = vchi_bulk_queue_receive(instance->handle,
--                                    msg_context->u.bulk.buffer->buffer,
--                                    /* Actual receive needs to be a multiple
--                                     * of 4 bytes
--                                     */
--                                    (len + 3) & ~3,
--                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
--                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
--                                    msg_context);
--
--      vchi_service_release(instance->handle);
--
--      if (ret != 0)
--              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
--                     __func__, msg_context, ret);
--}
--
--/* enqueue a bulk receive for a given message context */
--static int bulk_receive(struct vchiq_mmal_instance *instance,
--                      struct mmal_msg *msg,
--                      struct mmal_msg_context *msg_context)
--{
--      unsigned long rd_len;
--
--      rd_len = msg->u.buffer_from_host.buffer_header.length;
--
--      if (!msg_context->u.bulk.buffer) {
--              pr_err("bulk.buffer not configured - error in buffer_from_host\n");
--
--              /* todo: this is a serious error, we should never have
--               * committed a buffer_to_host operation to the mmal
--               * port without the buffer to back it up (underflow
--               * handling) and there is no obvious way to deal with
--               * this - how is the mmal servie going to react when
--               * we fail to do the xfer and reschedule a buffer when
--               * it arrives? perhaps a starved flag to indicate a
--               * waiting bulk receive?
--               */
--
--              return -EINVAL;
--      }
--
--      /* ensure we do not overrun the available buffer */
--      if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
--              rd_len = msg_context->u.bulk.buffer->buffer_size;
--              pr_warn("short read as not enough receive buffer space\n");
--              /* todo: is this the correct response, what happens to
--               * the rest of the message data?
--               */
--      }
--
--      /* store length */
--      msg_context->u.bulk.buffer_used = rd_len;
--      msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
--      msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
--
--      queue_work(msg_context->instance->bulk_wq,
--                 &msg_context->u.bulk.buffer_to_host_work);
--
--      return 0;
--}
--
--/* data in message, memcpy from packet into output buffer */
--static int inline_receive(struct vchiq_mmal_instance *instance,
--                        struct mmal_msg *msg,
--                        struct mmal_msg_context *msg_context)
--{
--      memcpy(msg_context->u.bulk.buffer->buffer,
--             msg->u.buffer_from_host.short_data,
--             msg->u.buffer_from_host.payload_in_message);
--
--      msg_context->u.bulk.buffer_used =
--          msg->u.buffer_from_host.payload_in_message;
--
--      return 0;
--}
--
--/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
--static int
--buffer_from_host(struct vchiq_mmal_instance *instance,
--               struct vchiq_mmal_port *port, struct mmal_buffer *buf)
--{
--      struct mmal_msg_context *msg_context;
--      struct mmal_msg m;
--      int ret;
--
--      if (!port->enabled)
--              return -EINVAL;
--
--      pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
--
--      /* get context */
--      if (!buf->msg_context) {
--              pr_err("%s: msg_context not allocated, buf %p\n", __func__,
--                     buf);
--              return -EINVAL;
--      }
--      msg_context = buf->msg_context;
--
--      /* store bulk message context for when data arrives */
--      msg_context->u.bulk.instance = instance;
--      msg_context->u.bulk.port = port;
--      msg_context->u.bulk.buffer = buf;
--      msg_context->u.bulk.buffer_used = 0;
--
--      /* initialise work structure ready to schedule callback */
--      INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
--      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
--                buffer_to_host_work_cb);
--
--      atomic_inc(&port->buffers_with_vpu);
--
--      /* prep the buffer from host message */
--      memset(&m, 0xbc, sizeof(m));    /* just to make debug clearer */
--
--      m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
--      m.h.magic = MMAL_MAGIC;
--      m.h.context = msg_context->handle;
--      m.h.status = 0;
--
--      /* drvbuf is our private data passed back */
--      m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
--      m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
--      m.u.buffer_from_host.drvbuf.port_handle = port->handle;
--      m.u.buffer_from_host.drvbuf.client_context = msg_context->handle;
--
--      /* buffer header */
--      m.u.buffer_from_host.buffer_header.cmd = 0;
--      m.u.buffer_from_host.buffer_header.data =
--              (u32)(unsigned long)buf->buffer;
--      m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
--      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
--      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
--      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
--      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
--      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
--
--      /* clear buffer type sepecific data */
--      memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
--             sizeof(m.u.buffer_from_host.buffer_header_type_specific));
--
--      /* no payload in message */
--      m.u.buffer_from_host.payload_in_message = 0;
--
--      vchi_service_use(instance->handle);
--
--      ret = vchi_queue_kernel_message(instance->handle,
--                                      &m,
--                                      sizeof(struct mmal_msg_header) +
--                                      sizeof(m.u.buffer_from_host));
--
--      vchi_service_release(instance->handle);
--
--      return ret;
--}
--
--/* deals with receipt of buffer to host message */
--static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
--                            struct mmal_msg *msg, u32 msg_len)
--{
--      struct mmal_msg_context *msg_context;
--      u32 handle;
--
--      pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
--               __func__, instance, msg, msg_len);
--
--      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
--              handle = msg->u.buffer_from_host.drvbuf.client_context;
--              msg_context = lookup_msg_context(instance, handle);
--
--              if (!msg_context) {
--                      pr_err("drvbuf.client_context(%u) is invalid\n",
--                             handle);
--                      return;
--              }
--      } else {
--              pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
--              return;
--      }
--
--      msg_context->u.bulk.mmal_flags =
--                              msg->u.buffer_from_host.buffer_header.flags;
--
--      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
--              /* message reception had an error */
--              pr_warn("error %d in reply\n", msg->h.status);
--
--              msg_context->u.bulk.status = msg->h.status;
--
--      } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
--              /* empty buffer */
--              if (msg->u.buffer_from_host.buffer_header.flags &
--                  MMAL_BUFFER_HEADER_FLAG_EOS) {
--                      msg_context->u.bulk.status =
--                          bulk_receive(instance, msg, msg_context);
--                      if (msg_context->u.bulk.status == 0)
--                              return; /* successful bulk submission, bulk
--                                       * completion will trigger callback
--                                       */
--              } else {
--                      /* do callback with empty buffer - not EOS though */
--                      msg_context->u.bulk.status = 0;
--                      msg_context->u.bulk.buffer_used = 0;
--              }
--      } else if (msg->u.buffer_from_host.payload_in_message == 0) {
--              /* data is not in message, queue a bulk receive */
--              msg_context->u.bulk.status =
--                  bulk_receive(instance, msg, msg_context);
--              if (msg_context->u.bulk.status == 0)
--                      return; /* successful bulk submission, bulk
--                               * completion will trigger callback
--                               */
--
--              /* failed to submit buffer, this will end badly */
--              pr_err("error %d on bulk submission\n",
--                     msg_context->u.bulk.status);
--
--      } else if (msg->u.buffer_from_host.payload_in_message <=
--                 MMAL_VC_SHORT_DATA) {
--              /* data payload within message */
--              msg_context->u.bulk.status = inline_receive(instance, msg,
--                                                          msg_context);
--      } else {
--              pr_err("message with invalid short payload\n");
--
--              /* signal error */
--              msg_context->u.bulk.status = -EINVAL;
--              msg_context->u.bulk.buffer_used =
--                  msg->u.buffer_from_host.payload_in_message;
--      }
--
--      /* schedule the port callback */
--      schedule_work(&msg_context->u.bulk.work);
--}
--
--static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
--                          struct mmal_msg_context *msg_context)
--{
--      msg_context->u.bulk.status = 0;
--
--      /* schedule the port callback */
--      schedule_work(&msg_context->u.bulk.work);
--}
--
--static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
--                        struct mmal_msg_context *msg_context)
--{
--      pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
--
--      msg_context->u.bulk.status = -EINTR;
--
--      schedule_work(&msg_context->u.bulk.work);
--}
--
--/* incoming event service callback */
--static void service_callback(void *param,
--                           const VCHI_CALLBACK_REASON_T reason,
--                           void *bulk_ctx)
--{
--      struct vchiq_mmal_instance *instance = param;
--      int status;
--      u32 msg_len;
--      struct mmal_msg *msg;
--      VCHI_HELD_MSG_T msg_handle;
--      struct mmal_msg_context *msg_context;
--
--      if (!instance) {
--              pr_err("Message callback passed NULL instance\n");
--              return;
--      }
--
--      switch (reason) {
--      case VCHI_CALLBACK_MSG_AVAILABLE:
--              status = vchi_msg_hold(instance->handle, (void **)&msg,
--                                     &msg_len, VCHI_FLAGS_NONE, &msg_handle);
--              if (status) {
--                      pr_err("Unable to dequeue a message (%d)\n", status);
--                      break;
--              }
--
--              DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
--
--              /* handling is different for buffer messages */
--              switch (msg->h.type) {
--              case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
--                      vchi_held_msg_release(&msg_handle);
--                      break;
--
--              case MMAL_MSG_TYPE_EVENT_TO_HOST:
--                      event_to_host_cb(instance, msg, msg_len);
--                      vchi_held_msg_release(&msg_handle);
--
--                      break;
--
--              case MMAL_MSG_TYPE_BUFFER_TO_HOST:
--                      buffer_to_host_cb(instance, msg, msg_len);
--                      vchi_held_msg_release(&msg_handle);
--                      break;
--
--              default:
--                      /* messages dependent on header context to complete */
--                      if (!msg->h.context) {
--                              pr_err("received message context was null!\n");
--                              vchi_held_msg_release(&msg_handle);
--                              break;
--                      }
--
--                      msg_context = lookup_msg_context(instance,
--                                                       msg->h.context);
--                      if (!msg_context) {
--                              pr_err("received invalid message context %u!\n",
--                                     msg->h.context);
--                              vchi_held_msg_release(&msg_handle);
--                              break;
--                      }
--
--                      /* fill in context values */
--                      msg_context->u.sync.msg_handle = msg_handle;
--                      msg_context->u.sync.msg = msg;
--                      msg_context->u.sync.msg_len = msg_len;
--
--                      /* todo: should this check (completion_done()
--                       * == 1) for no one waiting? or do we need a
--                       * flag to tell us the completion has been
--                       * interrupted so we can free the message and
--                       * its context. This probably also solves the
--                       * message arriving after interruption todo
--                       * below
--                       */
--
--                      /* complete message so caller knows it happened */
--                      complete(&msg_context->u.sync.cmplt);
--                      break;
--              }
--
--              break;
--
--      case VCHI_CALLBACK_BULK_RECEIVED:
--              bulk_receive_cb(instance, bulk_ctx);
--              break;
--
--      case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
--              bulk_abort_cb(instance, bulk_ctx);
--              break;
--
--      case VCHI_CALLBACK_SERVICE_CLOSED:
--              /* TODO: consider if this requires action if received when
--               * driver is not explicitly closing the service
--               */
--              break;
--
--      default:
--              pr_err("Received unhandled message reason %d\n", reason);
--              break;
--      }
--}
--
--static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
--                                   struct mmal_msg *msg,
--                                   unsigned int payload_len,
--                                   struct mmal_msg **msg_out,
--                                   VCHI_HELD_MSG_T *msg_handle_out)
--{
--      struct mmal_msg_context *msg_context;
--      int ret;
--      unsigned long timeout;
--
--      /* payload size must not cause message to exceed max size */
--      if (payload_len >
--          (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
--              pr_err("payload length %d exceeds max:%d\n", payload_len,
--                     (int)(MMAL_MSG_MAX_SIZE -
--                          sizeof(struct mmal_msg_header)));
--              return -EINVAL;
--      }
--
--      msg_context = get_msg_context(instance);
--      if (IS_ERR(msg_context))
--              return PTR_ERR(msg_context);
--
--      init_completion(&msg_context->u.sync.cmplt);
--
--      msg->h.magic = MMAL_MAGIC;
--      msg->h.context = msg_context->handle;
--      msg->h.status = 0;
--
--      DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
--                   ">>> sync message");
--
--      vchi_service_use(instance->handle);
--
--      ret = vchi_queue_kernel_message(instance->handle,
--                                      msg,
--                                      sizeof(struct mmal_msg_header) +
--                                      payload_len);
--
--      vchi_service_release(instance->handle);
--
--      if (ret) {
--              pr_err("error %d queuing message\n", ret);
--              release_msg_context(msg_context);
--              return ret;
--      }
--
--      timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
--                                            3 * HZ);
--      if (timeout == 0) {
--              pr_err("timed out waiting for sync completion\n");
--              ret = -ETIME;
--              /* todo: what happens if the message arrives after aborting */
--              release_msg_context(msg_context);
--              return ret;
--      }
--
--      *msg_out = msg_context->u.sync.msg;
--      *msg_handle_out = msg_context->u.sync.msg_handle;
--      release_msg_context(msg_context);
--
--      return 0;
--}
--
--static void dump_port_info(struct vchiq_mmal_port *port)
--{
--      pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
--
--      pr_debug("buffer minimum num:%d size:%d align:%d\n",
--               port->minimum_buffer.num,
--               port->minimum_buffer.size, port->minimum_buffer.alignment);
--
--      pr_debug("buffer recommended num:%d size:%d align:%d\n",
--               port->recommended_buffer.num,
--               port->recommended_buffer.size,
--               port->recommended_buffer.alignment);
--
--      pr_debug("buffer current values num:%d size:%d align:%d\n",
--               port->current_buffer.num,
--               port->current_buffer.size, port->current_buffer.alignment);
--
--      pr_debug("elementary stream: type:%d encoding:0x%x variant:0x%x\n",
--               port->format.type,
--               port->format.encoding, port->format.encoding_variant);
--
--      pr_debug("                  bitrate:%d flags:0x%x\n",
--               port->format.bitrate, port->format.flags);
--
--      if (port->format.type == MMAL_ES_TYPE_VIDEO) {
--              pr_debug
--                  ("es video format: width:%d height:%d colourspace:0x%x\n",
--                   port->es.video.width, port->es.video.height,
--                   port->es.video.color_space);
--
--              pr_debug("               : crop xywh %d,%d,%d,%d\n",
--                       port->es.video.crop.x,
--                       port->es.video.crop.y,
--                       port->es.video.crop.width, port->es.video.crop.height);
--              pr_debug("               : framerate %d/%d  aspect %d/%d\n",
--                       port->es.video.frame_rate.num,
--                       port->es.video.frame_rate.den,
--                       port->es.video.par.num, port->es.video.par.den);
--      }
--}
--
--static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
--{
--      /* todo do readonly fields need setting at all? */
--      p->type = port->type;
--      p->index = port->index;
--      p->index_all = 0;
--      p->is_enabled = port->enabled;
--      p->buffer_num_min = port->minimum_buffer.num;
--      p->buffer_size_min = port->minimum_buffer.size;
--      p->buffer_alignment_min = port->minimum_buffer.alignment;
--      p->buffer_num_recommended = port->recommended_buffer.num;
--      p->buffer_size_recommended = port->recommended_buffer.size;
--
--      /* only three writable fields in a port */
--      p->buffer_num = port->current_buffer.num;
--      p->buffer_size = port->current_buffer.size;
--      p->userdata = (u32)(unsigned long)port;
--}
--
--static int port_info_set(struct vchiq_mmal_instance *instance,
--                       struct vchiq_mmal_port *port)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      pr_debug("setting port info port %p\n", port);
--      if (!port)
--              return -1;
--      dump_port_info(port);
--
--      m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
--
--      m.u.port_info_set.component_handle = port->component->handle;
--      m.u.port_info_set.port_type = port->type;
--      m.u.port_info_set.port_index = port->index;
--
--      port_to_mmal_msg(port, &m.u.port_info_set.port);
--
--      /* elementary stream format setup */
--      m.u.port_info_set.format.type = port->format.type;
--      m.u.port_info_set.format.encoding = port->format.encoding;
--      m.u.port_info_set.format.encoding_variant =
--          port->format.encoding_variant;
--      m.u.port_info_set.format.bitrate = port->format.bitrate;
--      m.u.port_info_set.format.flags = port->format.flags;
--
--      memcpy(&m.u.port_info_set.es, &port->es,
--             sizeof(union mmal_es_specific_format));
--
--      m.u.port_info_set.format.extradata_size = port->format.extradata_size;
--      memcpy(&m.u.port_info_set.extradata, port->format.extradata,
--             port->format.extradata_size);
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.port_info_set),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      /* return operation status */
--      ret = -rmsg->u.port_info_get_reply.status;
--
--      pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
--               port->component->handle, port->handle);
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* use port info get message to retrieve port information */
--static int port_info_get(struct vchiq_mmal_instance *instance,
--                       struct vchiq_mmal_port *port)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      /* port info time */
--      m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
--      m.u.port_info_get.component_handle = port->component->handle;
--      m.u.port_info_get.port_type = port->type;
--      m.u.port_info_get.index = port->index;
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.port_info_get),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      /* return operation status */
--      ret = -rmsg->u.port_info_get_reply.status;
--      if (ret != MMAL_MSG_STATUS_SUCCESS)
--              goto release_msg;
--
--      if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
--              port->enabled = false;
--      else
--              port->enabled = true;
--
--      /* copy the values out of the message */
--      port->handle = rmsg->u.port_info_get_reply.port_handle;
--
--      /* port type and index cached to use on port info set because
--       * it does not use a port handle
--       */
--      port->type = rmsg->u.port_info_get_reply.port_type;
--      port->index = rmsg->u.port_info_get_reply.port_index;
--
--      port->minimum_buffer.num =
--          rmsg->u.port_info_get_reply.port.buffer_num_min;
--      port->minimum_buffer.size =
--          rmsg->u.port_info_get_reply.port.buffer_size_min;
--      port->minimum_buffer.alignment =
--          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
--
--      port->recommended_buffer.alignment =
--          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
--      port->recommended_buffer.num =
--          rmsg->u.port_info_get_reply.port.buffer_num_recommended;
--
--      port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
--      port->current_buffer.size =
--          rmsg->u.port_info_get_reply.port.buffer_size;
--
--      /* stream format */
--      port->format.type = rmsg->u.port_info_get_reply.format.type;
--      port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
--      port->format.encoding_variant =
--          rmsg->u.port_info_get_reply.format.encoding_variant;
--      port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
--      port->format.flags = rmsg->u.port_info_get_reply.format.flags;
--
--      /* elementary stream format */
--      memcpy(&port->es,
--             &rmsg->u.port_info_get_reply.es,
--             sizeof(union mmal_es_specific_format));
--      port->format.es = &port->es;
--
--      port->format.extradata_size =
--          rmsg->u.port_info_get_reply.format.extradata_size;
--      memcpy(port->format.extradata,
--             rmsg->u.port_info_get_reply.extradata,
--             port->format.extradata_size);
--
--      pr_debug("received port info\n");
--      dump_port_info(port);
--
--release_msg:
--
--      pr_debug("%s:result:%d component:0x%x port:%d\n",
--               __func__, ret, port->component->handle, port->handle);
--
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* create comonent on vc */
--static int create_component(struct vchiq_mmal_instance *instance,
--                          struct vchiq_mmal_component *component,
--                          const char *name)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      /* build component create message */
--      m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
--      m.u.component_create.client_component = (u32)(unsigned long)component;
--      strncpy(m.u.component_create.name, name,
--              sizeof(m.u.component_create.name));
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.component_create),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != m.h.type) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.component_create_reply.status;
--      if (ret != MMAL_MSG_STATUS_SUCCESS)
--              goto release_msg;
--
--      /* a valid component response received */
--      component->handle = rmsg->u.component_create_reply.component_handle;
--      component->inputs = rmsg->u.component_create_reply.input_num;
--      component->outputs = rmsg->u.component_create_reply.output_num;
--      component->clocks = rmsg->u.component_create_reply.clock_num;
--
--      pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
--               component->handle,
--               component->inputs, component->outputs, component->clocks);
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* destroys a component on vc */
--static int destroy_component(struct vchiq_mmal_instance *instance,
--                           struct vchiq_mmal_component *component)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
--      m.u.component_destroy.component_handle = component->handle;
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.component_destroy),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != m.h.type) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.component_destroy_reply.status;
--
--release_msg:
--
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* enable a component on vc */
--static int enable_component(struct vchiq_mmal_instance *instance,
--                          struct vchiq_mmal_component *component)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
--      m.u.component_enable.component_handle = component->handle;
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.component_enable),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != m.h.type) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.component_enable_reply.status;
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* disable a component on vc */
--static int disable_component(struct vchiq_mmal_instance *instance,
--                           struct vchiq_mmal_component *component)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
--      m.u.component_disable.component_handle = component->handle;
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.component_disable),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != m.h.type) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.component_disable_reply.status;
--
--release_msg:
--
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* get version of mmal implementation */
--static int get_version(struct vchiq_mmal_instance *instance,
--                     u32 *major_out, u32 *minor_out)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_GET_VERSION;
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.version),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != m.h.type) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      *major_out = rmsg->u.version.major;
--      *minor_out = rmsg->u.version.minor;
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* do a port action with a port as a parameter */
--static int port_action_port(struct vchiq_mmal_instance *instance,
--                          struct vchiq_mmal_port *port,
--                          enum mmal_msg_port_action_type action_type)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
--      m.u.port_action_port.component_handle = port->component->handle;
--      m.u.port_action_port.port_handle = port->handle;
--      m.u.port_action_port.action = action_type;
--
--      port_to_mmal_msg(port, &m.u.port_action_port.port);
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.port_action_port),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.port_action_reply.status;
--
--      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
--               __func__,
--               ret, port->component->handle, port->handle,
--               port_action_type_names[action_type], action_type);
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* do a port action with handles as parameters */
--static int port_action_handle(struct vchiq_mmal_instance *instance,
--                            struct vchiq_mmal_port *port,
--                            enum mmal_msg_port_action_type action_type,
--                            u32 connect_component_handle,
--                            u32 connect_port_handle)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
--
--      m.u.port_action_handle.component_handle = port->component->handle;
--      m.u.port_action_handle.port_handle = port->handle;
--      m.u.port_action_handle.action = action_type;
--
--      m.u.port_action_handle.connect_component_handle =
--          connect_component_handle;
--      m.u.port_action_handle.connect_port_handle = connect_port_handle;
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(m.u.port_action_handle),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.port_action_reply.status;
--
--      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n",
--               __func__,
--               ret, port->component->handle, port->handle,
--               port_action_type_names[action_type],
--               action_type, connect_component_handle, connect_port_handle);
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--static int port_parameter_set(struct vchiq_mmal_instance *instance,
--                            struct vchiq_mmal_port *port,
--                            u32 parameter_id, void *value, u32 value_size)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
--
--      m.u.port_parameter_set.component_handle = port->component->handle;
--      m.u.port_parameter_set.port_handle = port->handle;
--      m.u.port_parameter_set.id = parameter_id;
--      m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
--      memcpy(&m.u.port_parameter_set.value, value, value_size);
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      (4 * sizeof(u32)) + value_size,
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
--              /* got an unexpected message type in reply */
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.port_parameter_set_reply.status;
--
--      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
--               __func__,
--               ret, port->component->handle, port->handle, parameter_id);
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--static int port_parameter_get(struct vchiq_mmal_instance *instance,
--                            struct vchiq_mmal_port *port,
--                            u32 parameter_id, void *value, u32 *value_size)
--{
--      int ret;
--      struct mmal_msg m;
--      struct mmal_msg *rmsg;
--      VCHI_HELD_MSG_T rmsg_handle;
--
--      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
--
--      m.u.port_parameter_get.component_handle = port->component->handle;
--      m.u.port_parameter_get.port_handle = port->handle;
--      m.u.port_parameter_get.id = parameter_id;
--      m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
--
--      ret = send_synchronous_mmal_msg(instance, &m,
--                                      sizeof(struct
--                                             mmal_msg_port_parameter_get),
--                                      &rmsg, &rmsg_handle);
--      if (ret)
--              return ret;
--
--      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
--              /* got an unexpected message type in reply */
--              pr_err("Incorrect reply type %d\n", rmsg->h.type);
--              ret = -EINVAL;
--              goto release_msg;
--      }
--
--      ret = -rmsg->u.port_parameter_get_reply.status;
--      /* port_parameter_get_reply.size includes the header,
--       * whilst *value_size doesn't.
--       */
--      rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32));
--
--      if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) {
--              /* Copy only as much as we have space for
--               * but report true size of parameter
--               */
--              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
--                     *value_size);
--              *value_size = rmsg->u.port_parameter_get_reply.size;
--      } else {
--              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
--                     rmsg->u.port_parameter_get_reply.size);
--      }
--
--      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
--               ret, port->component->handle, port->handle, parameter_id);
--
--release_msg:
--      vchi_held_msg_release(&rmsg_handle);
--
--      return ret;
--}
--
--/* disables a port and drains buffers from it */
--static int port_disable(struct vchiq_mmal_instance *instance,
--                      struct vchiq_mmal_port *port)
--{
--      int ret;
--      struct list_head *q, *buf_head;
--      unsigned long flags = 0;
--
--      if (!port->enabled)
--              return 0;
--
--      port->enabled = false;
--
--      ret = port_action_port(instance, port,
--                             MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
--      if (ret == 0) {
--              /*
--               * Drain all queued buffers on port. This should only
--               * apply to buffers that have been queued before the port
--               * has been enabled. If the port has been enabled and buffers
--               * passed, then the buffers should have been removed from this
--               * list, and we should get the relevant callbacks via VCHIQ
--               * to release the buffers.
--               */
--              spin_lock_irqsave(&port->slock, flags);
--
--              list_for_each_safe(buf_head, q, &port->buffers) {
--                      struct mmal_buffer *mmalbuf;
--
--                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
--                                           list);
--                      list_del(buf_head);
--                      if (port->buffer_cb)
--                              port->buffer_cb(instance,
--                                              port, 0, mmalbuf, 0, 0,
--                                              MMAL_TIME_UNKNOWN,
--                                              MMAL_TIME_UNKNOWN);
--              }
--
--              spin_unlock_irqrestore(&port->slock, flags);
--
--              ret = port_info_get(instance, port);
--      }
--
--      return ret;
--}
--
--/* enable a port */
--static int port_enable(struct vchiq_mmal_instance *instance,
--                     struct vchiq_mmal_port *port)
--{
--      unsigned int hdr_count;
--      struct list_head *q, *buf_head;
--      int ret;
--
--      if (port->enabled)
--              return 0;
--
--      ret = port_action_port(instance, port,
--                             MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
--      if (ret)
--              goto done;
--
--      port->enabled = true;
--
--      if (port->buffer_cb) {
--              /* send buffer headers to videocore */
--              hdr_count = 1;
--              list_for_each_safe(buf_head, q, &port->buffers) {
--                      struct mmal_buffer *mmalbuf;
--
--                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
--                                           list);
--                      ret = buffer_from_host(instance, port, mmalbuf);
--                      if (ret)
--                              goto done;
--
--                      list_del(buf_head);
--                      hdr_count++;
--                      if (hdr_count > port->current_buffer.num)
--                              break;
--              }
--      }
--
--      ret = port_info_get(instance, port);
--
--done:
--      return ret;
--}
--
--/* ------------------------------------------------------------------
-- * Exported API
-- *------------------------------------------------------------------
-- */
--
--int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
--                             struct vchiq_mmal_port *port)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      ret = port_info_set(instance, port);
--      if (ret)
--              goto release_unlock;
--
--      /* read what has actually been set */
--      ret = port_info_get(instance, port);
--
--release_unlock:
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
--                                struct vchiq_mmal_port *port,
--                                u32 parameter, void *value, u32 value_size)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      ret = port_parameter_set(instance, port, parameter, value, value_size);
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
--                                struct vchiq_mmal_port *port,
--                                u32 parameter, void *value, u32 *value_size)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      ret = port_parameter_get(instance, port, parameter, value, value_size);
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--/* enable a port
-- *
-- * enables a port and queues buffers for satisfying callbacks if we
-- * provide a callback handler
-- */
--int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
--                         struct vchiq_mmal_port *port,
--                         vchiq_mmal_buffer_cb buffer_cb)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      /* already enabled - noop */
--      if (port->enabled) {
--              ret = 0;
--              goto unlock;
--      }
--
--      port->buffer_cb = buffer_cb;
--
--      ret = port_enable(instance, port);
--
--unlock:
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
--                          struct vchiq_mmal_port *port)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      if (!port->enabled) {
--              mutex_unlock(&instance->vchiq_mutex);
--              return 0;
--      }
--
--      ret = port_disable(instance, port);
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--/* ports will be connected in a tunneled manner so data buffers
-- * are not handled by client.
-- */
--int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
--                                 struct vchiq_mmal_port *src,
--                                 struct vchiq_mmal_port *dst)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      /* disconnect ports if connected */
--      if (src->connected) {
--              ret = port_disable(instance, src);
--              if (ret) {
--                      pr_err("failed disabling src port(%d)\n", ret);
--                      goto release_unlock;
--              }
--
--              /* do not need to disable the destination port as they
--               * are connected and it is done automatically
--               */
--
--              ret = port_action_handle(instance, src,
--                                       MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
--                                       src->connected->component->handle,
--                                       src->connected->handle);
--              if (ret < 0) {
--                      pr_err("failed disconnecting src port\n");
--                      goto release_unlock;
--              }
--              src->connected->enabled = false;
--              src->connected = NULL;
--      }
--
--      if (!dst) {
--              /* do not make new connection */
--              ret = 0;
--              pr_debug("not making new connection\n");
--              goto release_unlock;
--      }
--
--      /* copy src port format to dst */
--      dst->format.encoding = src->format.encoding;
--      dst->es.video.width = src->es.video.width;
--      dst->es.video.height = src->es.video.height;
--      dst->es.video.crop.x = src->es.video.crop.x;
--      dst->es.video.crop.y = src->es.video.crop.y;
--      dst->es.video.crop.width = src->es.video.crop.width;
--      dst->es.video.crop.height = src->es.video.crop.height;
--      dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
--      dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
--
--      /* set new format */
--      ret = port_info_set(instance, dst);
--      if (ret) {
--              pr_debug("setting port info failed\n");
--              goto release_unlock;
--      }
--
--      /* read what has actually been set */
--      ret = port_info_get(instance, dst);
--      if (ret) {
--              pr_debug("read back port info failed\n");
--              goto release_unlock;
--      }
--
--      /* connect two ports together */
--      ret = port_action_handle(instance, src,
--                               MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
--                               dst->component->handle, dst->handle);
--      if (ret < 0) {
--              pr_debug("connecting port %d:%d to %d:%d failed\n",
--                       src->component->handle, src->handle,
--                       dst->component->handle, dst->handle);
--              goto release_unlock;
--      }
--      src->connected = dst;
--
--release_unlock:
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
--                           struct vchiq_mmal_port *port,
--                           struct mmal_buffer *buffer)
--{
--      unsigned long flags = 0;
--      int ret;
--
--      ret = buffer_from_host(instance, port, buffer);
--      if (ret == -EINVAL) {
--              /* Port is disabled. Queue for when it is enabled. */
--              spin_lock_irqsave(&port->slock, flags);
--              list_add_tail(&buffer->list, &port->buffers);
--              spin_unlock_irqrestore(&port->slock, flags);
--      }
--
--      return 0;
--}
--
--int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
--                        struct mmal_buffer *buf)
--{
--      struct mmal_msg_context *msg_context = get_msg_context(instance);
--
--      if (IS_ERR(msg_context))
--              return (PTR_ERR(msg_context));
--
--      buf->msg_context = msg_context;
--      return 0;
--}
--
--int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
--{
--      struct mmal_msg_context *msg_context = buf->msg_context;
--
--      if (msg_context)
--              release_msg_context(msg_context);
--      buf->msg_context = NULL;
--
--      return 0;
--}
--
--/* Initialise a mmal component and its ports
-- *
-- */
--int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
--                            const char *name,
--                            struct vchiq_mmal_component **component_out)
--{
--      int ret;
--      int idx;                /* port index */
--      struct vchiq_mmal_component *component;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
--              ret = -EINVAL;  /* todo is this correct error? */
--              goto unlock;
--      }
--
--      component = &instance->component[instance->component_idx];
--
--      ret = create_component(instance, component, name);
--      if (ret < 0) {
--              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
--                     __func__, ret);
--              goto unlock;
--      }
--
--      /* ports info needs gathering */
--      component->control.type = MMAL_PORT_TYPE_CONTROL;
--      component->control.index = 0;
--      component->control.component = component;
--      spin_lock_init(&component->control.slock);
--      INIT_LIST_HEAD(&component->control.buffers);
--      ret = port_info_get(instance, &component->control);
--      if (ret < 0)
--              goto release_component;
--
--      for (idx = 0; idx < component->inputs; idx++) {
--              component->input[idx].type = MMAL_PORT_TYPE_INPUT;
--              component->input[idx].index = idx;
--              component->input[idx].component = component;
--              spin_lock_init(&component->input[idx].slock);
--              INIT_LIST_HEAD(&component->input[idx].buffers);
--              ret = port_info_get(instance, &component->input[idx]);
--              if (ret < 0)
--                      goto release_component;
--      }
--
--      for (idx = 0; idx < component->outputs; idx++) {
--              component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
--              component->output[idx].index = idx;
--              component->output[idx].component = component;
--              spin_lock_init(&component->output[idx].slock);
--              INIT_LIST_HEAD(&component->output[idx].buffers);
--              ret = port_info_get(instance, &component->output[idx]);
--              if (ret < 0)
--                      goto release_component;
--      }
--
--      for (idx = 0; idx < component->clocks; idx++) {
--              component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
--              component->clock[idx].index = idx;
--              component->clock[idx].component = component;
--              spin_lock_init(&component->clock[idx].slock);
--              INIT_LIST_HEAD(&component->clock[idx].buffers);
--              ret = port_info_get(instance, &component->clock[idx]);
--              if (ret < 0)
--                      goto release_component;
--      }
--
--      instance->component_idx++;
--
--      *component_out = component;
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return 0;
--
--release_component:
--      destroy_component(instance, component);
--unlock:
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--/*
-- * cause a mmal component to be destroyed
-- */
--int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
--                                struct vchiq_mmal_component *component)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      if (component->enabled)
--              ret = disable_component(instance, component);
--
--      ret = destroy_component(instance, component);
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--/*
-- * cause a mmal component to be enabled
-- */
--int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
--                              struct vchiq_mmal_component *component)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      if (component->enabled) {
--              mutex_unlock(&instance->vchiq_mutex);
--              return 0;
--      }
--
--      ret = enable_component(instance, component);
--      if (ret == 0)
--              component->enabled = true;
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--/*
-- * cause a mmal component to be enabled
-- */
--int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
--                               struct vchiq_mmal_component *component)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      if (!component->enabled) {
--              mutex_unlock(&instance->vchiq_mutex);
--              return 0;
--      }
--
--      ret = disable_component(instance, component);
--      if (ret == 0)
--              component->enabled = false;
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
--                     u32 *major_out, u32 *minor_out)
--{
--      int ret;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      ret = get_version(instance, major_out, minor_out);
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      return ret;
--}
--
--int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
--{
--      int status = 0;
--
--      if (!instance)
--              return -EINVAL;
--
--      if (mutex_lock_interruptible(&instance->vchiq_mutex))
--              return -EINTR;
--
--      vchi_service_use(instance->handle);
--
--      status = vchi_service_close(instance->handle);
--      if (status != 0)
--              pr_err("mmal-vchiq: VCHIQ close failed\n");
--
--      mutex_unlock(&instance->vchiq_mutex);
--
--      flush_workqueue(instance->bulk_wq);
--      destroy_workqueue(instance->bulk_wq);
--
--      vfree(instance->bulk_scratch);
--
--      idr_destroy(&instance->context_map);
--
--      kfree(instance);
--
--      return status;
--}
--
--int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
--{
--      int status;
--      struct vchiq_mmal_instance *instance;
--      static VCHI_CONNECTION_T *vchi_connection;
--      static VCHI_INSTANCE_T vchi_instance;
--      SERVICE_CREATION_T params = {
--              .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
--              .service_id             = VC_MMAL_SERVER_NAME,
--              .connection             = vchi_connection,
--              .rx_fifo_size           = 0,
--              .tx_fifo_size           = 0,
--              .callback               = service_callback,
--              .callback_param         = NULL,
--              .want_unaligned_bulk_rx = 1,
--              .want_unaligned_bulk_tx = 1,
--              .want_crc               = 0
--      };
--
--      /* compile time checks to ensure structure size as they are
--       * directly (de)serialised from memory.
--       */
--
--      /* ensure the header structure has packed to the correct size */
--      BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
--
--      /* ensure message structure does not exceed maximum length */
--      BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
--
--      /* mmal port struct is correct size */
--      BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
--
--      /* create a vchi instance */
--      status = vchi_initialise(&vchi_instance);
--      if (status) {
--              pr_err("Failed to initialise VCHI instance (status=%d)\n",
--                     status);
--              return -EIO;
--      }
--
--      status = vchi_connect(NULL, 0, vchi_instance);
--      if (status) {
--              pr_err("Failed to connect VCHI instance (status=%d)\n", status);
--              return -EIO;
--      }
--
--      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
--
--      if (!instance)
--              return -ENOMEM;
--
--      mutex_init(&instance->vchiq_mutex);
--
--      instance->bulk_scratch = vmalloc(PAGE_SIZE);
--
--      mutex_init(&instance->context_map_lock);
--      idr_init_base(&instance->context_map, 1);
--
--      params.callback_param = instance;
--
--      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
--                                                  WQ_MEM_RECLAIM);
--      if (!instance->bulk_wq)
--              goto err_free;
--
--      status = vchi_service_open(vchi_instance, &params, &instance->handle);
--      if (status) {
--              pr_err("Failed to open VCHI service connection (status=%d)\n",
--                     status);
--              goto err_close_services;
--      }
--
--      vchi_service_release(instance->handle);
--
--      *out_instance = instance;
--
--      return 0;
--
--err_close_services:
--      vchi_service_close(instance->handle);
--      destroy_workqueue(instance->bulk_wq);
--err_free:
--      vfree(instance->bulk_scratch);
--      kfree(instance);
--      return -ENODEV;
--}
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -0,0 +1,1921 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ *
-+ * V4L2 driver MMAL vchiq interface code
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/mutex.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/completion.h>
-+#include <linux/vmalloc.h>
-+#include <asm/cacheflush.h>
-+#include <media/videobuf2-vmalloc.h>
-+
-+#include "mmal-common.h"
-+#include "mmal-vchiq.h"
-+#include "mmal-msg.h"
-+
-+#define USE_VCHIQ_ARM
-+#include "interface/vchi/vchi.h"
-+
-+MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface");
-+MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("0.0.1");
-+
-+/* maximum number of components supported */
-+#define VCHIQ_MMAL_MAX_COMPONENTS 4
-+
-+/*#define FULL_MSG_DUMP 1*/
-+
-+#ifdef DEBUG
-+static const char *const msg_type_names[] = {
-+      "UNKNOWN",
-+      "QUIT",
-+      "SERVICE_CLOSED",
-+      "GET_VERSION",
-+      "COMPONENT_CREATE",
-+      "COMPONENT_DESTROY",
-+      "COMPONENT_ENABLE",
-+      "COMPONENT_DISABLE",
-+      "PORT_INFO_GET",
-+      "PORT_INFO_SET",
-+      "PORT_ACTION",
-+      "BUFFER_FROM_HOST",
-+      "BUFFER_TO_HOST",
-+      "GET_STATS",
-+      "PORT_PARAMETER_SET",
-+      "PORT_PARAMETER_GET",
-+      "EVENT_TO_HOST",
-+      "GET_CORE_STATS_FOR_PORT",
-+      "OPAQUE_ALLOCATOR",
-+      "CONSUME_MEM",
-+      "LMK",
-+      "OPAQUE_ALLOCATOR_DESC",
-+      "DRM_GET_LHS32",
-+      "DRM_GET_TIME",
-+      "BUFFER_FROM_HOST_ZEROLEN",
-+      "PORT_FLUSH",
-+      "HOST_LOG",
-+};
-+#endif
-+
-+static const char *const port_action_type_names[] = {
-+      "UNKNOWN",
-+      "ENABLE",
-+      "DISABLE",
-+      "FLUSH",
-+      "CONNECT",
-+      "DISCONNECT",
-+      "SET_REQUIREMENTS",
-+};
-+
-+#if defined(DEBUG)
-+#if defined(FULL_MSG_DUMP)
-+#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
-+      do {                                                            \
-+              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
-+                       msg_type_names[(MSG)->h.type],                 \
-+                       (MSG)->h.type, (MSG_LEN));                     \
-+              print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
-+                             16, 4, (MSG),                            \
-+                             sizeof(struct mmal_msg_header), 1);      \
-+              print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
-+                             16, 4,                                   \
-+                             ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
-+                             (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
-+      } while (0)
-+#else
-+#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
-+      {                                                               \
-+              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
-+                       msg_type_names[(MSG)->h.type],                 \
-+                       (MSG)->h.type, (MSG_LEN));                     \
-+      }
-+#endif
-+#else
-+#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
-+#endif
-+
-+struct vchiq_mmal_instance;
-+
-+/* normal message context */
-+struct mmal_msg_context {
-+      struct vchiq_mmal_instance *instance;
-+
-+      /* Index in the context_map idr so that we can find the
-+       * mmal_msg_context again when servicing the VCHI reply.
-+       */
-+      int handle;
-+
-+      union {
-+              struct {
-+                      /* work struct for buffer_cb callback */
-+                      struct work_struct work;
-+                      /* work struct for deferred callback */
-+                      struct work_struct buffer_to_host_work;
-+                      /* mmal instance */
-+                      struct vchiq_mmal_instance *instance;
-+                      /* mmal port */
-+                      struct vchiq_mmal_port *port;
-+                      /* actual buffer used to store bulk reply */
-+                      struct mmal_buffer *buffer;
-+                      /* amount of buffer used */
-+                      unsigned long buffer_used;
-+                      /* MMAL buffer flags */
-+                      u32 mmal_flags;
-+                      /* Presentation and Decode timestamps */
-+                      s64 pts;
-+                      s64 dts;
-+
-+                      int status;     /* context status */
-+
-+              } bulk;         /* bulk data */
-+
-+              struct {
-+                      /* message handle to release */
-+                      VCHI_HELD_MSG_T msg_handle;
-+                      /* pointer to received message */
-+                      struct mmal_msg *msg;
-+                      /* received message length */
-+                      u32 msg_len;
-+                      /* completion upon reply */
-+                      struct completion cmplt;
-+              } sync;         /* synchronous response */
-+      } u;
-+
-+};
-+
-+struct vchiq_mmal_instance {
-+      VCHI_SERVICE_HANDLE_T handle;
-+
-+      /* ensure serialised access to service */
-+      struct mutex vchiq_mutex;
-+
-+      /* vmalloc page to receive scratch bulk xfers into */
-+      void *bulk_scratch;
-+
-+      struct idr context_map;
-+      /* protect accesses to context_map */
-+      struct mutex context_map_lock;
-+
-+      /* component to use next */
-+      int component_idx;
-+      struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
-+
-+      /* ordered workqueue to process all bulk operations */
-+      struct workqueue_struct *bulk_wq;
-+};
-+
-+static struct mmal_msg_context *
-+get_msg_context(struct vchiq_mmal_instance *instance)
-+{
-+      struct mmal_msg_context *msg_context;
-+      int handle;
-+
-+      /* todo: should this be allocated from a pool to avoid kzalloc */
-+      msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
-+
-+      if (!msg_context)
-+              return ERR_PTR(-ENOMEM);
-+
-+      /* Create an ID that will be passed along with our message so
-+       * that when we service the VCHI reply, we can look up what
-+       * message is being replied to.
-+       */
-+      mutex_lock(&instance->context_map_lock);
-+      handle = idr_alloc(&instance->context_map, msg_context,
-+                         0, 0, GFP_KERNEL);
-+      mutex_unlock(&instance->context_map_lock);
-+
-+      if (handle < 0) {
-+              kfree(msg_context);
-+              return ERR_PTR(handle);
-+      }
-+
-+      msg_context->instance = instance;
-+      msg_context->handle = handle;
-+
-+      return msg_context;
-+}
-+
-+static struct mmal_msg_context *
-+lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
-+{
-+      return idr_find(&instance->context_map, handle);
-+}
-+
-+static void
-+release_msg_context(struct mmal_msg_context *msg_context)
-+{
-+      struct vchiq_mmal_instance *instance = msg_context->instance;
-+
-+      mutex_lock(&instance->context_map_lock);
-+      idr_remove(&instance->context_map, msg_context->handle);
-+      mutex_unlock(&instance->context_map_lock);
-+      kfree(msg_context);
-+}
-+
-+/* deals with receipt of event to host message */
-+static void event_to_host_cb(struct vchiq_mmal_instance *instance,
-+                           struct mmal_msg *msg, u32 msg_len)
-+{
-+      pr_debug("unhandled event\n");
-+      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
-+               msg->u.event_to_host.client_component,
-+               msg->u.event_to_host.port_type,
-+               msg->u.event_to_host.port_num,
-+               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
-+}
-+
-+/* workqueue scheduled callback
-+ *
-+ * we do this because it is important we do not call any other vchiq
-+ * sync calls from witin the message delivery thread
-+ */
-+static void buffer_work_cb(struct work_struct *work)
-+{
-+      struct mmal_msg_context *msg_context =
-+              container_of(work, struct mmal_msg_context, u.bulk.work);
-+
-+      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-+
-+      msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
-+                                          msg_context->u.bulk.port,
-+                                          msg_context->u.bulk.status,
-+                                          msg_context->u.bulk.buffer,
-+                                          msg_context->u.bulk.buffer_used,
-+                                          msg_context->u.bulk.mmal_flags,
-+                                          msg_context->u.bulk.dts,
-+                                          msg_context->u.bulk.pts);
-+}
-+
-+/* workqueue scheduled callback to handle receiving buffers
-+ *
-+ * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
-+ * If we block in the service_callback context then we can't process the
-+ * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
-+ * vchi_bulk_queue_receive() call to complete.
-+ */
-+static void buffer_to_host_work_cb(struct work_struct *work)
-+{
-+      struct mmal_msg_context *msg_context =
-+              container_of(work, struct mmal_msg_context,
-+                           u.bulk.buffer_to_host_work);
-+      struct vchiq_mmal_instance *instance = msg_context->instance;
-+      unsigned long len = msg_context->u.bulk.buffer_used;
-+      int ret;
-+
-+      if (!len)
-+              /* Dummy receive to ensure the buffers remain in order */
-+              len = 8;
-+      /* queue the bulk submission */
-+      vchi_service_use(instance->handle);
-+      ret = vchi_bulk_queue_receive(instance->handle,
-+                                    msg_context->u.bulk.buffer->buffer,
-+                                    /* Actual receive needs to be a multiple
-+                                     * of 4 bytes
-+                                     */
-+                                    (len + 3) & ~3,
-+                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
-+                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
-+                                    msg_context);
-+
-+      vchi_service_release(instance->handle);
-+
-+      if (ret != 0)
-+              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
-+                     __func__, msg_context, ret);
-+}
-+
-+/* enqueue a bulk receive for a given message context */
-+static int bulk_receive(struct vchiq_mmal_instance *instance,
-+                      struct mmal_msg *msg,
-+                      struct mmal_msg_context *msg_context)
-+{
-+      unsigned long rd_len;
-+
-+      rd_len = msg->u.buffer_from_host.buffer_header.length;
-+
-+      if (!msg_context->u.bulk.buffer) {
-+              pr_err("bulk.buffer not configured - error in buffer_from_host\n");
-+
-+              /* todo: this is a serious error, we should never have
-+               * committed a buffer_to_host operation to the mmal
-+               * port without the buffer to back it up (underflow
-+               * handling) and there is no obvious way to deal with
-+               * this - how is the mmal servie going to react when
-+               * we fail to do the xfer and reschedule a buffer when
-+               * it arrives? perhaps a starved flag to indicate a
-+               * waiting bulk receive?
-+               */
-+
-+              return -EINVAL;
-+      }
-+
-+      /* ensure we do not overrun the available buffer */
-+      if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
-+              rd_len = msg_context->u.bulk.buffer->buffer_size;
-+              pr_warn("short read as not enough receive buffer space\n");
-+              /* todo: is this the correct response, what happens to
-+               * the rest of the message data?
-+               */
-+      }
-+
-+      /* store length */
-+      msg_context->u.bulk.buffer_used = rd_len;
-+      msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
-+      msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
-+
-+      queue_work(msg_context->instance->bulk_wq,
-+                 &msg_context->u.bulk.buffer_to_host_work);
-+
-+      return 0;
-+}
-+
-+/* data in message, memcpy from packet into output buffer */
-+static int inline_receive(struct vchiq_mmal_instance *instance,
-+                        struct mmal_msg *msg,
-+                        struct mmal_msg_context *msg_context)
-+{
-+      memcpy(msg_context->u.bulk.buffer->buffer,
-+             msg->u.buffer_from_host.short_data,
-+             msg->u.buffer_from_host.payload_in_message);
-+
-+      msg_context->u.bulk.buffer_used =
-+          msg->u.buffer_from_host.payload_in_message;
-+
-+      return 0;
-+}
-+
-+/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
-+static int
-+buffer_from_host(struct vchiq_mmal_instance *instance,
-+               struct vchiq_mmal_port *port, struct mmal_buffer *buf)
-+{
-+      struct mmal_msg_context *msg_context;
-+      struct mmal_msg m;
-+      int ret;
-+
-+      if (!port->enabled)
-+              return -EINVAL;
-+
-+      pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
-+
-+      /* get context */
-+      if (!buf->msg_context) {
-+              pr_err("%s: msg_context not allocated, buf %p\n", __func__,
-+                     buf);
-+              return -EINVAL;
-+      }
-+      msg_context = buf->msg_context;
-+
-+      /* store bulk message context for when data arrives */
-+      msg_context->u.bulk.instance = instance;
-+      msg_context->u.bulk.port = port;
-+      msg_context->u.bulk.buffer = buf;
-+      msg_context->u.bulk.buffer_used = 0;
-+
-+      /* initialise work structure ready to schedule callback */
-+      INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
-+      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
-+                buffer_to_host_work_cb);
-+
-+      atomic_inc(&port->buffers_with_vpu);
-+
-+      /* prep the buffer from host message */
-+      memset(&m, 0xbc, sizeof(m));    /* just to make debug clearer */
-+
-+      m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
-+      m.h.magic = MMAL_MAGIC;
-+      m.h.context = msg_context->handle;
-+      m.h.status = 0;
-+
-+      /* drvbuf is our private data passed back */
-+      m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
-+      m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
-+      m.u.buffer_from_host.drvbuf.port_handle = port->handle;
-+      m.u.buffer_from_host.drvbuf.client_context = msg_context->handle;
-+
-+      /* buffer header */
-+      m.u.buffer_from_host.buffer_header.cmd = 0;
-+      m.u.buffer_from_host.buffer_header.data =
-+              (u32)(unsigned long)buf->buffer;
-+      m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
-+      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
-+      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
-+      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
-+      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
-+      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
-+
-+      /* clear buffer type sepecific data */
-+      memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
-+             sizeof(m.u.buffer_from_host.buffer_header_type_specific));
-+
-+      /* no payload in message */
-+      m.u.buffer_from_host.payload_in_message = 0;
-+
-+      vchi_service_use(instance->handle);
-+
-+      ret = vchi_queue_kernel_message(instance->handle,
-+                                      &m,
-+                                      sizeof(struct mmal_msg_header) +
-+                                      sizeof(m.u.buffer_from_host));
-+
-+      vchi_service_release(instance->handle);
-+
-+      return ret;
-+}
-+
-+/* deals with receipt of buffer to host message */
-+static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
-+                            struct mmal_msg *msg, u32 msg_len)
-+{
-+      struct mmal_msg_context *msg_context;
-+      u32 handle;
-+
-+      pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
-+               __func__, instance, msg, msg_len);
-+
-+      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
-+              handle = msg->u.buffer_from_host.drvbuf.client_context;
-+              msg_context = lookup_msg_context(instance, handle);
-+
-+              if (!msg_context) {
-+                      pr_err("drvbuf.client_context(%u) is invalid\n",
-+                             handle);
-+                      return;
-+              }
-+      } else {
-+              pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
-+              return;
-+      }
-+
-+      msg_context->u.bulk.mmal_flags =
-+                              msg->u.buffer_from_host.buffer_header.flags;
-+
-+      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
-+              /* message reception had an error */
-+              pr_warn("error %d in reply\n", msg->h.status);
-+
-+              msg_context->u.bulk.status = msg->h.status;
-+
-+      } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
-+              /* empty buffer */
-+              if (msg->u.buffer_from_host.buffer_header.flags &
-+                  MMAL_BUFFER_HEADER_FLAG_EOS) {
-+                      msg_context->u.bulk.status =
-+                          bulk_receive(instance, msg, msg_context);
-+                      if (msg_context->u.bulk.status == 0)
-+                              return; /* successful bulk submission, bulk
-+                                       * completion will trigger callback
-+                                       */
-+              } else {
-+                      /* do callback with empty buffer - not EOS though */
-+                      msg_context->u.bulk.status = 0;
-+                      msg_context->u.bulk.buffer_used = 0;
-+              }
-+      } else if (msg->u.buffer_from_host.payload_in_message == 0) {
-+              /* data is not in message, queue a bulk receive */
-+              msg_context->u.bulk.status =
-+                  bulk_receive(instance, msg, msg_context);
-+              if (msg_context->u.bulk.status == 0)
-+                      return; /* successful bulk submission, bulk
-+                               * completion will trigger callback
-+                               */
-+
-+              /* failed to submit buffer, this will end badly */
-+              pr_err("error %d on bulk submission\n",
-+                     msg_context->u.bulk.status);
-+
-+      } else if (msg->u.buffer_from_host.payload_in_message <=
-+                 MMAL_VC_SHORT_DATA) {
-+              /* data payload within message */
-+              msg_context->u.bulk.status = inline_receive(instance, msg,
-+                                                          msg_context);
-+      } else {
-+              pr_err("message with invalid short payload\n");
-+
-+              /* signal error */
-+              msg_context->u.bulk.status = -EINVAL;
-+              msg_context->u.bulk.buffer_used =
-+                  msg->u.buffer_from_host.payload_in_message;
-+      }
-+
-+      /* schedule the port callback */
-+      schedule_work(&msg_context->u.bulk.work);
-+}
-+
-+static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
-+                          struct mmal_msg_context *msg_context)
-+{
-+      msg_context->u.bulk.status = 0;
-+
-+      /* schedule the port callback */
-+      schedule_work(&msg_context->u.bulk.work);
-+}
-+
-+static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
-+                        struct mmal_msg_context *msg_context)
-+{
-+      pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
-+
-+      msg_context->u.bulk.status = -EINTR;
-+
-+      schedule_work(&msg_context->u.bulk.work);
-+}
-+
-+/* incoming event service callback */
-+static void service_callback(void *param,
-+                           const VCHI_CALLBACK_REASON_T reason,
-+                           void *bulk_ctx)
-+{
-+      struct vchiq_mmal_instance *instance = param;
-+      int status;
-+      u32 msg_len;
-+      struct mmal_msg *msg;
-+      VCHI_HELD_MSG_T msg_handle;
-+      struct mmal_msg_context *msg_context;
-+
-+      if (!instance) {
-+              pr_err("Message callback passed NULL instance\n");
-+              return;
-+      }
-+
-+      switch (reason) {
-+      case VCHI_CALLBACK_MSG_AVAILABLE:
-+              status = vchi_msg_hold(instance->handle, (void **)&msg,
-+                                     &msg_len, VCHI_FLAGS_NONE, &msg_handle);
-+              if (status) {
-+                      pr_err("Unable to dequeue a message (%d)\n", status);
-+                      break;
-+              }
-+
-+              DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
-+
-+              /* handling is different for buffer messages */
-+              switch (msg->h.type) {
-+              case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
-+                      vchi_held_msg_release(&msg_handle);
-+                      break;
-+
-+              case MMAL_MSG_TYPE_EVENT_TO_HOST:
-+                      event_to_host_cb(instance, msg, msg_len);
-+                      vchi_held_msg_release(&msg_handle);
-+
-+                      break;
-+
-+              case MMAL_MSG_TYPE_BUFFER_TO_HOST:
-+                      buffer_to_host_cb(instance, msg, msg_len);
-+                      vchi_held_msg_release(&msg_handle);
-+                      break;
-+
-+              default:
-+                      /* messages dependent on header context to complete */
-+                      if (!msg->h.context) {
-+                              pr_err("received message context was null!\n");
-+                              vchi_held_msg_release(&msg_handle);
-+                              break;
-+                      }
-+
-+                      msg_context = lookup_msg_context(instance,
-+                                                       msg->h.context);
-+                      if (!msg_context) {
-+                              pr_err("received invalid message context %u!\n",
-+                                     msg->h.context);
-+                              vchi_held_msg_release(&msg_handle);
-+                              break;
-+                      }
-+
-+                      /* fill in context values */
-+                      msg_context->u.sync.msg_handle = msg_handle;
-+                      msg_context->u.sync.msg = msg;
-+                      msg_context->u.sync.msg_len = msg_len;
-+
-+                      /* todo: should this check (completion_done()
-+                       * == 1) for no one waiting? or do we need a
-+                       * flag to tell us the completion has been
-+                       * interrupted so we can free the message and
-+                       * its context. This probably also solves the
-+                       * message arriving after interruption todo
-+                       * below
-+                       */
-+
-+                      /* complete message so caller knows it happened */
-+                      complete(&msg_context->u.sync.cmplt);
-+                      break;
-+              }
-+
-+              break;
-+
-+      case VCHI_CALLBACK_BULK_RECEIVED:
-+              bulk_receive_cb(instance, bulk_ctx);
-+              break;
-+
-+      case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
-+              bulk_abort_cb(instance, bulk_ctx);
-+              break;
-+
-+      case VCHI_CALLBACK_SERVICE_CLOSED:
-+              /* TODO: consider if this requires action if received when
-+               * driver is not explicitly closing the service
-+               */
-+              break;
-+
-+      default:
-+              pr_err("Received unhandled message reason %d\n", reason);
-+              break;
-+      }
-+}
-+
-+static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
-+                                   struct mmal_msg *msg,
-+                                   unsigned int payload_len,
-+                                   struct mmal_msg **msg_out,
-+                                   VCHI_HELD_MSG_T *msg_handle_out)
-+{
-+      struct mmal_msg_context *msg_context;
-+      int ret;
-+      unsigned long timeout;
-+
-+      /* payload size must not cause message to exceed max size */
-+      if (payload_len >
-+          (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
-+              pr_err("payload length %d exceeds max:%d\n", payload_len,
-+                     (int)(MMAL_MSG_MAX_SIZE -
-+                          sizeof(struct mmal_msg_header)));
-+              return -EINVAL;
-+      }
-+
-+      msg_context = get_msg_context(instance);
-+      if (IS_ERR(msg_context))
-+              return PTR_ERR(msg_context);
-+
-+      init_completion(&msg_context->u.sync.cmplt);
-+
-+      msg->h.magic = MMAL_MAGIC;
-+      msg->h.context = msg_context->handle;
-+      msg->h.status = 0;
-+
-+      DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
-+                   ">>> sync message");
-+
-+      vchi_service_use(instance->handle);
-+
-+      ret = vchi_queue_kernel_message(instance->handle,
-+                                      msg,
-+                                      sizeof(struct mmal_msg_header) +
-+                                      payload_len);
-+
-+      vchi_service_release(instance->handle);
-+
-+      if (ret) {
-+              pr_err("error %d queuing message\n", ret);
-+              release_msg_context(msg_context);
-+              return ret;
-+      }
-+
-+      timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
-+                                            3 * HZ);
-+      if (timeout == 0) {
-+              pr_err("timed out waiting for sync completion\n");
-+              ret = -ETIME;
-+              /* todo: what happens if the message arrives after aborting */
-+              release_msg_context(msg_context);
-+              return ret;
-+      }
-+
-+      *msg_out = msg_context->u.sync.msg;
-+      *msg_handle_out = msg_context->u.sync.msg_handle;
-+      release_msg_context(msg_context);
-+
-+      return 0;
-+}
-+
-+static void dump_port_info(struct vchiq_mmal_port *port)
-+{
-+      pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
-+
-+      pr_debug("buffer minimum num:%d size:%d align:%d\n",
-+               port->minimum_buffer.num,
-+               port->minimum_buffer.size, port->minimum_buffer.alignment);
-+
-+      pr_debug("buffer recommended num:%d size:%d align:%d\n",
-+               port->recommended_buffer.num,
-+               port->recommended_buffer.size,
-+               port->recommended_buffer.alignment);
-+
-+      pr_debug("buffer current values num:%d size:%d align:%d\n",
-+               port->current_buffer.num,
-+               port->current_buffer.size, port->current_buffer.alignment);
-+
-+      pr_debug("elementary stream: type:%d encoding:0x%x variant:0x%x\n",
-+               port->format.type,
-+               port->format.encoding, port->format.encoding_variant);
-+
-+      pr_debug("                  bitrate:%d flags:0x%x\n",
-+               port->format.bitrate, port->format.flags);
-+
-+      if (port->format.type == MMAL_ES_TYPE_VIDEO) {
-+              pr_debug
-+                  ("es video format: width:%d height:%d colourspace:0x%x\n",
-+                   port->es.video.width, port->es.video.height,
-+                   port->es.video.color_space);
-+
-+              pr_debug("               : crop xywh %d,%d,%d,%d\n",
-+                       port->es.video.crop.x,
-+                       port->es.video.crop.y,
-+                       port->es.video.crop.width, port->es.video.crop.height);
-+              pr_debug("               : framerate %d/%d  aspect %d/%d\n",
-+                       port->es.video.frame_rate.num,
-+                       port->es.video.frame_rate.den,
-+                       port->es.video.par.num, port->es.video.par.den);
-+      }
-+}
-+
-+static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
-+{
-+      /* todo do readonly fields need setting at all? */
-+      p->type = port->type;
-+      p->index = port->index;
-+      p->index_all = 0;
-+      p->is_enabled = port->enabled;
-+      p->buffer_num_min = port->minimum_buffer.num;
-+      p->buffer_size_min = port->minimum_buffer.size;
-+      p->buffer_alignment_min = port->minimum_buffer.alignment;
-+      p->buffer_num_recommended = port->recommended_buffer.num;
-+      p->buffer_size_recommended = port->recommended_buffer.size;
-+
-+      /* only three writable fields in a port */
-+      p->buffer_num = port->current_buffer.num;
-+      p->buffer_size = port->current_buffer.size;
-+      p->userdata = (u32)(unsigned long)port;
-+}
-+
-+static int port_info_set(struct vchiq_mmal_instance *instance,
-+                       struct vchiq_mmal_port *port)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      pr_debug("setting port info port %p\n", port);
-+      if (!port)
-+              return -1;
-+      dump_port_info(port);
-+
-+      m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
-+
-+      m.u.port_info_set.component_handle = port->component->handle;
-+      m.u.port_info_set.port_type = port->type;
-+      m.u.port_info_set.port_index = port->index;
-+
-+      port_to_mmal_msg(port, &m.u.port_info_set.port);
-+
-+      /* elementary stream format setup */
-+      m.u.port_info_set.format.type = port->format.type;
-+      m.u.port_info_set.format.encoding = port->format.encoding;
-+      m.u.port_info_set.format.encoding_variant =
-+          port->format.encoding_variant;
-+      m.u.port_info_set.format.bitrate = port->format.bitrate;
-+      m.u.port_info_set.format.flags = port->format.flags;
-+
-+      memcpy(&m.u.port_info_set.es, &port->es,
-+             sizeof(union mmal_es_specific_format));
-+
-+      m.u.port_info_set.format.extradata_size = port->format.extradata_size;
-+      memcpy(&m.u.port_info_set.extradata, port->format.extradata,
-+             port->format.extradata_size);
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.port_info_set),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      /* return operation status */
-+      ret = -rmsg->u.port_info_get_reply.status;
-+
-+      pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
-+               port->component->handle, port->handle);
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* use port info get message to retrieve port information */
-+static int port_info_get(struct vchiq_mmal_instance *instance,
-+                       struct vchiq_mmal_port *port)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      /* port info time */
-+      m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
-+      m.u.port_info_get.component_handle = port->component->handle;
-+      m.u.port_info_get.port_type = port->type;
-+      m.u.port_info_get.index = port->index;
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.port_info_get),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      /* return operation status */
-+      ret = -rmsg->u.port_info_get_reply.status;
-+      if (ret != MMAL_MSG_STATUS_SUCCESS)
-+              goto release_msg;
-+
-+      if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
-+              port->enabled = false;
-+      else
-+              port->enabled = true;
-+
-+      /* copy the values out of the message */
-+      port->handle = rmsg->u.port_info_get_reply.port_handle;
-+
-+      /* port type and index cached to use on port info set because
-+       * it does not use a port handle
-+       */
-+      port->type = rmsg->u.port_info_get_reply.port_type;
-+      port->index = rmsg->u.port_info_get_reply.port_index;
-+
-+      port->minimum_buffer.num =
-+          rmsg->u.port_info_get_reply.port.buffer_num_min;
-+      port->minimum_buffer.size =
-+          rmsg->u.port_info_get_reply.port.buffer_size_min;
-+      port->minimum_buffer.alignment =
-+          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
-+
-+      port->recommended_buffer.alignment =
-+          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
-+      port->recommended_buffer.num =
-+          rmsg->u.port_info_get_reply.port.buffer_num_recommended;
-+
-+      port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
-+      port->current_buffer.size =
-+          rmsg->u.port_info_get_reply.port.buffer_size;
-+
-+      /* stream format */
-+      port->format.type = rmsg->u.port_info_get_reply.format.type;
-+      port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
-+      port->format.encoding_variant =
-+          rmsg->u.port_info_get_reply.format.encoding_variant;
-+      port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
-+      port->format.flags = rmsg->u.port_info_get_reply.format.flags;
-+
-+      /* elementary stream format */
-+      memcpy(&port->es,
-+             &rmsg->u.port_info_get_reply.es,
-+             sizeof(union mmal_es_specific_format));
-+      port->format.es = &port->es;
-+
-+      port->format.extradata_size =
-+          rmsg->u.port_info_get_reply.format.extradata_size;
-+      memcpy(port->format.extradata,
-+             rmsg->u.port_info_get_reply.extradata,
-+             port->format.extradata_size);
-+
-+      pr_debug("received port info\n");
-+      dump_port_info(port);
-+
-+release_msg:
-+
-+      pr_debug("%s:result:%d component:0x%x port:%d\n",
-+               __func__, ret, port->component->handle, port->handle);
-+
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* create comonent on vc */
-+static int create_component(struct vchiq_mmal_instance *instance,
-+                          struct vchiq_mmal_component *component,
-+                          const char *name)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      /* build component create message */
-+      m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
-+      m.u.component_create.client_component = (u32)(unsigned long)component;
-+      strncpy(m.u.component_create.name, name,
-+              sizeof(m.u.component_create.name));
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.component_create),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != m.h.type) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.component_create_reply.status;
-+      if (ret != MMAL_MSG_STATUS_SUCCESS)
-+              goto release_msg;
-+
-+      /* a valid component response received */
-+      component->handle = rmsg->u.component_create_reply.component_handle;
-+      component->inputs = rmsg->u.component_create_reply.input_num;
-+      component->outputs = rmsg->u.component_create_reply.output_num;
-+      component->clocks = rmsg->u.component_create_reply.clock_num;
-+
-+      pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
-+               component->handle,
-+               component->inputs, component->outputs, component->clocks);
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* destroys a component on vc */
-+static int destroy_component(struct vchiq_mmal_instance *instance,
-+                           struct vchiq_mmal_component *component)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
-+      m.u.component_destroy.component_handle = component->handle;
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.component_destroy),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != m.h.type) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.component_destroy_reply.status;
-+
-+release_msg:
-+
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* enable a component on vc */
-+static int enable_component(struct vchiq_mmal_instance *instance,
-+                          struct vchiq_mmal_component *component)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
-+      m.u.component_enable.component_handle = component->handle;
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.component_enable),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != m.h.type) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.component_enable_reply.status;
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* disable a component on vc */
-+static int disable_component(struct vchiq_mmal_instance *instance,
-+                           struct vchiq_mmal_component *component)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
-+      m.u.component_disable.component_handle = component->handle;
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.component_disable),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != m.h.type) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.component_disable_reply.status;
-+
-+release_msg:
-+
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* get version of mmal implementation */
-+static int get_version(struct vchiq_mmal_instance *instance,
-+                     u32 *major_out, u32 *minor_out)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_GET_VERSION;
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.version),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != m.h.type) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      *major_out = rmsg->u.version.major;
-+      *minor_out = rmsg->u.version.minor;
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* do a port action with a port as a parameter */
-+static int port_action_port(struct vchiq_mmal_instance *instance,
-+                          struct vchiq_mmal_port *port,
-+                          enum mmal_msg_port_action_type action_type)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
-+      m.u.port_action_port.component_handle = port->component->handle;
-+      m.u.port_action_port.port_handle = port->handle;
-+      m.u.port_action_port.action = action_type;
-+
-+      port_to_mmal_msg(port, &m.u.port_action_port.port);
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.port_action_port),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.port_action_reply.status;
-+
-+      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
-+               __func__,
-+               ret, port->component->handle, port->handle,
-+               port_action_type_names[action_type], action_type);
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* do a port action with handles as parameters */
-+static int port_action_handle(struct vchiq_mmal_instance *instance,
-+                            struct vchiq_mmal_port *port,
-+                            enum mmal_msg_port_action_type action_type,
-+                            u32 connect_component_handle,
-+                            u32 connect_port_handle)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
-+
-+      m.u.port_action_handle.component_handle = port->component->handle;
-+      m.u.port_action_handle.port_handle = port->handle;
-+      m.u.port_action_handle.action = action_type;
-+
-+      m.u.port_action_handle.connect_component_handle =
-+          connect_component_handle;
-+      m.u.port_action_handle.connect_port_handle = connect_port_handle;
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(m.u.port_action_handle),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.port_action_reply.status;
-+
-+      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n",
-+               __func__,
-+               ret, port->component->handle, port->handle,
-+               port_action_type_names[action_type],
-+               action_type, connect_component_handle, connect_port_handle);
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+static int port_parameter_set(struct vchiq_mmal_instance *instance,
-+                            struct vchiq_mmal_port *port,
-+                            u32 parameter_id, void *value, u32 value_size)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
-+
-+      m.u.port_parameter_set.component_handle = port->component->handle;
-+      m.u.port_parameter_set.port_handle = port->handle;
-+      m.u.port_parameter_set.id = parameter_id;
-+      m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
-+      memcpy(&m.u.port_parameter_set.value, value, value_size);
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      (4 * sizeof(u32)) + value_size,
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
-+              /* got an unexpected message type in reply */
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.port_parameter_set_reply.status;
-+
-+      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
-+               __func__,
-+               ret, port->component->handle, port->handle, parameter_id);
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+static int port_parameter_get(struct vchiq_mmal_instance *instance,
-+                            struct vchiq_mmal_port *port,
-+                            u32 parameter_id, void *value, u32 *value_size)
-+{
-+      int ret;
-+      struct mmal_msg m;
-+      struct mmal_msg *rmsg;
-+      VCHI_HELD_MSG_T rmsg_handle;
-+
-+      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
-+
-+      m.u.port_parameter_get.component_handle = port->component->handle;
-+      m.u.port_parameter_get.port_handle = port->handle;
-+      m.u.port_parameter_get.id = parameter_id;
-+      m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
-+
-+      ret = send_synchronous_mmal_msg(instance, &m,
-+                                      sizeof(struct
-+                                             mmal_msg_port_parameter_get),
-+                                      &rmsg, &rmsg_handle);
-+      if (ret)
-+              return ret;
-+
-+      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
-+              /* got an unexpected message type in reply */
-+              pr_err("Incorrect reply type %d\n", rmsg->h.type);
-+              ret = -EINVAL;
-+              goto release_msg;
-+      }
-+
-+      ret = -rmsg->u.port_parameter_get_reply.status;
-+      /* port_parameter_get_reply.size includes the header,
-+       * whilst *value_size doesn't.
-+       */
-+      rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32));
-+
-+      if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) {
-+              /* Copy only as much as we have space for
-+               * but report true size of parameter
-+               */
-+              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
-+                     *value_size);
-+              *value_size = rmsg->u.port_parameter_get_reply.size;
-+      } else {
-+              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
-+                     rmsg->u.port_parameter_get_reply.size);
-+      }
-+
-+      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
-+               ret, port->component->handle, port->handle, parameter_id);
-+
-+release_msg:
-+      vchi_held_msg_release(&rmsg_handle);
-+
-+      return ret;
-+}
-+
-+/* disables a port and drains buffers from it */
-+static int port_disable(struct vchiq_mmal_instance *instance,
-+                      struct vchiq_mmal_port *port)
-+{
-+      int ret;
-+      struct list_head *q, *buf_head;
-+      unsigned long flags = 0;
-+
-+      if (!port->enabled)
-+              return 0;
-+
-+      port->enabled = false;
-+
-+      ret = port_action_port(instance, port,
-+                             MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
-+      if (ret == 0) {
-+              /*
-+               * Drain all queued buffers on port. This should only
-+               * apply to buffers that have been queued before the port
-+               * has been enabled. If the port has been enabled and buffers
-+               * passed, then the buffers should have been removed from this
-+               * list, and we should get the relevant callbacks via VCHIQ
-+               * to release the buffers.
-+               */
-+              spin_lock_irqsave(&port->slock, flags);
-+
-+              list_for_each_safe(buf_head, q, &port->buffers) {
-+                      struct mmal_buffer *mmalbuf;
-+
-+                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
-+                                           list);
-+                      list_del(buf_head);
-+                      if (port->buffer_cb)
-+                              port->buffer_cb(instance,
-+                                              port, 0, mmalbuf, 0, 0,
-+                                              MMAL_TIME_UNKNOWN,
-+                                              MMAL_TIME_UNKNOWN);
-+              }
-+
-+              spin_unlock_irqrestore(&port->slock, flags);
-+
-+              ret = port_info_get(instance, port);
-+      }
-+
-+      return ret;
-+}
-+
-+/* enable a port */
-+static int port_enable(struct vchiq_mmal_instance *instance,
-+                     struct vchiq_mmal_port *port)
-+{
-+      unsigned int hdr_count;
-+      struct list_head *q, *buf_head;
-+      int ret;
-+
-+      if (port->enabled)
-+              return 0;
-+
-+      ret = port_action_port(instance, port,
-+                             MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
-+      if (ret)
-+              goto done;
-+
-+      port->enabled = true;
-+
-+      if (port->buffer_cb) {
-+              /* send buffer headers to videocore */
-+              hdr_count = 1;
-+              list_for_each_safe(buf_head, q, &port->buffers) {
-+                      struct mmal_buffer *mmalbuf;
-+
-+                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
-+                                           list);
-+                      ret = buffer_from_host(instance, port, mmalbuf);
-+                      if (ret)
-+                              goto done;
-+
-+                      list_del(buf_head);
-+                      hdr_count++;
-+                      if (hdr_count > port->current_buffer.num)
-+                              break;
-+              }
-+      }
-+
-+      ret = port_info_get(instance, port);
-+
-+done:
-+      return ret;
-+}
-+
-+/* ------------------------------------------------------------------
-+ * Exported API
-+ *------------------------------------------------------------------
-+ */
-+
-+int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
-+                             struct vchiq_mmal_port *port)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      ret = port_info_set(instance, port);
-+      if (ret)
-+              goto release_unlock;
-+
-+      /* read what has actually been set */
-+      ret = port_info_get(instance, port);
-+
-+release_unlock:
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format);
-+
-+int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
-+                                struct vchiq_mmal_port *port,
-+                                u32 parameter, void *value, u32 value_size)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      ret = port_parameter_set(instance, port, parameter, value, value_size);
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
-+
-+int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
-+                                struct vchiq_mmal_port *port,
-+                                u32 parameter, void *value, u32 *value_size)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      ret = port_parameter_get(instance, port, parameter, value, value_size);
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get);
-+
-+/* enable a port
-+ *
-+ * enables a port and queues buffers for satisfying callbacks if we
-+ * provide a callback handler
-+ */
-+int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
-+                         struct vchiq_mmal_port *port,
-+                         vchiq_mmal_buffer_cb buffer_cb)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      /* already enabled - noop */
-+      if (port->enabled) {
-+              ret = 0;
-+              goto unlock;
-+      }
-+
-+      port->buffer_cb = buffer_cb;
-+
-+      ret = port_enable(instance, port);
-+
-+unlock:
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable);
-+
-+int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
-+                          struct vchiq_mmal_port *port)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      if (!port->enabled) {
-+              mutex_unlock(&instance->vchiq_mutex);
-+              return 0;
-+      }
-+
-+      ret = port_disable(instance, port);
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable);
-+
-+/* ports will be connected in a tunneled manner so data buffers
-+ * are not handled by client.
-+ */
-+int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
-+                                 struct vchiq_mmal_port *src,
-+                                 struct vchiq_mmal_port *dst)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      /* disconnect ports if connected */
-+      if (src->connected) {
-+              ret = port_disable(instance, src);
-+              if (ret) {
-+                      pr_err("failed disabling src port(%d)\n", ret);
-+                      goto release_unlock;
-+              }
-+
-+              /* do not need to disable the destination port as they
-+               * are connected and it is done automatically
-+               */
-+
-+              ret = port_action_handle(instance, src,
-+                                       MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
-+                                       src->connected->component->handle,
-+                                       src->connected->handle);
-+              if (ret < 0) {
-+                      pr_err("failed disconnecting src port\n");
-+                      goto release_unlock;
-+              }
-+              src->connected->enabled = false;
-+              src->connected = NULL;
-+      }
-+
-+      if (!dst) {
-+              /* do not make new connection */
-+              ret = 0;
-+              pr_debug("not making new connection\n");
-+              goto release_unlock;
-+      }
-+
-+      /* copy src port format to dst */
-+      dst->format.encoding = src->format.encoding;
-+      dst->es.video.width = src->es.video.width;
-+      dst->es.video.height = src->es.video.height;
-+      dst->es.video.crop.x = src->es.video.crop.x;
-+      dst->es.video.crop.y = src->es.video.crop.y;
-+      dst->es.video.crop.width = src->es.video.crop.width;
-+      dst->es.video.crop.height = src->es.video.crop.height;
-+      dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
-+      dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
-+
-+      /* set new format */
-+      ret = port_info_set(instance, dst);
-+      if (ret) {
-+              pr_debug("setting port info failed\n");
-+              goto release_unlock;
-+      }
-+
-+      /* read what has actually been set */
-+      ret = port_info_get(instance, dst);
-+      if (ret) {
-+              pr_debug("read back port info failed\n");
-+              goto release_unlock;
-+      }
-+
-+      /* connect two ports together */
-+      ret = port_action_handle(instance, src,
-+                               MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
-+                               dst->component->handle, dst->handle);
-+      if (ret < 0) {
-+              pr_debug("connecting port %d:%d to %d:%d failed\n",
-+                       src->component->handle, src->handle,
-+                       dst->component->handle, dst->handle);
-+              goto release_unlock;
-+      }
-+      src->connected = dst;
-+
-+release_unlock:
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_connect_tunnel);
-+
-+int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
-+                           struct vchiq_mmal_port *port,
-+                           struct mmal_buffer *buffer)
-+{
-+      unsigned long flags = 0;
-+      int ret;
-+
-+      ret = buffer_from_host(instance, port, buffer);
-+      if (ret == -EINVAL) {
-+              /* Port is disabled. Queue for when it is enabled. */
-+              spin_lock_irqsave(&port->slock, flags);
-+              list_add_tail(&buffer->list, &port->buffers);
-+              spin_unlock_irqrestore(&port->slock, flags);
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_submit_buffer);
-+
-+int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
-+                        struct mmal_buffer *buf)
-+{
-+      struct mmal_msg_context *msg_context = get_msg_context(instance);
-+
-+      if (IS_ERR(msg_context))
-+              return (PTR_ERR(msg_context));
-+
-+      buf->msg_context = msg_context;
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
-+
-+int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
-+{
-+      struct mmal_msg_context *msg_context = buf->msg_context;
-+
-+      if (msg_context)
-+              release_msg_context(msg_context);
-+      buf->msg_context = NULL;
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
-+
-+/* Initialise a mmal component and its ports
-+ *
-+ */
-+int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
-+                            const char *name,
-+                            struct vchiq_mmal_component **component_out)
-+{
-+      int ret;
-+      int idx;                /* port index */
-+      struct vchiq_mmal_component *component;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
-+              ret = -EINVAL;  /* todo is this correct error? */
-+              goto unlock;
-+      }
-+
-+      component = &instance->component[instance->component_idx];
-+
-+      ret = create_component(instance, component, name);
-+      if (ret < 0) {
-+              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
-+                     __func__, ret);
-+              goto unlock;
-+      }
-+
-+      /* ports info needs gathering */
-+      component->control.type = MMAL_PORT_TYPE_CONTROL;
-+      component->control.index = 0;
-+      component->control.component = component;
-+      spin_lock_init(&component->control.slock);
-+      INIT_LIST_HEAD(&component->control.buffers);
-+      ret = port_info_get(instance, &component->control);
-+      if (ret < 0)
-+              goto release_component;
-+
-+      for (idx = 0; idx < component->inputs; idx++) {
-+              component->input[idx].type = MMAL_PORT_TYPE_INPUT;
-+              component->input[idx].index = idx;
-+              component->input[idx].component = component;
-+              spin_lock_init(&component->input[idx].slock);
-+              INIT_LIST_HEAD(&component->input[idx].buffers);
-+              ret = port_info_get(instance, &component->input[idx]);
-+              if (ret < 0)
-+                      goto release_component;
-+      }
-+
-+      for (idx = 0; idx < component->outputs; idx++) {
-+              component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
-+              component->output[idx].index = idx;
-+              component->output[idx].component = component;
-+              spin_lock_init(&component->output[idx].slock);
-+              INIT_LIST_HEAD(&component->output[idx].buffers);
-+              ret = port_info_get(instance, &component->output[idx]);
-+              if (ret < 0)
-+                      goto release_component;
-+      }
-+
-+      for (idx = 0; idx < component->clocks; idx++) {
-+              component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
-+              component->clock[idx].index = idx;
-+              component->clock[idx].component = component;
-+              spin_lock_init(&component->clock[idx].slock);
-+              INIT_LIST_HEAD(&component->clock[idx].buffers);
-+              ret = port_info_get(instance, &component->clock[idx]);
-+              if (ret < 0)
-+                      goto release_component;
-+      }
-+
-+      instance->component_idx++;
-+
-+      *component_out = component;
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return 0;
-+
-+release_component:
-+      destroy_component(instance, component);
-+unlock:
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_init);
-+
-+/*
-+ * cause a mmal component to be destroyed
-+ */
-+int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
-+                                struct vchiq_mmal_component *component)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      if (component->enabled)
-+              ret = disable_component(instance, component);
-+
-+      ret = destroy_component(instance, component);
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise);
-+
-+/*
-+ * cause a mmal component to be enabled
-+ */
-+int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
-+                              struct vchiq_mmal_component *component)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      if (component->enabled) {
-+              mutex_unlock(&instance->vchiq_mutex);
-+              return 0;
-+      }
-+
-+      ret = enable_component(instance, component);
-+      if (ret == 0)
-+              component->enabled = true;
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable);
-+
-+/*
-+ * cause a mmal component to be enabled
-+ */
-+int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
-+                               struct vchiq_mmal_component *component)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      if (!component->enabled) {
-+              mutex_unlock(&instance->vchiq_mutex);
-+              return 0;
-+      }
-+
-+      ret = disable_component(instance, component);
-+      if (ret == 0)
-+              component->enabled = false;
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable);
-+
-+int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
-+                     u32 *major_out, u32 *minor_out)
-+{
-+      int ret;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      ret = get_version(instance, major_out, minor_out);
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_version);
-+
-+int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
-+{
-+      int status = 0;
-+
-+      if (!instance)
-+              return -EINVAL;
-+
-+      if (mutex_lock_interruptible(&instance->vchiq_mutex))
-+              return -EINTR;
-+
-+      vchi_service_use(instance->handle);
-+
-+      status = vchi_service_close(instance->handle);
-+      if (status != 0)
-+              pr_err("mmal-vchiq: VCHIQ close failed\n");
-+
-+      mutex_unlock(&instance->vchiq_mutex);
-+
-+      flush_workqueue(instance->bulk_wq);
-+      destroy_workqueue(instance->bulk_wq);
-+
-+      vfree(instance->bulk_scratch);
-+
-+      idr_destroy(&instance->context_map);
-+
-+      kfree(instance);
-+
-+      return status;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_finalise);
-+
-+int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
-+{
-+      int status;
-+      struct vchiq_mmal_instance *instance;
-+      static VCHI_CONNECTION_T *vchi_connection;
-+      static VCHI_INSTANCE_T vchi_instance;
-+      SERVICE_CREATION_T params = {
-+              .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
-+              .service_id             = VC_MMAL_SERVER_NAME,
-+              .connection             = vchi_connection,
-+              .rx_fifo_size           = 0,
-+              .tx_fifo_size           = 0,
-+              .callback               = service_callback,
-+              .callback_param         = NULL,
-+              .want_unaligned_bulk_rx = 1,
-+              .want_unaligned_bulk_tx = 1,
-+              .want_crc               = 0
-+      };
-+
-+      /* compile time checks to ensure structure size as they are
-+       * directly (de)serialised from memory.
-+       */
-+
-+      /* ensure the header structure has packed to the correct size */
-+      BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
-+
-+      /* ensure message structure does not exceed maximum length */
-+      BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
-+
-+      /* mmal port struct is correct size */
-+      BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
-+
-+      /* create a vchi instance */
-+      status = vchi_initialise(&vchi_instance);
-+      if (status) {
-+              pr_err("Failed to initialise VCHI instance (status=%d)\n",
-+                     status);
-+              return -EIO;
-+      }
-+
-+      status = vchi_connect(NULL, 0, vchi_instance);
-+      if (status) {
-+              pr_err("Failed to connect VCHI instance (status=%d)\n", status);
-+              return -EIO;
-+      }
-+
-+      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-+
-+      if (!instance)
-+              return -ENOMEM;
-+
-+      mutex_init(&instance->vchiq_mutex);
-+
-+      instance->bulk_scratch = vmalloc(PAGE_SIZE);
-+
-+      mutex_init(&instance->context_map_lock);
-+      idr_init_base(&instance->context_map, 1);
-+
-+      params.callback_param = instance;
-+
-+      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
-+                                                  WQ_MEM_RECLAIM);
-+      if (!instance->bulk_wq)
-+              goto err_free;
-+
-+      status = vchi_service_open(vchi_instance, &params, &instance->handle);
-+      if (status) {
-+              pr_err("Failed to open VCHI service connection (status=%d)\n",
-+                     status);
-+              goto err_close_services;
-+      }
-+
-+      vchi_service_release(instance->handle);
-+
-+      *out_instance = instance;
-+
-+      return 0;
-+
-+err_close_services:
-+      vchi_service_close(instance->handle);
-+      destroy_workqueue(instance->bulk_wq);
-+err_free:
-+      vfree(instance->bulk_scratch);
-+      kfree(instance);
-+      return -ENODEV;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_init);
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-+++ /dev/null
-@@ -1,61 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- *
-- * MMAL structures
-- *
-- */
--#ifndef MMAL_COMMON_H
--#define MMAL_COMMON_H
--
--#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
--#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
--
--/** Special value signalling that time is not known */
--#define MMAL_TIME_UNKNOWN BIT_ULL(63)
--
--struct mmal_msg_context;
--
--/* mapping between v4l and mmal video modes */
--struct mmal_fmt {
--      char  *name;
--      u32   fourcc;          /* v4l2 format id */
--      int   flags;           /* v4l2 flags field */
--      u32   mmal;
--      int   depth;
--      u32   mmal_component;  /* MMAL component index to be used to encode */
--      u32   ybbp;            /* depth of first Y plane for planar formats */
--      bool  remove_padding;  /* Does the GPU have to remove padding,
--                              * or can we do hide padding via bytesperline.
--                              */
--};
--
--/* buffer for one video frame */
--struct mmal_buffer {
--      /* v4l buffer data -- must be first */
--      struct vb2_v4l2_buffer  vb;
--
--      /* list of buffers available */
--      struct list_head        list;
--
--      void *buffer; /* buffer pointer */
--      unsigned long buffer_size; /* size of allocated buffer */
--
--      struct mmal_msg_context *msg_context;
--};
--
--/* */
--struct mmal_colourfx {
--      s32 enable;
--      u32 u;
--      u32 v;
--};
--#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
-+++ /dev/null
-@@ -1,124 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- */
--#ifndef MMAL_ENCODINGS_H
--#define MMAL_ENCODINGS_H
--
--#define MMAL_ENCODING_H264             MMAL_FOURCC('H', '2', '6', '4')
--#define MMAL_ENCODING_H263             MMAL_FOURCC('H', '2', '6', '3')
--#define MMAL_ENCODING_MP4V             MMAL_FOURCC('M', 'P', '4', 'V')
--#define MMAL_ENCODING_MP2V             MMAL_FOURCC('M', 'P', '2', 'V')
--#define MMAL_ENCODING_MP1V             MMAL_FOURCC('M', 'P', '1', 'V')
--#define MMAL_ENCODING_WMV3             MMAL_FOURCC('W', 'M', 'V', '3')
--#define MMAL_ENCODING_WMV2             MMAL_FOURCC('W', 'M', 'V', '2')
--#define MMAL_ENCODING_WMV1             MMAL_FOURCC('W', 'M', 'V', '1')
--#define MMAL_ENCODING_WVC1             MMAL_FOURCC('W', 'V', 'C', '1')
--#define MMAL_ENCODING_VP8              MMAL_FOURCC('V', 'P', '8', ' ')
--#define MMAL_ENCODING_VP7              MMAL_FOURCC('V', 'P', '7', ' ')
--#define MMAL_ENCODING_VP6              MMAL_FOURCC('V', 'P', '6', ' ')
--#define MMAL_ENCODING_THEORA           MMAL_FOURCC('T', 'H', 'E', 'O')
--#define MMAL_ENCODING_SPARK            MMAL_FOURCC('S', 'P', 'R', 'K')
--#define MMAL_ENCODING_MJPEG            MMAL_FOURCC('M', 'J', 'P', 'G')
--
--#define MMAL_ENCODING_JPEG             MMAL_FOURCC('J', 'P', 'E', 'G')
--#define MMAL_ENCODING_GIF              MMAL_FOURCC('G', 'I', 'F', ' ')
--#define MMAL_ENCODING_PNG              MMAL_FOURCC('P', 'N', 'G', ' ')
--#define MMAL_ENCODING_PPM              MMAL_FOURCC('P', 'P', 'M', ' ')
--#define MMAL_ENCODING_TGA              MMAL_FOURCC('T', 'G', 'A', ' ')
--#define MMAL_ENCODING_BMP              MMAL_FOURCC('B', 'M', 'P', ' ')
--
--#define MMAL_ENCODING_I420             MMAL_FOURCC('I', '4', '2', '0')
--#define MMAL_ENCODING_I420_SLICE       MMAL_FOURCC('S', '4', '2', '0')
--#define MMAL_ENCODING_YV12             MMAL_FOURCC('Y', 'V', '1', '2')
--#define MMAL_ENCODING_I422             MMAL_FOURCC('I', '4', '2', '2')
--#define MMAL_ENCODING_I422_SLICE       MMAL_FOURCC('S', '4', '2', '2')
--#define MMAL_ENCODING_YUYV             MMAL_FOURCC('Y', 'U', 'Y', 'V')
--#define MMAL_ENCODING_YVYU             MMAL_FOURCC('Y', 'V', 'Y', 'U')
--#define MMAL_ENCODING_UYVY             MMAL_FOURCC('U', 'Y', 'V', 'Y')
--#define MMAL_ENCODING_VYUY             MMAL_FOURCC('V', 'Y', 'U', 'Y')
--#define MMAL_ENCODING_NV12             MMAL_FOURCC('N', 'V', '1', '2')
--#define MMAL_ENCODING_NV21             MMAL_FOURCC('N', 'V', '2', '1')
--#define MMAL_ENCODING_ARGB             MMAL_FOURCC('A', 'R', 'G', 'B')
--#define MMAL_ENCODING_RGBA             MMAL_FOURCC('R', 'G', 'B', 'A')
--#define MMAL_ENCODING_ABGR             MMAL_FOURCC('A', 'B', 'G', 'R')
--#define MMAL_ENCODING_BGRA             MMAL_FOURCC('B', 'G', 'R', 'A')
--#define MMAL_ENCODING_RGB16            MMAL_FOURCC('R', 'G', 'B', '2')
--#define MMAL_ENCODING_RGB24            MMAL_FOURCC('R', 'G', 'B', '3')
--#define MMAL_ENCODING_RGB32            MMAL_FOURCC('R', 'G', 'B', '4')
--#define MMAL_ENCODING_BGR16            MMAL_FOURCC('B', 'G', 'R', '2')
--#define MMAL_ENCODING_BGR24            MMAL_FOURCC('B', 'G', 'R', '3')
--#define MMAL_ENCODING_BGR32            MMAL_FOURCC('B', 'G', 'R', '4')
--
--/** SAND Video (YUVUV128) format, native format understood by VideoCore.
-- * This format is *not* opaque - if requested you will receive full frames
-- * of YUV_UV video.
-- */
--#define MMAL_ENCODING_YUVUV128         MMAL_FOURCC('S', 'A', 'N', 'D')
--
--/** VideoCore opaque image format, image handles are returned to
-- * the host but not the actual image data.
-- */
--#define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
--
--/** An EGL image handle
-- */
--#define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
--
--/* }@ */
--
--/** \name Pre-defined audio encodings */
--/* @{ */
--#define MMAL_ENCODING_PCM_UNSIGNED_BE  MMAL_FOURCC('P', 'C', 'M', 'U')
--#define MMAL_ENCODING_PCM_UNSIGNED_LE  MMAL_FOURCC('p', 'c', 'm', 'u')
--#define MMAL_ENCODING_PCM_SIGNED_BE    MMAL_FOURCC('P', 'C', 'M', 'S')
--#define MMAL_ENCODING_PCM_SIGNED_LE    MMAL_FOURCC('p', 'c', 'm', 's')
--#define MMAL_ENCODING_PCM_FLOAT_BE     MMAL_FOURCC('P', 'C', 'M', 'F')
--#define MMAL_ENCODING_PCM_FLOAT_LE     MMAL_FOURCC('p', 'c', 'm', 'f')
--
--/* Pre-defined H264 encoding variants */
--
--/** ISO 14496-10 Annex B byte stream format */
--#define MMAL_ENCODING_VARIANT_H264_DEFAULT   0
--/** ISO 14496-15 AVC stream format */
--#define MMAL_ENCODING_VARIANT_H264_AVC1      MMAL_FOURCC('A', 'V', 'C', '1')
--/** Implicitly delineated NAL units without emulation prevention */
--#define MMAL_ENCODING_VARIANT_H264_RAW       MMAL_FOURCC('R', 'A', 'W', ' ')
--
--/** \defgroup MmalColorSpace List of pre-defined video color spaces
-- * This defines a list of common color spaces. This list isn't exhaustive and
-- * is only provided as a convenience to avoid clients having to use FourCC
-- * codes directly. However components are allowed to define and use their own
-- * FourCC codes.
-- */
--/* @{ */
--
--/** Unknown color space */
--#define MMAL_COLOR_SPACE_UNKNOWN       0
--/** ITU-R BT.601-5 [SDTV] */
--#define MMAL_COLOR_SPACE_ITUR_BT601    MMAL_FOURCC('Y', '6', '0', '1')
--/** ITU-R BT.709-3 [HDTV] */
--#define MMAL_COLOR_SPACE_ITUR_BT709    MMAL_FOURCC('Y', '7', '0', '9')
--/** JPEG JFIF */
--#define MMAL_COLOR_SPACE_JPEG_JFIF     MMAL_FOURCC('Y', 'J', 'F', 'I')
--/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
--#define MMAL_COLOR_SPACE_FCC           MMAL_FOURCC('Y', 'F', 'C', 'C')
--/** Society of Motion Picture and Television Engineers 240M (1999) */
--#define MMAL_COLOR_SPACE_SMPTE240M     MMAL_FOURCC('Y', '2', '4', '0')
--/** ITU-R BT.470-2 System M */
--#define MMAL_COLOR_SPACE_BT470_2_M     MMAL_FOURCC('Y', '_', '_', 'M')
--/** ITU-R BT.470-2 System BG */
--#define MMAL_COLOR_SPACE_BT470_2_BG    MMAL_FOURCC('Y', '_', 'B', 'G')
--/** JPEG JFIF, but with 16..255 luma */
--#define MMAL_COLOR_SPACE_JFIF_Y16_255  MMAL_FOURCC('Y', 'Y', '1', '6')
--/* @} MmalColorSpace List */
--
--#endif /* MMAL_ENCODINGS_H */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
-+++ /dev/null
-@@ -1,48 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- */
--
--#ifndef MMAL_MSG_COMMON_H
--#define MMAL_MSG_COMMON_H
--
--enum mmal_msg_status {
--      MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
--      MMAL_MSG_STATUS_ENOMEM,      /**< Out of memory */
--      MMAL_MSG_STATUS_ENOSPC,      /**< Out of resources other than memory */
--      MMAL_MSG_STATUS_EINVAL,      /**< Argument is invalid */
--      MMAL_MSG_STATUS_ENOSYS,      /**< Function not implemented */
--      MMAL_MSG_STATUS_ENOENT,      /**< No such file or directory */
--      MMAL_MSG_STATUS_ENXIO,       /**< No such device or address */
--      MMAL_MSG_STATUS_EIO,         /**< I/O error */
--      MMAL_MSG_STATUS_ESPIPE,      /**< Illegal seek */
--      MMAL_MSG_STATUS_ECORRUPT,    /**< Data is corrupt \attention */
--      MMAL_MSG_STATUS_ENOTREADY,   /**< Component is not ready */
--      MMAL_MSG_STATUS_ECONFIG,     /**< Component is not configured */
--      MMAL_MSG_STATUS_EISCONN,     /**< Port is already connected */
--      MMAL_MSG_STATUS_ENOTCONN,    /**< Port is disconnected */
--      MMAL_MSG_STATUS_EAGAIN,      /**< Resource temporarily unavailable. */
--      MMAL_MSG_STATUS_EFAULT,      /**< Bad address */
--};
--
--struct mmal_rect {
--      s32 x;      /**< x coordinate (from left) */
--      s32 y;      /**< y coordinate (from top) */
--      s32 width;  /**< width */
--      s32 height; /**< height */
--};
--
--struct mmal_rational {
--      s32 num;    /**< Numerator */
--      s32 den;    /**< Denominator */
--};
--
--#endif /* MMAL_MSG_COMMON_H */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
-+++ /dev/null
-@@ -1,106 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- */
--
--#ifndef MMAL_MSG_FORMAT_H
--#define MMAL_MSG_FORMAT_H
--
--#include "mmal-msg-common.h"
--
--/* MMAL_ES_FORMAT_T */
--
--struct mmal_audio_format {
--      u32 channels;           /* Number of audio channels */
--      u32 sample_rate;        /* Sample rate */
--
--      u32 bits_per_sample;    /* Bits per sample */
--      u32 block_align;        /* Size of a block of data */
--};
--
--struct mmal_video_format {
--      u32 width;              /* Width of frame in pixels */
--      u32 height;             /* Height of frame in rows of pixels */
--      struct mmal_rect crop;  /* Visible region of the frame */
--      struct mmal_rational frame_rate;        /* Frame rate */
--      struct mmal_rational par;               /* Pixel aspect ratio */
--
--      /*
--       * FourCC specifying the color space of the video stream. See the
--       * MmalColorSpace "pre-defined color spaces" for some examples.
--       */
--      u32 color_space;
--};
--
--struct mmal_subpicture_format {
--      u32 x_offset;
--      u32 y_offset;
--};
--
--union mmal_es_specific_format {
--      struct mmal_audio_format audio;
--      struct mmal_video_format video;
--      struct mmal_subpicture_format subpicture;
--};
--
--/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
--struct mmal_es_format_local {
--      u32 type;       /* enum mmal_es_type */
--
--      u32 encoding;   /* FourCC specifying encoding of the elementary
--                       * stream.
--                       */
--      u32 encoding_variant;   /* FourCC specifying the specific
--                               * encoding variant of the elementary
--                               * stream.
--                               */
--
--      union mmal_es_specific_format *es;      /* Type specific
--                                               * information for the
--                                               * elementary stream
--                                               */
--
--      u32 bitrate;    /* Bitrate in bits per second */
--      u32 flags;      /* Flags describing properties of the elementary
--                       * stream.
--                       */
--
--      u32 extradata_size;     /* Size of the codec specific data */
--      u8  *extradata;         /* Codec specific data */
--};
--
--/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
--struct mmal_es_format {
--      u32 type;       /* enum mmal_es_type */
--
--      u32 encoding;   /* FourCC specifying encoding of the elementary
--                       * stream.
--                       */
--      u32 encoding_variant;   /* FourCC specifying the specific
--                               * encoding variant of the elementary
--                               * stream.
--                               */
--
--      u32 es; /* Type specific
--               * information for the
--               * elementary stream
--               */
--
--      u32 bitrate;    /* Bitrate in bits per second */
--      u32 flags;      /* Flags describing properties of the elementary
--                       * stream.
--                       */
--
--      u32 extradata_size;     /* Size of the codec specific data */
--      u32 extradata;          /* Codec specific data */
--};
--
--#endif /* MMAL_MSG_FORMAT_H */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
-+++ /dev/null
-@@ -1,109 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- */
--
--/* MMAL_PORT_TYPE_T */
--enum mmal_port_type {
--      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
--      MMAL_PORT_TYPE_CONTROL,         /* Control port */
--      MMAL_PORT_TYPE_INPUT,           /* Input port */
--      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
--      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
--};
--
--/* The port is pass-through and doesn't need buffer headers allocated */
--#define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
--/*
-- *The port wants to allocate the buffer payloads.
-- * This signals a preference that payload allocation should be done
-- * on this port for efficiency reasons.
-- */
--#define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
--/*
-- * The port supports format change events.
-- * This applies to input ports and is used to let the client know
-- * whether the port supports being reconfigured via a format
-- * change event (i.e. without having to disable the port).
-- */
--#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
--
--/*
-- * mmal port structure (MMAL_PORT_T)
-- *
-- * most elements are informational only, the pointer values for
-- * interogation messages are generally provided as additional
-- * structures within the message. When used to set values only the
-- * buffer_num, buffer_size and userdata parameters are writable.
-- */
--struct mmal_port {
--      u32 priv;       /* Private member used by the framework */
--      u32 name;       /* Port name. Used for debugging purposes (RO) */
--
--      u32 type;       /* Type of the port (RO) enum mmal_port_type */
--      u16 index;      /* Index of the port in its type list (RO) */
--      u16 index_all;  /* Index of the port in the list of all ports (RO) */
--
--      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
--      u32 format;     /* Format of the elementary stream */
--
--      u32 buffer_num_min;     /* Minimum number of buffers the port
--                               *   requires (RO).  This is set by the
--                               *   component.
--                               */
--
--      u32 buffer_size_min;    /* Minimum size of buffers the port
--                               * requires (RO).  This is set by the
--                               * component.
--                               */
--
--      u32 buffer_alignment_min;/* Minimum alignment requirement for
--                                * the buffers (RO).  A value of
--                                * zero means no special alignment
--                                * requirements.  This is set by the
--                                * component.
--                                */
--
--      u32 buffer_num_recommended;     /* Number of buffers the port
--                                       * recommends for optimal
--                                       * performance (RO).  A value of
--                                       * zero means no special
--                                       * recommendation.  This is set
--                                       * by the component.
--                                       */
--
--      u32 buffer_size_recommended;    /* Size of buffers the port
--                                       * recommends for optimal
--                                       * performance (RO).  A value of
--                                       * zero means no special
--                                       * recommendation.  This is set
--                                       * by the component.
--                                       */
--
--      u32 buffer_num; /* Actual number of buffers the port will use.
--                       * This is set by the client.
--                       */
--
--      u32 buffer_size; /* Actual maximum size of the buffers that
--                        * will be sent to the port. This is set by
--                        * the client.
--                        */
--
--      u32 component;  /* Component this port belongs to (Read Only) */
--
--      u32 userdata;   /* Field reserved for use by the client */
--
--      u32 capabilities;       /* Flags describing the capabilities of a
--                               * port (RO).  Bitwise combination of \ref
--                               * portcapabilities "Port capabilities"
--                               * values.
--                               */
--};
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-+++ /dev/null
-@@ -1,406 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- */
--
--/*
-- * all the data structures which serialise the MMAL protocol. note
-- * these are directly mapped onto the recived message data.
-- *
-- * BEWARE: They seem to *assume* pointers are u32 and that there is no
-- * structure padding!
-- *
-- * NOTE: this implementation uses kernel types to ensure sizes. Rather
-- * than assigning values to enums to force their size the
-- * implementation uses fixed size types and not the enums (though the
-- * comments have the actual enum type
-- */
--#ifndef MMAL_MSG_H
--#define MMAL_MSG_H
--
--#define VC_MMAL_VER 15
--#define VC_MMAL_MIN_VER 10
--#define VC_MMAL_SERVER_NAME  MAKE_FOURCC("mmal")
--
--/* max total message size is 512 bytes */
--#define MMAL_MSG_MAX_SIZE 512
--/* with six 32bit header elements max payload is therefore 488 bytes */
--#define MMAL_MSG_MAX_PAYLOAD 488
--
--#include "mmal-msg-common.h"
--#include "mmal-msg-format.h"
--#include "mmal-msg-port.h"
--
--enum mmal_msg_type {
--      MMAL_MSG_TYPE_QUIT = 1,
--      MMAL_MSG_TYPE_SERVICE_CLOSED,
--      MMAL_MSG_TYPE_GET_VERSION,
--      MMAL_MSG_TYPE_COMPONENT_CREATE,
--      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
--      MMAL_MSG_TYPE_COMPONENT_ENABLE,
--      MMAL_MSG_TYPE_COMPONENT_DISABLE,
--      MMAL_MSG_TYPE_PORT_INFO_GET,
--      MMAL_MSG_TYPE_PORT_INFO_SET,
--      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
--      MMAL_MSG_TYPE_BUFFER_FROM_HOST,
--      MMAL_MSG_TYPE_BUFFER_TO_HOST,
--      MMAL_MSG_TYPE_GET_STATS,
--      MMAL_MSG_TYPE_PORT_PARAMETER_SET,
--      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
--      MMAL_MSG_TYPE_EVENT_TO_HOST,
--      MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
--      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
--      MMAL_MSG_TYPE_CONSUME_MEM,
--      MMAL_MSG_TYPE_LMK,                      /* 20 */
--      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
--      MMAL_MSG_TYPE_DRM_GET_LHS32,
--      MMAL_MSG_TYPE_DRM_GET_TIME,
--      MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
--      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
--      MMAL_MSG_TYPE_HOST_LOG,
--      MMAL_MSG_TYPE_MSG_LAST
--};
--
--/* port action request messages differ depending on the action type */
--enum mmal_msg_port_action_type {
--      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
--      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
--      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
--      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
--      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
--      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
--      MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
--};
--
--struct mmal_msg_header {
--      u32 magic;
--      u32 type;       /* enum mmal_msg_type */
--
--      /* Opaque handle to the control service */
--      u32 control_service;
--
--      u32 context;    /* a u32 per message context */
--      u32 status;     /* The status of the vchiq operation */
--      u32 padding;
--};
--
--/* Send from VC to host to report version */
--struct mmal_msg_version {
--      u32 flags;
--      u32 major;
--      u32 minor;
--      u32 minimum;
--};
--
--/* request to VC to create component */
--struct mmal_msg_component_create {
--      u32 client_component;   /* component context */
--      char name[128];
--      u32 pid;                /* For debug */
--};
--
--/* reply from VC to component creation request */
--struct mmal_msg_component_create_reply {
--      u32 status;     /* enum mmal_msg_status - how does this differ to
--                       * the one in the header?
--                       */
--      u32 component_handle; /* VideoCore handle for component */
--      u32 input_num;        /* Number of input ports */
--      u32 output_num;       /* Number of output ports */
--      u32 clock_num;        /* Number of clock ports */
--};
--
--/* request to VC to destroy a component */
--struct mmal_msg_component_destroy {
--      u32 component_handle;
--};
--
--struct mmal_msg_component_destroy_reply {
--      u32 status; /* The component destruction status */
--};
--
--/* request and reply to VC to enable a component */
--struct mmal_msg_component_enable {
--      u32 component_handle;
--};
--
--struct mmal_msg_component_enable_reply {
--      u32 status; /* The component enable status */
--};
--
--/* request and reply to VC to disable a component */
--struct mmal_msg_component_disable {
--      u32 component_handle;
--};
--
--struct mmal_msg_component_disable_reply {
--      u32 status; /* The component disable status */
--};
--
--/* request to VC to get port information */
--struct mmal_msg_port_info_get {
--      u32 component_handle;  /* component handle port is associated with */
--      u32 port_type;         /* enum mmal_msg_port_type */
--      u32 index;             /* port index to query */
--};
--
--/* reply from VC to get port info request */
--struct mmal_msg_port_info_get_reply {
--      u32 status;             /* enum mmal_msg_status */
--      u32 component_handle;   /* component handle port is associated with */
--      u32 port_type;          /* enum mmal_msg_port_type */
--      u32 port_index;         /* port indexed in query */
--      s32 found;              /* unused */
--      u32 port_handle;        /* Handle to use for this port */
--      struct mmal_port port;
--      struct mmal_es_format format; /* elementary stream format */
--      union mmal_es_specific_format es; /* es type specific data */
--      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
--};
--
--/* request to VC to set port information */
--struct mmal_msg_port_info_set {
--      u32 component_handle;
--      u32 port_type;          /* enum mmal_msg_port_type */
--      u32 port_index;         /* port indexed in query */
--      struct mmal_port port;
--      struct mmal_es_format format;
--      union mmal_es_specific_format es;
--      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
--};
--
--/* reply from VC to port info set request */
--struct mmal_msg_port_info_set_reply {
--      u32 status;
--      u32 component_handle;   /* component handle port is associated with */
--      u32 port_type;          /* enum mmal_msg_port_type */
--      u32 index;              /* port indexed in query */
--      s32 found;              /* unused */
--      u32 port_handle;        /* Handle to use for this port */
--      struct mmal_port port;
--      struct mmal_es_format format;
--      union mmal_es_specific_format es;
--      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
--};
--
--/* port action requests that take a mmal_port as a parameter */
--struct mmal_msg_port_action_port {
--      u32 component_handle;
--      u32 port_handle;
--      u32 action;             /* enum mmal_msg_port_action_type */
--      struct mmal_port port;
--};
--
--/* port action requests that take handles as a parameter */
--struct mmal_msg_port_action_handle {
--      u32 component_handle;
--      u32 port_handle;
--      u32 action;             /* enum mmal_msg_port_action_type */
--      u32 connect_component_handle;
--      u32 connect_port_handle;
--};
--
--struct mmal_msg_port_action_reply {
--      u32 status;     /* The port action operation status */
--};
--
--/* MMAL buffer transfer */
--
--/* Size of space reserved in a buffer message for short messages. */
--#define MMAL_VC_SHORT_DATA 128
--
--/* Signals that the current payload is the end of the stream of data */
--#define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
--/* Signals that the start of the current payload starts a frame */
--#define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
--/* Signals that the end of the current payload ends a frame */
--#define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
--/* Signals that the current payload contains only complete frames (>1) */
--#define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
--      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
--       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
--/* Signals that the current payload is a keyframe (i.e. self decodable) */
--#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
--/*
-- * Signals a discontinuity in the stream of data (e.g. after a seek).
-- * Can be used for instance by a decoder to reset its state
-- */
--#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
--/*
-- * Signals a buffer containing some kind of config data for the component
-- * (e.g. codec config data)
-- */
--#define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
--/* Signals an encrypted payload */
--#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
--/* Signals a buffer containing side information */
--#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
--/*
-- * Signals a buffer which is the snapshot/postview image from a stills
-- * capture
-- */
--#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
--/* Signals a buffer which contains data known to be corrupted */
--#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
--/* Signals that a buffer failed to be transmitted */
--#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
--
--struct mmal_driver_buffer {
--      u32 magic;
--      u32 component_handle;
--      u32 port_handle;
--      u32 client_context;
--};
--
--/* buffer header */
--struct mmal_buffer_header {
--      u32 next;       /* next header */
--      u32 priv;       /* framework private data */
--      u32 cmd;
--      u32 data;
--      u32 alloc_size;
--      u32 length;
--      u32 offset;
--      u32 flags;
--      s64 pts;
--      s64 dts;
--      u32 type;
--      u32 user_data;
--};
--
--struct mmal_buffer_header_type_specific {
--      union {
--              struct {
--              u32 planes;
--              u32 offset[4];
--              u32 pitch[4];
--              u32 flags;
--              } video;
--      } u;
--};
--
--struct mmal_msg_buffer_from_host {
--      /*
--       *The front 32 bytes of the buffer header are copied
--       * back to us in the reply to allow for context. This
--       * area is used to store two mmal_driver_buffer structures to
--       * allow for multiple concurrent service users.
--       */
--      /* control data */
--      struct mmal_driver_buffer drvbuf;
--
--      /* referenced control data for passthrough buffer management */
--      struct mmal_driver_buffer drvbuf_ref;
--      struct mmal_buffer_header buffer_header; /* buffer header itself */
--      struct mmal_buffer_header_type_specific buffer_header_type_specific;
--      s32 is_zero_copy;
--      s32 has_reference;
--
--      /* allows short data to be xfered in control message */
--      u32 payload_in_message;
--      u8 short_data[MMAL_VC_SHORT_DATA];
--};
--
--/* port parameter setting */
--
--#define MMAL_WORKER_PORT_PARAMETER_SPACE      96
--
--struct mmal_msg_port_parameter_set {
--      u32 component_handle;   /* component */
--      u32 port_handle;        /* port */
--      u32 id;                 /* Parameter ID  */
--      u32 size;               /* Parameter size */
--      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
--};
--
--struct mmal_msg_port_parameter_set_reply {
--      u32 status;     /* enum mmal_msg_status todo: how does this
--                       * differ to the one in the header?
--                       */
--};
--
--/* port parameter getting */
--
--struct mmal_msg_port_parameter_get {
--      u32 component_handle;   /* component */
--      u32 port_handle;        /* port */
--      u32 id;                 /* Parameter ID  */
--      u32 size;               /* Parameter size */
--};
--
--struct mmal_msg_port_parameter_get_reply {
--      u32 status;             /* Status of mmal_port_parameter_get call */
--      u32 id;                 /* Parameter ID  */
--      u32 size;               /* Parameter size */
--      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
--};
--
--/* event messages */
--#define MMAL_WORKER_EVENT_SPACE 256
--
--struct mmal_msg_event_to_host {
--      u32 client_component;   /* component context */
--
--      u32 port_type;
--      u32 port_num;
--
--      u32 cmd;
--      u32 length;
--      u8 data[MMAL_WORKER_EVENT_SPACE];
--      u32 delayed_buffer;
--};
--
--/* all mmal messages are serialised through this structure */
--struct mmal_msg {
--      /* header */
--      struct mmal_msg_header h;
--      /* payload */
--      union {
--              struct mmal_msg_version version;
--
--              struct mmal_msg_component_create component_create;
--              struct mmal_msg_component_create_reply component_create_reply;
--
--              struct mmal_msg_component_destroy component_destroy;
--              struct mmal_msg_component_destroy_reply component_destroy_reply;
--
--              struct mmal_msg_component_enable component_enable;
--              struct mmal_msg_component_enable_reply component_enable_reply;
--
--              struct mmal_msg_component_disable component_disable;
--              struct mmal_msg_component_disable_reply component_disable_reply;
--
--              struct mmal_msg_port_info_get port_info_get;
--              struct mmal_msg_port_info_get_reply port_info_get_reply;
--
--              struct mmal_msg_port_info_set port_info_set;
--              struct mmal_msg_port_info_set_reply port_info_set_reply;
--
--              struct mmal_msg_port_action_port port_action_port;
--              struct mmal_msg_port_action_handle port_action_handle;
--              struct mmal_msg_port_action_reply port_action_reply;
--
--              struct mmal_msg_buffer_from_host buffer_from_host;
--
--              struct mmal_msg_port_parameter_set port_parameter_set;
--              struct mmal_msg_port_parameter_set_reply
--                      port_parameter_set_reply;
--              struct mmal_msg_port_parameter_get
--                      port_parameter_get;
--              struct mmal_msg_port_parameter_get_reply
--                      port_parameter_get_reply;
--
--              struct mmal_msg_event_to_host event_to_host;
--
--              u8 payload[MMAL_MSG_MAX_PAYLOAD];
--      } u;
--};
--#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ /dev/null
-@@ -1,755 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- */
--
--/* common parameters */
--
--/** @name Parameter groups
-- * Parameters are divided into groups, and then allocated sequentially within
-- * a group using an enum.
-- * @{
-- */
--
--#ifndef MMAL_PARAMETERS_H
--#define MMAL_PARAMETERS_H
--
--/** Common parameter ID group, used with many types of component. */
--#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
--/** Camera-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
--/** Video-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
--/** Audio-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
--/** Clock-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
--/** Miracast-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
--
--/* Common parameters */
--enum mmal_parameter_common_type {
--      /**< Never a valid parameter ID */
--      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
--
--              /**< MMAL_PARAMETER_ENCODING_T */
--      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
--              /**< MMAL_PARAMETER_URI_T */
--      MMAL_PARAMETER_URI,
--              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
--      MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
--              /** MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_ZERO_COPY,
--              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
--      MMAL_PARAMETER_BUFFER_REQUIREMENTS,
--              /**< MMAL_PARAMETER_STATISTICS_T */
--      MMAL_PARAMETER_STATISTICS,
--              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
--      MMAL_PARAMETER_CORE_STATISTICS,
--              /**< MMAL_PARAMETER_MEM_USAGE_T */
--      MMAL_PARAMETER_MEM_USAGE,
--              /**< MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
--              /**< MMAL_PARAMETER_SEEK_T */
--      MMAL_PARAMETER_SEEK,
--              /**< MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_POWERMON_ENABLE,
--              /**< MMAL_PARAMETER_LOGGING_T */
--      MMAL_PARAMETER_LOGGING,
--              /**< MMAL_PARAMETER_UINT64_T */
--      MMAL_PARAMETER_SYSTEM_TIME,
--              /**< MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_NO_IMAGE_PADDING,
--};
--
--/* camera parameters */
--
--enum mmal_parameter_camera_type {
--      /* 0 */
--              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
--      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
--              MMAL_PARAMETER_GROUP_CAMERA,
--              /**< Unused? */
--      MMAL_PARAMETER_CAPTURE_QUALITY,
--              /**< @ref MMAL_PARAMETER_INT32_T */
--      MMAL_PARAMETER_ROTATION,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_EXIF_DISABLE,
--              /**< @ref MMAL_PARAMETER_EXIF_T */
--      MMAL_PARAMETER_EXIF,
--              /**< @ref MMAL_PARAM_AWBMODE_T */
--      MMAL_PARAMETER_AWB_MODE,
--              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
--      MMAL_PARAMETER_IMAGE_EFFECT,
--              /**< @ref MMAL_PARAMETER_COLOURFX_T */
--      MMAL_PARAMETER_COLOUR_EFFECT,
--              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
--      MMAL_PARAMETER_FLICKER_AVOID,
--              /**< @ref MMAL_PARAMETER_FLASH_T */
--      MMAL_PARAMETER_FLASH,
--              /**< @ref MMAL_PARAMETER_REDEYE_T */
--      MMAL_PARAMETER_REDEYE,
--              /**< @ref MMAL_PARAMETER_FOCUS_T */
--      MMAL_PARAMETER_FOCUS,
--              /**< Unused? */
--      MMAL_PARAMETER_FOCAL_LENGTHS,
--              /**< @ref MMAL_PARAMETER_INT32_T */
--      MMAL_PARAMETER_EXPOSURE_COMP,
--              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
--      MMAL_PARAMETER_ZOOM,
--              /**< @ref MMAL_PARAMETER_MIRROR_T */
--      MMAL_PARAMETER_MIRROR,
--
--      /* 0x10 */
--              /**< @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_CAMERA_NUM,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_CAPTURE,
--              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
--      MMAL_PARAMETER_EXPOSURE_MODE,
--              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
--      MMAL_PARAMETER_EXP_METERING_MODE,
--              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
--      MMAL_PARAMETER_FOCUS_STATUS,
--              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
--      MMAL_PARAMETER_CAMERA_CONFIG,
--              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
--      MMAL_PARAMETER_CAPTURE_STATUS,
--              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
--      MMAL_PARAMETER_FACE_TRACK,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
--              /**< @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_JPEG_Q_FACTOR,
--              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
--      MMAL_PARAMETER_FRAME_RATE,
--              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
--      MMAL_PARAMETER_USE_STC,
--              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
--      MMAL_PARAMETER_CAMERA_INFO,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_STABILISATION,
--              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
--      MMAL_PARAMETER_FACE_TRACK_RESULTS,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
--
--      /* 0x20 */
--              /**< @ref MMAL_PARAMETER_URI_T */
--      MMAL_PARAMETER_DPF_FILE,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_ENABLE_DPF_FILE,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
--              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
--      MMAL_PARAMETER_CAPTURE_MODE,
--              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
--      MMAL_PARAMETER_FOCUS_REGIONS,
--              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
--      MMAL_PARAMETER_INPUT_CROP,
--              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
--      MMAL_PARAMETER_SENSOR_INFORMATION,
--              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
--      MMAL_PARAMETER_FLASH_SELECT,
--              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
--      MMAL_PARAMETER_FIELD_OF_VIEW,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
--              /**< @ref MMAL_PARAMETER_DRC_T */
--      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
--              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
--      MMAL_PARAMETER_ALGORITHM_CONTROL,
--              /**< @ref MMAL_PARAMETER_RATIONAL_T */
--      MMAL_PARAMETER_SHARPNESS,
--              /**< @ref MMAL_PARAMETER_RATIONAL_T */
--      MMAL_PARAMETER_CONTRAST,
--              /**< @ref MMAL_PARAMETER_RATIONAL_T */
--      MMAL_PARAMETER_BRIGHTNESS,
--              /**< @ref MMAL_PARAMETER_RATIONAL_T */
--      MMAL_PARAMETER_SATURATION,
--
--      /* 0x30 */
--              /**< @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_ISO,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_ANTISHAKE,
--              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
--      MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
--              /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
--              /** @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_CAMERA_MIN_ISO,
--              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
--      MMAL_PARAMETER_CAMERA_USE_CASE,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_CAPTURE_STATS_PASS,
--              /** @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
--              /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_ENABLE_REGISTER_FILE,
--              /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
--              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
--      MMAL_PARAMETER_CONFIGFILE_REGISTERS,
--              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
--      MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_JPEG_ATTACH_LOG,
--              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
--      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
--              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
--      MMAL_PARAMETER_FPS_RANGE,
--              /**< @ref MMAL_PARAMETER_INT32_T */
--      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
--
--      /* 0x40 */
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_FLASH_REQUIRED,
--              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_SW_SATURATION_DISABLE,
--      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_SHUTTER_SPEED,
--              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
--      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
--};
--
--struct mmal_parameter_rational {
--      s32 num;    /**< Numerator */
--      s32 den;    /**< Denominator */
--};
--
--enum mmal_parameter_camera_config_timestamp_mode {
--      MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
--      MMAL_PARAM_TIMESTAMP_MODE_RAW_STC,  /* Use the raw STC value
--                                           * for the frame timestamp
--                                           */
--      MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
--                                            * but subtract the
--                                            * timestamp of the first
--                                            * frame sent to give a
--                                            * zero based timestamp.
--                                            */
--};
--
--struct mmal_parameter_fps_range {
--      /**< Low end of the permitted framerate range */
--      struct mmal_parameter_rational  fps_low;
--      /**< High end of the permitted framerate range */
--      struct mmal_parameter_rational  fps_high;
--};
--
--/* camera configuration parameter */
--struct mmal_parameter_camera_config {
--      /* Parameters for setting up the image pools */
--      u32 max_stills_w; /* Max size of stills capture */
--      u32 max_stills_h;
--      u32 stills_yuv422; /* Allow YUV422 stills capture */
--      u32 one_shot_stills; /* Continuous or one shot stills captures. */
--
--      u32 max_preview_video_w; /* Max size of the preview or video
--                                * capture frames
--                                */
--      u32 max_preview_video_h;
--      u32 num_preview_video_frames;
--
--      /** Sets the height of the circular buffer for stills capture. */
--      u32 stills_capture_circular_buffer_height;
--
--      /** Allows preview/encode to resume as fast as possible after the stills
--       * input frame has been received, and then processes the still frame in
--       * the background whilst preview/encode has resumed.
--       * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
--       */
--      u32 fast_preview_resume;
--
--      /** Selects algorithm for timestamping frames if
--       * there is no clock component connected.
--       * enum mmal_parameter_camera_config_timestamp_mode
--       */
--      s32 use_stc_timestamp;
--};
--
--enum mmal_parameter_exposuremode {
--      MMAL_PARAM_EXPOSUREMODE_OFF,
--      MMAL_PARAM_EXPOSUREMODE_AUTO,
--      MMAL_PARAM_EXPOSUREMODE_NIGHT,
--      MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
--      MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
--      MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
--      MMAL_PARAM_EXPOSUREMODE_SPORTS,
--      MMAL_PARAM_EXPOSUREMODE_SNOW,
--      MMAL_PARAM_EXPOSUREMODE_BEACH,
--      MMAL_PARAM_EXPOSUREMODE_VERYLONG,
--      MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
--      MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
--      MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
--};
--
--enum mmal_parameter_exposuremeteringmode {
--      MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
--      MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
--      MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
--      MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
--};
--
--enum mmal_parameter_awbmode {
--      MMAL_PARAM_AWBMODE_OFF,
--      MMAL_PARAM_AWBMODE_AUTO,
--      MMAL_PARAM_AWBMODE_SUNLIGHT,
--      MMAL_PARAM_AWBMODE_CLOUDY,
--      MMAL_PARAM_AWBMODE_SHADE,
--      MMAL_PARAM_AWBMODE_TUNGSTEN,
--      MMAL_PARAM_AWBMODE_FLUORESCENT,
--      MMAL_PARAM_AWBMODE_INCANDESCENT,
--      MMAL_PARAM_AWBMODE_FLASH,
--      MMAL_PARAM_AWBMODE_HORIZON,
--};
--
--enum mmal_parameter_imagefx {
--      MMAL_PARAM_IMAGEFX_NONE,
--      MMAL_PARAM_IMAGEFX_NEGATIVE,
--      MMAL_PARAM_IMAGEFX_SOLARIZE,
--      MMAL_PARAM_IMAGEFX_POSTERIZE,
--      MMAL_PARAM_IMAGEFX_WHITEBOARD,
--      MMAL_PARAM_IMAGEFX_BLACKBOARD,
--      MMAL_PARAM_IMAGEFX_SKETCH,
--      MMAL_PARAM_IMAGEFX_DENOISE,
--      MMAL_PARAM_IMAGEFX_EMBOSS,
--      MMAL_PARAM_IMAGEFX_OILPAINT,
--      MMAL_PARAM_IMAGEFX_HATCH,
--      MMAL_PARAM_IMAGEFX_GPEN,
--      MMAL_PARAM_IMAGEFX_PASTEL,
--      MMAL_PARAM_IMAGEFX_WATERCOLOUR,
--      MMAL_PARAM_IMAGEFX_FILM,
--      MMAL_PARAM_IMAGEFX_BLUR,
--      MMAL_PARAM_IMAGEFX_SATURATION,
--      MMAL_PARAM_IMAGEFX_COLOURSWAP,
--      MMAL_PARAM_IMAGEFX_WASHEDOUT,
--      MMAL_PARAM_IMAGEFX_POSTERISE,
--      MMAL_PARAM_IMAGEFX_COLOURPOINT,
--      MMAL_PARAM_IMAGEFX_COLOURBALANCE,
--      MMAL_PARAM_IMAGEFX_CARTOON,
--};
--
--enum MMAL_PARAM_FLICKERAVOID_T {
--      MMAL_PARAM_FLICKERAVOID_OFF,
--      MMAL_PARAM_FLICKERAVOID_AUTO,
--      MMAL_PARAM_FLICKERAVOID_50HZ,
--      MMAL_PARAM_FLICKERAVOID_60HZ,
--      MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
--};
--
--struct mmal_parameter_awbgains {
--      struct mmal_parameter_rational r_gain;  /**< Red gain */
--      struct mmal_parameter_rational b_gain;  /**< Blue gain */
--};
--
--/** Manner of video rate control */
--enum mmal_parameter_rate_control_mode {
--      MMAL_VIDEO_RATECONTROL_DEFAULT,
--      MMAL_VIDEO_RATECONTROL_VARIABLE,
--      MMAL_VIDEO_RATECONTROL_CONSTANT,
--      MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
--      MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
--};
--
--enum mmal_video_profile {
--      MMAL_VIDEO_PROFILE_H263_BASELINE,
--      MMAL_VIDEO_PROFILE_H263_H320CODING,
--      MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
--      MMAL_VIDEO_PROFILE_H263_ISWV2,
--      MMAL_VIDEO_PROFILE_H263_ISWV3,
--      MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
--      MMAL_VIDEO_PROFILE_H263_INTERNET,
--      MMAL_VIDEO_PROFILE_H263_INTERLACE,
--      MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
--      MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
--      MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
--      MMAL_VIDEO_PROFILE_MP4V_CORE,
--      MMAL_VIDEO_PROFILE_MP4V_MAIN,
--      MMAL_VIDEO_PROFILE_MP4V_NBIT,
--      MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
--      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
--      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
--      MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
--      MMAL_VIDEO_PROFILE_MP4V_HYBRID,
--      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
--      MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
--      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
--      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
--      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
--      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
--      MMAL_VIDEO_PROFILE_H264_BASELINE,
--      MMAL_VIDEO_PROFILE_H264_MAIN,
--      MMAL_VIDEO_PROFILE_H264_EXTENDED,
--      MMAL_VIDEO_PROFILE_H264_HIGH,
--      MMAL_VIDEO_PROFILE_H264_HIGH10,
--      MMAL_VIDEO_PROFILE_H264_HIGH422,
--      MMAL_VIDEO_PROFILE_H264_HIGH444,
--      MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
--      MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
--};
--
--enum mmal_video_level {
--      MMAL_VIDEO_LEVEL_H263_10,
--      MMAL_VIDEO_LEVEL_H263_20,
--      MMAL_VIDEO_LEVEL_H263_30,
--      MMAL_VIDEO_LEVEL_H263_40,
--      MMAL_VIDEO_LEVEL_H263_45,
--      MMAL_VIDEO_LEVEL_H263_50,
--      MMAL_VIDEO_LEVEL_H263_60,
--      MMAL_VIDEO_LEVEL_H263_70,
--      MMAL_VIDEO_LEVEL_MP4V_0,
--      MMAL_VIDEO_LEVEL_MP4V_0b,
--      MMAL_VIDEO_LEVEL_MP4V_1,
--      MMAL_VIDEO_LEVEL_MP4V_2,
--      MMAL_VIDEO_LEVEL_MP4V_3,
--      MMAL_VIDEO_LEVEL_MP4V_4,
--      MMAL_VIDEO_LEVEL_MP4V_4a,
--      MMAL_VIDEO_LEVEL_MP4V_5,
--      MMAL_VIDEO_LEVEL_MP4V_6,
--      MMAL_VIDEO_LEVEL_H264_1,
--      MMAL_VIDEO_LEVEL_H264_1b,
--      MMAL_VIDEO_LEVEL_H264_11,
--      MMAL_VIDEO_LEVEL_H264_12,
--      MMAL_VIDEO_LEVEL_H264_13,
--      MMAL_VIDEO_LEVEL_H264_2,
--      MMAL_VIDEO_LEVEL_H264_21,
--      MMAL_VIDEO_LEVEL_H264_22,
--      MMAL_VIDEO_LEVEL_H264_3,
--      MMAL_VIDEO_LEVEL_H264_31,
--      MMAL_VIDEO_LEVEL_H264_32,
--      MMAL_VIDEO_LEVEL_H264_4,
--      MMAL_VIDEO_LEVEL_H264_41,
--      MMAL_VIDEO_LEVEL_H264_42,
--      MMAL_VIDEO_LEVEL_H264_5,
--      MMAL_VIDEO_LEVEL_H264_51,
--      MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
--};
--
--struct mmal_parameter_video_profile {
--      enum mmal_video_profile profile;
--      enum mmal_video_level level;
--};
--
--/* video parameters */
--
--enum mmal_parameter_video_type {
--      /** @ref MMAL_DISPLAYREGION_T */
--      MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
--
--      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
--      MMAL_PARAMETER_SUPPORTED_PROFILES,
--
--      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
--      MMAL_PARAMETER_PROFILE,
--
--      /** @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_INTRAPERIOD,
--
--      /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
--      MMAL_PARAMETER_RATECONTROL,
--
--      /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
--      MMAL_PARAMETER_NALUNITFORMAT,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
--
--      /** @ref MMAL_PARAMETER_UINT32_T.
--       * Setting the value to zero resets to the default (one slice per
--       * frame).
--       */
--      MMAL_PARAMETER_MB_ROWS_PER_SLICE,
--
--      /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
--      MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
--
--      /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
--      MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
--
--      /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
--      MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
--      MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
--      /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
--      MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
--      MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
--
--      /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
--      MMAL_PARAMETER_VIDEO_BIT_RATE,
--
--      /** @ref MMAL_PARAMETER_FRAME_RATE_T */
--      MMAL_PARAMETER_VIDEO_FRAME_RATE,
--
--      /** @ref MMAL_PARAMETER_UINT32_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
--
--      /** @ref MMAL_PARAMETER_UINT32_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
--
--      /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
--
--      MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
--      /** @ref MMAL_PARAMETER_UINT32_T.
--       * Changing this parameter from the default can reduce frame rate
--       * because image buffers need to be re-pitched.
--       */
--      MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
--
--      /** @ref MMAL_PARAMETER_UINT32_T.
--       * Changing this parameter from the default can reduce frame rate
--       * because image buffers need to be re-pitched.
--       */
--      MMAL_PARAMETER_VIDEO_ALIGN_VERT,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
--      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
--
--      /** @ref MMAL_PARAMETER_UINT32_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
--
--      /**< @ref MMAL_PARAMETER_UINT32_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
--
--      /**< @ref MMAL_PARAMETER_UINT32_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
--
--      /** @ref MMAL_PARAMETER_UINT32_T */
--      MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
--
--      /** @ref MMAL_PARAMETER_UINT32_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
--
--      /* H264 specific parameters */
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
--
--      /** @ref MMAL_PARAMETER_UINT32_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
--
--      /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
--      MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
--
--      /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
--      MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
--
--      /** @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
--
--      /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
--      MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
--
--      /** @ref MMAL_PARAMETER_BYTES_T */
--      MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3,
--
--      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS,
--
--      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
--
--      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
--};
--
--/** Valid mirror modes */
--enum mmal_parameter_mirror {
--      MMAL_PARAM_MIRROR_NONE,
--      MMAL_PARAM_MIRROR_VERTICAL,
--      MMAL_PARAM_MIRROR_HORIZONTAL,
--      MMAL_PARAM_MIRROR_BOTH,
--};
--
--enum mmal_parameter_displaytransform {
--      MMAL_DISPLAY_ROT0 = 0,
--      MMAL_DISPLAY_MIRROR_ROT0 = 1,
--      MMAL_DISPLAY_MIRROR_ROT180 = 2,
--      MMAL_DISPLAY_ROT180 = 3,
--      MMAL_DISPLAY_MIRROR_ROT90 = 4,
--      MMAL_DISPLAY_ROT270 = 5,
--      MMAL_DISPLAY_ROT90 = 6,
--      MMAL_DISPLAY_MIRROR_ROT270 = 7,
--};
--
--enum mmal_parameter_displaymode {
--      MMAL_DISPLAY_MODE_FILL = 0,
--      MMAL_DISPLAY_MODE_LETTERBOX = 1,
--};
--
--enum mmal_parameter_displayset {
--      MMAL_DISPLAY_SET_NONE = 0,
--      MMAL_DISPLAY_SET_NUM = 1,
--      MMAL_DISPLAY_SET_FULLSCREEN = 2,
--      MMAL_DISPLAY_SET_TRANSFORM = 4,
--      MMAL_DISPLAY_SET_DEST_RECT = 8,
--      MMAL_DISPLAY_SET_SRC_RECT = 0x10,
--      MMAL_DISPLAY_SET_MODE = 0x20,
--      MMAL_DISPLAY_SET_PIXEL = 0x40,
--      MMAL_DISPLAY_SET_NOASPECT = 0x80,
--      MMAL_DISPLAY_SET_LAYER = 0x100,
--      MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
--      MMAL_DISPLAY_SET_ALPHA = 0x400,
--};
--
--/* rectangle, used lots so it gets its own struct */
--struct vchiq_mmal_rect {
--      s32 x;
--      s32 y;
--      s32 width;
--      s32 height;
--};
--
--struct mmal_parameter_displayregion {
--      /** Bitfield that indicates which fields are set and should be
--       * used. All other fields will maintain their current value.
--       * \ref MMAL_DISPLAYSET_T defines the bits that can be
--       * combined.
--       */
--      u32 set;
--
--      /** Describes the display output device, with 0 typically
--       * being a directly connected LCD display.  The actual values
--       * will depend on the hardware.  Code using hard-wired numbers
--       * (e.g. 2) is certain to fail.
--       */
--
--      u32 display_num;
--      /** Indicates that we are using the full device screen area,
--       * rather than a window of the display.  If zero, then
--       * dest_rect is used to specify a region of the display to
--       * use.
--       */
--
--      s32 fullscreen;
--      /** Indicates any rotation or flipping used to map frames onto
--       * the natural display orientation.
--       */
--      u32 transform; /* enum mmal_parameter_displaytransform */
--
--      /** Where to display the frame within the screen, if
--       * fullscreen is zero.
--       */
--      struct vchiq_mmal_rect dest_rect;
--
--      /** Indicates which area of the frame to display. If all
--       * values are zero, the whole frame will be used.
--       */
--      struct vchiq_mmal_rect src_rect;
--
--      /** If set to non-zero, indicates that any display scaling
--       * should disregard the aspect ratio of the frame region being
--       * displayed.
--       */
--      s32 noaspect;
--
--      /** Indicates how the image should be scaled to fit the
--       * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
--       * that the image should fill the screen by potentially
--       * cropping the frames.  Setting \code mode \endcode to \code
--       * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
--       * source region should be displayed and black bars added if
--       * necessary.
--       */
--      u32 mode; /* enum mmal_parameter_displaymode */
--
--      /** If non-zero, defines the width of a source pixel relative
--       * to \code pixel_y \endcode.  If zero, then pixels default to
--       * being square.
--       */
--      u32 pixel_x;
--
--      /** If non-zero, defines the height of a source pixel relative
--       * to \code pixel_x \endcode.  If zero, then pixels default to
--       * being square.
--       */
--      u32 pixel_y;
--
--      /** Sets the relative depth of the images, with greater values
--       * being in front of smaller values.
--       */
--      u32 layer;
--
--      /** Set to non-zero to ensure copy protection is used on
--       * output.
--       */
--      s32 copyprotect_required;
--
--      /** Level of opacity of the layer, where zero is fully
--       * transparent and 255 is fully opaque.
--       */
--      u32 alpha;
--};
--
--#define MMAL_MAX_IMAGEFX_PARAMETERS 5
--
--struct mmal_parameter_imagefx_parameters {
--      enum mmal_parameter_imagefx effect;
--      u32 num_effect_params;
--      u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
--};
--
--#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4
--#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2
--#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16
--
--struct mmal_parameter_camera_info_camera_t {
--      u32    port_id;
--      u32    max_width;
--      u32    max_height;
--      u32    lens_present;
--      u8     camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN];
--};
--
--enum mmal_parameter_camera_info_flash_type_t {
--      /* Make values explicit to ensure they match values in config ini */
--      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0,
--      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED   = 1,
--      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2,
--      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF
--};
--
--struct mmal_parameter_camera_info_flash_t {
--      enum mmal_parameter_camera_info_flash_type_t flash_type;
--};
--
--struct mmal_parameter_camera_info_t {
--      u32                            num_cameras;
--      u32                            num_flashes;
--      struct mmal_parameter_camera_info_camera_t
--                              cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
--      struct mmal_parameter_camera_info_flash_t
--                              flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
--};
--
--#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
-+++ /dev/null
-@@ -1,166 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- *          Dave Stevenson @ Broadcom
-- *            (now dave.stevenson@raspberrypi.org)
-- *          Simon Mellor @ Broadcom
-- *          Luke Diamand @ Broadcom
-- *
-- * MMAL interface to VCHIQ message passing
-- */
--
--#ifndef MMAL_VCHIQ_H
--#define MMAL_VCHIQ_H
--
--#include "mmal-msg-format.h"
--
--#define MAX_PORT_COUNT 4
--
--/* Maximum size of the format extradata. */
--#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
--
--struct vchiq_mmal_instance;
--
--enum vchiq_mmal_es_type {
--      MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
--      MMAL_ES_TYPE_CONTROL,     /**< Elementary stream of control commands */
--      MMAL_ES_TYPE_AUDIO,       /**< Audio elementary stream */
--      MMAL_ES_TYPE_VIDEO,       /**< Video elementary stream */
--      MMAL_ES_TYPE_SUBPICTURE   /**< Sub-picture elementary stream */
--};
--
--struct vchiq_mmal_port_buffer {
--      unsigned int num; /* number of buffers */
--      u32 size; /* size of buffers */
--      u32 alignment; /* alignment of buffers */
--};
--
--struct vchiq_mmal_port;
--
--typedef void (*vchiq_mmal_buffer_cb)(
--              struct vchiq_mmal_instance  *instance,
--              struct vchiq_mmal_port *port,
--              int status, struct mmal_buffer *buffer,
--              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
--
--struct vchiq_mmal_port {
--      bool enabled;
--      u32 handle;
--      u32 type; /* port type, cached to use on port info set */
--      u32 index; /* port index, cached to use on port info set */
--
--      /* component port belongs to, allows simple deref */
--      struct vchiq_mmal_component *component;
--
--      struct vchiq_mmal_port *connected; /* port conencted to */
--
--      /* buffer info */
--      struct vchiq_mmal_port_buffer minimum_buffer;
--      struct vchiq_mmal_port_buffer recommended_buffer;
--      struct vchiq_mmal_port_buffer current_buffer;
--
--      /* stream format */
--      struct mmal_es_format_local format;
--      /* elementary stream format */
--      union mmal_es_specific_format es;
--
--      /* data buffers to fill */
--      struct list_head buffers;
--      /* lock to serialise adding and removing buffers from list */
--      spinlock_t slock;
--
--      /* Count of buffers the VPU has yet to return */
--      atomic_t buffers_with_vpu;
--      /* callback on buffer completion */
--      vchiq_mmal_buffer_cb buffer_cb;
--      /* callback context */
--      void *cb_ctx;
--};
--
--struct vchiq_mmal_component {
--      bool enabled;
--      u32 handle;  /* VideoCore handle for component */
--      u32 inputs;  /* Number of input ports */
--      u32 outputs; /* Number of output ports */
--      u32 clocks;  /* Number of clock ports */
--      struct vchiq_mmal_port control; /* control port */
--      struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
--      struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
--      struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
--};
--
--int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
--int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
--
--/* Initialise a mmal component and its ports
-- *
-- */
--int vchiq_mmal_component_init(
--              struct vchiq_mmal_instance *instance,
--              const char *name,
--              struct vchiq_mmal_component **component_out);
--
--int vchiq_mmal_component_finalise(
--              struct vchiq_mmal_instance *instance,
--              struct vchiq_mmal_component *component);
--
--int vchiq_mmal_component_enable(
--              struct vchiq_mmal_instance *instance,
--              struct vchiq_mmal_component *component);
--
--int vchiq_mmal_component_disable(
--              struct vchiq_mmal_instance *instance,
--              struct vchiq_mmal_component *component);
--
--/* enable a mmal port
-- *
-- * enables a port and if a buffer callback provided enque buffer
-- * headers as appropriate for the port.
-- */
--int vchiq_mmal_port_enable(
--              struct vchiq_mmal_instance *instance,
--              struct vchiq_mmal_port *port,
--              vchiq_mmal_buffer_cb buffer_cb);
--
--/* disable a port
-- *
-- * disable a port will dequeue any pending buffers
-- */
--int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
--                          struct vchiq_mmal_port *port);
--
--int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
--                                struct vchiq_mmal_port *port,
--                                u32 parameter,
--                                void *value,
--                                u32 value_size);
--
--int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
--                                struct vchiq_mmal_port *port,
--                                u32 parameter,
--                                void *value,
--                                u32 *value_size);
--
--int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
--                             struct vchiq_mmal_port *port);
--
--int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
--                                 struct vchiq_mmal_port *src,
--                                 struct vchiq_mmal_port *dst);
--
--int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
--                     u32 *major_out,
--                     u32 *minor_out);
--
--int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
--                           struct vchiq_mmal_port *port,
--                           struct mmal_buffer *buf);
--
--int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
--                        struct mmal_buffer *buf);
--int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
--#endif /* MMAL_VCHIQ_H */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -0,0 +1,61 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ *
-+ * MMAL structures
-+ *
-+ */
-+#ifndef MMAL_COMMON_H
-+#define MMAL_COMMON_H
-+
-+#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
-+#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
-+
-+/** Special value signalling that time is not known */
-+#define MMAL_TIME_UNKNOWN BIT_ULL(63)
-+
-+struct mmal_msg_context;
-+
-+/* mapping between v4l and mmal video modes */
-+struct mmal_fmt {
-+      char  *name;
-+      u32   fourcc;          /* v4l2 format id */
-+      int   flags;           /* v4l2 flags field */
-+      u32   mmal;
-+      int   depth;
-+      u32   mmal_component;  /* MMAL component index to be used to encode */
-+      u32   ybbp;            /* depth of first Y plane for planar formats */
-+      bool  remove_padding;  /* Does the GPU have to remove padding,
-+                              * or can we do hide padding via bytesperline.
-+                              */
-+};
-+
-+/* buffer for one video frame */
-+struct mmal_buffer {
-+      /* v4l buffer data -- must be first */
-+      struct vb2_v4l2_buffer  vb;
-+
-+      /* list of buffers available */
-+      struct list_head        list;
-+
-+      void *buffer; /* buffer pointer */
-+      unsigned long buffer_size; /* size of allocated buffer */
-+
-+      struct mmal_msg_context *msg_context;
-+};
-+
-+/* */
-+struct mmal_colourfx {
-+      s32 enable;
-+      u32 u;
-+      u32 v;
-+};
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
-@@ -0,0 +1,124 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ */
-+#ifndef MMAL_ENCODINGS_H
-+#define MMAL_ENCODINGS_H
-+
-+#define MMAL_ENCODING_H264             MMAL_FOURCC('H', '2', '6', '4')
-+#define MMAL_ENCODING_H263             MMAL_FOURCC('H', '2', '6', '3')
-+#define MMAL_ENCODING_MP4V             MMAL_FOURCC('M', 'P', '4', 'V')
-+#define MMAL_ENCODING_MP2V             MMAL_FOURCC('M', 'P', '2', 'V')
-+#define MMAL_ENCODING_MP1V             MMAL_FOURCC('M', 'P', '1', 'V')
-+#define MMAL_ENCODING_WMV3             MMAL_FOURCC('W', 'M', 'V', '3')
-+#define MMAL_ENCODING_WMV2             MMAL_FOURCC('W', 'M', 'V', '2')
-+#define MMAL_ENCODING_WMV1             MMAL_FOURCC('W', 'M', 'V', '1')
-+#define MMAL_ENCODING_WVC1             MMAL_FOURCC('W', 'V', 'C', '1')
-+#define MMAL_ENCODING_VP8              MMAL_FOURCC('V', 'P', '8', ' ')
-+#define MMAL_ENCODING_VP7              MMAL_FOURCC('V', 'P', '7', ' ')
-+#define MMAL_ENCODING_VP6              MMAL_FOURCC('V', 'P', '6', ' ')
-+#define MMAL_ENCODING_THEORA           MMAL_FOURCC('T', 'H', 'E', 'O')
-+#define MMAL_ENCODING_SPARK            MMAL_FOURCC('S', 'P', 'R', 'K')
-+#define MMAL_ENCODING_MJPEG            MMAL_FOURCC('M', 'J', 'P', 'G')
-+
-+#define MMAL_ENCODING_JPEG             MMAL_FOURCC('J', 'P', 'E', 'G')
-+#define MMAL_ENCODING_GIF              MMAL_FOURCC('G', 'I', 'F', ' ')
-+#define MMAL_ENCODING_PNG              MMAL_FOURCC('P', 'N', 'G', ' ')
-+#define MMAL_ENCODING_PPM              MMAL_FOURCC('P', 'P', 'M', ' ')
-+#define MMAL_ENCODING_TGA              MMAL_FOURCC('T', 'G', 'A', ' ')
-+#define MMAL_ENCODING_BMP              MMAL_FOURCC('B', 'M', 'P', ' ')
-+
-+#define MMAL_ENCODING_I420             MMAL_FOURCC('I', '4', '2', '0')
-+#define MMAL_ENCODING_I420_SLICE       MMAL_FOURCC('S', '4', '2', '0')
-+#define MMAL_ENCODING_YV12             MMAL_FOURCC('Y', 'V', '1', '2')
-+#define MMAL_ENCODING_I422             MMAL_FOURCC('I', '4', '2', '2')
-+#define MMAL_ENCODING_I422_SLICE       MMAL_FOURCC('S', '4', '2', '2')
-+#define MMAL_ENCODING_YUYV             MMAL_FOURCC('Y', 'U', 'Y', 'V')
-+#define MMAL_ENCODING_YVYU             MMAL_FOURCC('Y', 'V', 'Y', 'U')
-+#define MMAL_ENCODING_UYVY             MMAL_FOURCC('U', 'Y', 'V', 'Y')
-+#define MMAL_ENCODING_VYUY             MMAL_FOURCC('V', 'Y', 'U', 'Y')
-+#define MMAL_ENCODING_NV12             MMAL_FOURCC('N', 'V', '1', '2')
-+#define MMAL_ENCODING_NV21             MMAL_FOURCC('N', 'V', '2', '1')
-+#define MMAL_ENCODING_ARGB             MMAL_FOURCC('A', 'R', 'G', 'B')
-+#define MMAL_ENCODING_RGBA             MMAL_FOURCC('R', 'G', 'B', 'A')
-+#define MMAL_ENCODING_ABGR             MMAL_FOURCC('A', 'B', 'G', 'R')
-+#define MMAL_ENCODING_BGRA             MMAL_FOURCC('B', 'G', 'R', 'A')
-+#define MMAL_ENCODING_RGB16            MMAL_FOURCC('R', 'G', 'B', '2')
-+#define MMAL_ENCODING_RGB24            MMAL_FOURCC('R', 'G', 'B', '3')
-+#define MMAL_ENCODING_RGB32            MMAL_FOURCC('R', 'G', 'B', '4')
-+#define MMAL_ENCODING_BGR16            MMAL_FOURCC('B', 'G', 'R', '2')
-+#define MMAL_ENCODING_BGR24            MMAL_FOURCC('B', 'G', 'R', '3')
-+#define MMAL_ENCODING_BGR32            MMAL_FOURCC('B', 'G', 'R', '4')
-+
-+/** SAND Video (YUVUV128) format, native format understood by VideoCore.
-+ * This format is *not* opaque - if requested you will receive full frames
-+ * of YUV_UV video.
-+ */
-+#define MMAL_ENCODING_YUVUV128         MMAL_FOURCC('S', 'A', 'N', 'D')
-+
-+/** VideoCore opaque image format, image handles are returned to
-+ * the host but not the actual image data.
-+ */
-+#define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
-+
-+/** An EGL image handle
-+ */
-+#define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
-+
-+/* }@ */
-+
-+/** \name Pre-defined audio encodings */
-+/* @{ */
-+#define MMAL_ENCODING_PCM_UNSIGNED_BE  MMAL_FOURCC('P', 'C', 'M', 'U')
-+#define MMAL_ENCODING_PCM_UNSIGNED_LE  MMAL_FOURCC('p', 'c', 'm', 'u')
-+#define MMAL_ENCODING_PCM_SIGNED_BE    MMAL_FOURCC('P', 'C', 'M', 'S')
-+#define MMAL_ENCODING_PCM_SIGNED_LE    MMAL_FOURCC('p', 'c', 'm', 's')
-+#define MMAL_ENCODING_PCM_FLOAT_BE     MMAL_FOURCC('P', 'C', 'M', 'F')
-+#define MMAL_ENCODING_PCM_FLOAT_LE     MMAL_FOURCC('p', 'c', 'm', 'f')
-+
-+/* Pre-defined H264 encoding variants */
-+
-+/** ISO 14496-10 Annex B byte stream format */
-+#define MMAL_ENCODING_VARIANT_H264_DEFAULT   0
-+/** ISO 14496-15 AVC stream format */
-+#define MMAL_ENCODING_VARIANT_H264_AVC1      MMAL_FOURCC('A', 'V', 'C', '1')
-+/** Implicitly delineated NAL units without emulation prevention */
-+#define MMAL_ENCODING_VARIANT_H264_RAW       MMAL_FOURCC('R', 'A', 'W', ' ')
-+
-+/** \defgroup MmalColorSpace List of pre-defined video color spaces
-+ * This defines a list of common color spaces. This list isn't exhaustive and
-+ * is only provided as a convenience to avoid clients having to use FourCC
-+ * codes directly. However components are allowed to define and use their own
-+ * FourCC codes.
-+ */
-+/* @{ */
-+
-+/** Unknown color space */
-+#define MMAL_COLOR_SPACE_UNKNOWN       0
-+/** ITU-R BT.601-5 [SDTV] */
-+#define MMAL_COLOR_SPACE_ITUR_BT601    MMAL_FOURCC('Y', '6', '0', '1')
-+/** ITU-R BT.709-3 [HDTV] */
-+#define MMAL_COLOR_SPACE_ITUR_BT709    MMAL_FOURCC('Y', '7', '0', '9')
-+/** JPEG JFIF */
-+#define MMAL_COLOR_SPACE_JPEG_JFIF     MMAL_FOURCC('Y', 'J', 'F', 'I')
-+/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
-+#define MMAL_COLOR_SPACE_FCC           MMAL_FOURCC('Y', 'F', 'C', 'C')
-+/** Society of Motion Picture and Television Engineers 240M (1999) */
-+#define MMAL_COLOR_SPACE_SMPTE240M     MMAL_FOURCC('Y', '2', '4', '0')
-+/** ITU-R BT.470-2 System M */
-+#define MMAL_COLOR_SPACE_BT470_2_M     MMAL_FOURCC('Y', '_', '_', 'M')
-+/** ITU-R BT.470-2 System BG */
-+#define MMAL_COLOR_SPACE_BT470_2_BG    MMAL_FOURCC('Y', '_', 'B', 'G')
-+/** JPEG JFIF, but with 16..255 luma */
-+#define MMAL_COLOR_SPACE_JFIF_Y16_255  MMAL_FOURCC('Y', 'Y', '1', '6')
-+/* @} MmalColorSpace List */
-+
-+#endif /* MMAL_ENCODINGS_H */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h
-@@ -0,0 +1,48 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ */
-+
-+#ifndef MMAL_MSG_COMMON_H
-+#define MMAL_MSG_COMMON_H
-+
-+enum mmal_msg_status {
-+      MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
-+      MMAL_MSG_STATUS_ENOMEM,      /**< Out of memory */
-+      MMAL_MSG_STATUS_ENOSPC,      /**< Out of resources other than memory */
-+      MMAL_MSG_STATUS_EINVAL,      /**< Argument is invalid */
-+      MMAL_MSG_STATUS_ENOSYS,      /**< Function not implemented */
-+      MMAL_MSG_STATUS_ENOENT,      /**< No such file or directory */
-+      MMAL_MSG_STATUS_ENXIO,       /**< No such device or address */
-+      MMAL_MSG_STATUS_EIO,         /**< I/O error */
-+      MMAL_MSG_STATUS_ESPIPE,      /**< Illegal seek */
-+      MMAL_MSG_STATUS_ECORRUPT,    /**< Data is corrupt \attention */
-+      MMAL_MSG_STATUS_ENOTREADY,   /**< Component is not ready */
-+      MMAL_MSG_STATUS_ECONFIG,     /**< Component is not configured */
-+      MMAL_MSG_STATUS_EISCONN,     /**< Port is already connected */
-+      MMAL_MSG_STATUS_ENOTCONN,    /**< Port is disconnected */
-+      MMAL_MSG_STATUS_EAGAIN,      /**< Resource temporarily unavailable. */
-+      MMAL_MSG_STATUS_EFAULT,      /**< Bad address */
-+};
-+
-+struct mmal_rect {
-+      s32 x;      /**< x coordinate (from left) */
-+      s32 y;      /**< y coordinate (from top) */
-+      s32 width;  /**< width */
-+      s32 height; /**< height */
-+};
-+
-+struct mmal_rational {
-+      s32 num;    /**< Numerator */
-+      s32 den;    /**< Denominator */
-+};
-+
-+#endif /* MMAL_MSG_COMMON_H */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h
-@@ -0,0 +1,106 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ */
-+
-+#ifndef MMAL_MSG_FORMAT_H
-+#define MMAL_MSG_FORMAT_H
-+
-+#include "mmal-msg-common.h"
-+
-+/* MMAL_ES_FORMAT_T */
-+
-+struct mmal_audio_format {
-+      u32 channels;           /* Number of audio channels */
-+      u32 sample_rate;        /* Sample rate */
-+
-+      u32 bits_per_sample;    /* Bits per sample */
-+      u32 block_align;        /* Size of a block of data */
-+};
-+
-+struct mmal_video_format {
-+      u32 width;              /* Width of frame in pixels */
-+      u32 height;             /* Height of frame in rows of pixels */
-+      struct mmal_rect crop;  /* Visible region of the frame */
-+      struct mmal_rational frame_rate;        /* Frame rate */
-+      struct mmal_rational par;               /* Pixel aspect ratio */
-+
-+      /*
-+       * FourCC specifying the color space of the video stream. See the
-+       * MmalColorSpace "pre-defined color spaces" for some examples.
-+       */
-+      u32 color_space;
-+};
-+
-+struct mmal_subpicture_format {
-+      u32 x_offset;
-+      u32 y_offset;
-+};
-+
-+union mmal_es_specific_format {
-+      struct mmal_audio_format audio;
-+      struct mmal_video_format video;
-+      struct mmal_subpicture_format subpicture;
-+};
-+
-+/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
-+struct mmal_es_format_local {
-+      u32 type;       /* enum mmal_es_type */
-+
-+      u32 encoding;   /* FourCC specifying encoding of the elementary
-+                       * stream.
-+                       */
-+      u32 encoding_variant;   /* FourCC specifying the specific
-+                               * encoding variant of the elementary
-+                               * stream.
-+                               */
-+
-+      union mmal_es_specific_format *es;      /* Type specific
-+                                               * information for the
-+                                               * elementary stream
-+                                               */
-+
-+      u32 bitrate;    /* Bitrate in bits per second */
-+      u32 flags;      /* Flags describing properties of the elementary
-+                       * stream.
-+                       */
-+
-+      u32 extradata_size;     /* Size of the codec specific data */
-+      u8  *extradata;         /* Codec specific data */
-+};
-+
-+/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
-+struct mmal_es_format {
-+      u32 type;       /* enum mmal_es_type */
-+
-+      u32 encoding;   /* FourCC specifying encoding of the elementary
-+                       * stream.
-+                       */
-+      u32 encoding_variant;   /* FourCC specifying the specific
-+                               * encoding variant of the elementary
-+                               * stream.
-+                               */
-+
-+      u32 es; /* Type specific
-+               * information for the
-+               * elementary stream
-+               */
-+
-+      u32 bitrate;    /* Bitrate in bits per second */
-+      u32 flags;      /* Flags describing properties of the elementary
-+                       * stream.
-+                       */
-+
-+      u32 extradata_size;     /* Size of the codec specific data */
-+      u32 extradata;          /* Codec specific data */
-+};
-+
-+#endif /* MMAL_MSG_FORMAT_H */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h
-@@ -0,0 +1,109 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ */
-+
-+/* MMAL_PORT_TYPE_T */
-+enum mmal_port_type {
-+      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
-+      MMAL_PORT_TYPE_CONTROL,         /* Control port */
-+      MMAL_PORT_TYPE_INPUT,           /* Input port */
-+      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
-+      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
-+};
-+
-+/* The port is pass-through and doesn't need buffer headers allocated */
-+#define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
-+/*
-+ *The port wants to allocate the buffer payloads.
-+ * This signals a preference that payload allocation should be done
-+ * on this port for efficiency reasons.
-+ */
-+#define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
-+/*
-+ * The port supports format change events.
-+ * This applies to input ports and is used to let the client know
-+ * whether the port supports being reconfigured via a format
-+ * change event (i.e. without having to disable the port).
-+ */
-+#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
-+
-+/*
-+ * mmal port structure (MMAL_PORT_T)
-+ *
-+ * most elements are informational only, the pointer values for
-+ * interogation messages are generally provided as additional
-+ * structures within the message. When used to set values only the
-+ * buffer_num, buffer_size and userdata parameters are writable.
-+ */
-+struct mmal_port {
-+      u32 priv;       /* Private member used by the framework */
-+      u32 name;       /* Port name. Used for debugging purposes (RO) */
-+
-+      u32 type;       /* Type of the port (RO) enum mmal_port_type */
-+      u16 index;      /* Index of the port in its type list (RO) */
-+      u16 index_all;  /* Index of the port in the list of all ports (RO) */
-+
-+      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
-+      u32 format;     /* Format of the elementary stream */
-+
-+      u32 buffer_num_min;     /* Minimum number of buffers the port
-+                               *   requires (RO).  This is set by the
-+                               *   component.
-+                               */
-+
-+      u32 buffer_size_min;    /* Minimum size of buffers the port
-+                               * requires (RO).  This is set by the
-+                               * component.
-+                               */
-+
-+      u32 buffer_alignment_min;/* Minimum alignment requirement for
-+                                * the buffers (RO).  A value of
-+                                * zero means no special alignment
-+                                * requirements.  This is set by the
-+                                * component.
-+                                */
-+
-+      u32 buffer_num_recommended;     /* Number of buffers the port
-+                                       * recommends for optimal
-+                                       * performance (RO).  A value of
-+                                       * zero means no special
-+                                       * recommendation.  This is set
-+                                       * by the component.
-+                                       */
-+
-+      u32 buffer_size_recommended;    /* Size of buffers the port
-+                                       * recommends for optimal
-+                                       * performance (RO).  A value of
-+                                       * zero means no special
-+                                       * recommendation.  This is set
-+                                       * by the component.
-+                                       */
-+
-+      u32 buffer_num; /* Actual number of buffers the port will use.
-+                       * This is set by the client.
-+                       */
-+
-+      u32 buffer_size; /* Actual maximum size of the buffers that
-+                        * will be sent to the port. This is set by
-+                        * the client.
-+                        */
-+
-+      u32 component;  /* Component this port belongs to (Read Only) */
-+
-+      u32 userdata;   /* Field reserved for use by the client */
-+
-+      u32 capabilities;       /* Flags describing the capabilities of a
-+                               * port (RO).  Bitwise combination of \ref
-+                               * portcapabilities "Port capabilities"
-+                               * values.
-+                               */
-+};
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-@@ -0,0 +1,406 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ */
-+
-+/*
-+ * all the data structures which serialise the MMAL protocol. note
-+ * these are directly mapped onto the recived message data.
-+ *
-+ * BEWARE: They seem to *assume* pointers are u32 and that there is no
-+ * structure padding!
-+ *
-+ * NOTE: this implementation uses kernel types to ensure sizes. Rather
-+ * than assigning values to enums to force their size the
-+ * implementation uses fixed size types and not the enums (though the
-+ * comments have the actual enum type
-+ */
-+#ifndef MMAL_MSG_H
-+#define MMAL_MSG_H
-+
-+#define VC_MMAL_VER 15
-+#define VC_MMAL_MIN_VER 10
-+#define VC_MMAL_SERVER_NAME  MAKE_FOURCC("mmal")
-+
-+/* max total message size is 512 bytes */
-+#define MMAL_MSG_MAX_SIZE 512
-+/* with six 32bit header elements max payload is therefore 488 bytes */
-+#define MMAL_MSG_MAX_PAYLOAD 488
-+
-+#include "mmal-msg-common.h"
-+#include "mmal-msg-format.h"
-+#include "mmal-msg-port.h"
-+
-+enum mmal_msg_type {
-+      MMAL_MSG_TYPE_QUIT = 1,
-+      MMAL_MSG_TYPE_SERVICE_CLOSED,
-+      MMAL_MSG_TYPE_GET_VERSION,
-+      MMAL_MSG_TYPE_COMPONENT_CREATE,
-+      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
-+      MMAL_MSG_TYPE_COMPONENT_ENABLE,
-+      MMAL_MSG_TYPE_COMPONENT_DISABLE,
-+      MMAL_MSG_TYPE_PORT_INFO_GET,
-+      MMAL_MSG_TYPE_PORT_INFO_SET,
-+      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
-+      MMAL_MSG_TYPE_BUFFER_FROM_HOST,
-+      MMAL_MSG_TYPE_BUFFER_TO_HOST,
-+      MMAL_MSG_TYPE_GET_STATS,
-+      MMAL_MSG_TYPE_PORT_PARAMETER_SET,
-+      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
-+      MMAL_MSG_TYPE_EVENT_TO_HOST,
-+      MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
-+      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
-+      MMAL_MSG_TYPE_CONSUME_MEM,
-+      MMAL_MSG_TYPE_LMK,                      /* 20 */
-+      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
-+      MMAL_MSG_TYPE_DRM_GET_LHS32,
-+      MMAL_MSG_TYPE_DRM_GET_TIME,
-+      MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
-+      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
-+      MMAL_MSG_TYPE_HOST_LOG,
-+      MMAL_MSG_TYPE_MSG_LAST
-+};
-+
-+/* port action request messages differ depending on the action type */
-+enum mmal_msg_port_action_type {
-+      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
-+      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
-+      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
-+      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
-+      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
-+      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
-+      MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
-+};
-+
-+struct mmal_msg_header {
-+      u32 magic;
-+      u32 type;       /* enum mmal_msg_type */
-+
-+      /* Opaque handle to the control service */
-+      u32 control_service;
-+
-+      u32 context;    /* a u32 per message context */
-+      u32 status;     /* The status of the vchiq operation */
-+      u32 padding;
-+};
-+
-+/* Send from VC to host to report version */
-+struct mmal_msg_version {
-+      u32 flags;
-+      u32 major;
-+      u32 minor;
-+      u32 minimum;
-+};
-+
-+/* request to VC to create component */
-+struct mmal_msg_component_create {
-+      u32 client_component;   /* component context */
-+      char name[128];
-+      u32 pid;                /* For debug */
-+};
-+
-+/* reply from VC to component creation request */
-+struct mmal_msg_component_create_reply {
-+      u32 status;     /* enum mmal_msg_status - how does this differ to
-+                       * the one in the header?
-+                       */
-+      u32 component_handle; /* VideoCore handle for component */
-+      u32 input_num;        /* Number of input ports */
-+      u32 output_num;       /* Number of output ports */
-+      u32 clock_num;        /* Number of clock ports */
-+};
-+
-+/* request to VC to destroy a component */
-+struct mmal_msg_component_destroy {
-+      u32 component_handle;
-+};
-+
-+struct mmal_msg_component_destroy_reply {
-+      u32 status; /* The component destruction status */
-+};
-+
-+/* request and reply to VC to enable a component */
-+struct mmal_msg_component_enable {
-+      u32 component_handle;
-+};
-+
-+struct mmal_msg_component_enable_reply {
-+      u32 status; /* The component enable status */
-+};
-+
-+/* request and reply to VC to disable a component */
-+struct mmal_msg_component_disable {
-+      u32 component_handle;
-+};
-+
-+struct mmal_msg_component_disable_reply {
-+      u32 status; /* The component disable status */
-+};
-+
-+/* request to VC to get port information */
-+struct mmal_msg_port_info_get {
-+      u32 component_handle;  /* component handle port is associated with */
-+      u32 port_type;         /* enum mmal_msg_port_type */
-+      u32 index;             /* port index to query */
-+};
-+
-+/* reply from VC to get port info request */
-+struct mmal_msg_port_info_get_reply {
-+      u32 status;             /* enum mmal_msg_status */
-+      u32 component_handle;   /* component handle port is associated with */
-+      u32 port_type;          /* enum mmal_msg_port_type */
-+      u32 port_index;         /* port indexed in query */
-+      s32 found;              /* unused */
-+      u32 port_handle;        /* Handle to use for this port */
-+      struct mmal_port port;
-+      struct mmal_es_format format; /* elementary stream format */
-+      union mmal_es_specific_format es; /* es type specific data */
-+      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
-+};
-+
-+/* request to VC to set port information */
-+struct mmal_msg_port_info_set {
-+      u32 component_handle;
-+      u32 port_type;          /* enum mmal_msg_port_type */
-+      u32 port_index;         /* port indexed in query */
-+      struct mmal_port port;
-+      struct mmal_es_format format;
-+      union mmal_es_specific_format es;
-+      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
-+};
-+
-+/* reply from VC to port info set request */
-+struct mmal_msg_port_info_set_reply {
-+      u32 status;
-+      u32 component_handle;   /* component handle port is associated with */
-+      u32 port_type;          /* enum mmal_msg_port_type */
-+      u32 index;              /* port indexed in query */
-+      s32 found;              /* unused */
-+      u32 port_handle;        /* Handle to use for this port */
-+      struct mmal_port port;
-+      struct mmal_es_format format;
-+      union mmal_es_specific_format es;
-+      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
-+};
-+
-+/* port action requests that take a mmal_port as a parameter */
-+struct mmal_msg_port_action_port {
-+      u32 component_handle;
-+      u32 port_handle;
-+      u32 action;             /* enum mmal_msg_port_action_type */
-+      struct mmal_port port;
-+};
-+
-+/* port action requests that take handles as a parameter */
-+struct mmal_msg_port_action_handle {
-+      u32 component_handle;
-+      u32 port_handle;
-+      u32 action;             /* enum mmal_msg_port_action_type */
-+      u32 connect_component_handle;
-+      u32 connect_port_handle;
-+};
-+
-+struct mmal_msg_port_action_reply {
-+      u32 status;     /* The port action operation status */
-+};
-+
-+/* MMAL buffer transfer */
-+
-+/* Size of space reserved in a buffer message for short messages. */
-+#define MMAL_VC_SHORT_DATA 128
-+
-+/* Signals that the current payload is the end of the stream of data */
-+#define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
-+/* Signals that the start of the current payload starts a frame */
-+#define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
-+/* Signals that the end of the current payload ends a frame */
-+#define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
-+/* Signals that the current payload contains only complete frames (>1) */
-+#define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
-+      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
-+       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
-+/* Signals that the current payload is a keyframe (i.e. self decodable) */
-+#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
-+/*
-+ * Signals a discontinuity in the stream of data (e.g. after a seek).
-+ * Can be used for instance by a decoder to reset its state
-+ */
-+#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
-+/*
-+ * Signals a buffer containing some kind of config data for the component
-+ * (e.g. codec config data)
-+ */
-+#define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
-+/* Signals an encrypted payload */
-+#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
-+/* Signals a buffer containing side information */
-+#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
-+/*
-+ * Signals a buffer which is the snapshot/postview image from a stills
-+ * capture
-+ */
-+#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
-+/* Signals a buffer which contains data known to be corrupted */
-+#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
-+/* Signals that a buffer failed to be transmitted */
-+#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
-+
-+struct mmal_driver_buffer {
-+      u32 magic;
-+      u32 component_handle;
-+      u32 port_handle;
-+      u32 client_context;
-+};
-+
-+/* buffer header */
-+struct mmal_buffer_header {
-+      u32 next;       /* next header */
-+      u32 priv;       /* framework private data */
-+      u32 cmd;
-+      u32 data;
-+      u32 alloc_size;
-+      u32 length;
-+      u32 offset;
-+      u32 flags;
-+      s64 pts;
-+      s64 dts;
-+      u32 type;
-+      u32 user_data;
-+};
-+
-+struct mmal_buffer_header_type_specific {
-+      union {
-+              struct {
-+              u32 planes;
-+              u32 offset[4];
-+              u32 pitch[4];
-+              u32 flags;
-+              } video;
-+      } u;
-+};
-+
-+struct mmal_msg_buffer_from_host {
-+      /*
-+       *The front 32 bytes of the buffer header are copied
-+       * back to us in the reply to allow for context. This
-+       * area is used to store two mmal_driver_buffer structures to
-+       * allow for multiple concurrent service users.
-+       */
-+      /* control data */
-+      struct mmal_driver_buffer drvbuf;
-+
-+      /* referenced control data for passthrough buffer management */
-+      struct mmal_driver_buffer drvbuf_ref;
-+      struct mmal_buffer_header buffer_header; /* buffer header itself */
-+      struct mmal_buffer_header_type_specific buffer_header_type_specific;
-+      s32 is_zero_copy;
-+      s32 has_reference;
-+
-+      /* allows short data to be xfered in control message */
-+      u32 payload_in_message;
-+      u8 short_data[MMAL_VC_SHORT_DATA];
-+};
-+
-+/* port parameter setting */
-+
-+#define MMAL_WORKER_PORT_PARAMETER_SPACE      96
-+
-+struct mmal_msg_port_parameter_set {
-+      u32 component_handle;   /* component */
-+      u32 port_handle;        /* port */
-+      u32 id;                 /* Parameter ID  */
-+      u32 size;               /* Parameter size */
-+      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
-+};
-+
-+struct mmal_msg_port_parameter_set_reply {
-+      u32 status;     /* enum mmal_msg_status todo: how does this
-+                       * differ to the one in the header?
-+                       */
-+};
-+
-+/* port parameter getting */
-+
-+struct mmal_msg_port_parameter_get {
-+      u32 component_handle;   /* component */
-+      u32 port_handle;        /* port */
-+      u32 id;                 /* Parameter ID  */
-+      u32 size;               /* Parameter size */
-+};
-+
-+struct mmal_msg_port_parameter_get_reply {
-+      u32 status;             /* Status of mmal_port_parameter_get call */
-+      u32 id;                 /* Parameter ID  */
-+      u32 size;               /* Parameter size */
-+      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
-+};
-+
-+/* event messages */
-+#define MMAL_WORKER_EVENT_SPACE 256
-+
-+struct mmal_msg_event_to_host {
-+      u32 client_component;   /* component context */
-+
-+      u32 port_type;
-+      u32 port_num;
-+
-+      u32 cmd;
-+      u32 length;
-+      u8 data[MMAL_WORKER_EVENT_SPACE];
-+      u32 delayed_buffer;
-+};
-+
-+/* all mmal messages are serialised through this structure */
-+struct mmal_msg {
-+      /* header */
-+      struct mmal_msg_header h;
-+      /* payload */
-+      union {
-+              struct mmal_msg_version version;
-+
-+              struct mmal_msg_component_create component_create;
-+              struct mmal_msg_component_create_reply component_create_reply;
-+
-+              struct mmal_msg_component_destroy component_destroy;
-+              struct mmal_msg_component_destroy_reply component_destroy_reply;
-+
-+              struct mmal_msg_component_enable component_enable;
-+              struct mmal_msg_component_enable_reply component_enable_reply;
-+
-+              struct mmal_msg_component_disable component_disable;
-+              struct mmal_msg_component_disable_reply component_disable_reply;
-+
-+              struct mmal_msg_port_info_get port_info_get;
-+              struct mmal_msg_port_info_get_reply port_info_get_reply;
-+
-+              struct mmal_msg_port_info_set port_info_set;
-+              struct mmal_msg_port_info_set_reply port_info_set_reply;
-+
-+              struct mmal_msg_port_action_port port_action_port;
-+              struct mmal_msg_port_action_handle port_action_handle;
-+              struct mmal_msg_port_action_reply port_action_reply;
-+
-+              struct mmal_msg_buffer_from_host buffer_from_host;
-+
-+              struct mmal_msg_port_parameter_set port_parameter_set;
-+              struct mmal_msg_port_parameter_set_reply
-+                      port_parameter_set_reply;
-+              struct mmal_msg_port_parameter_get
-+                      port_parameter_get;
-+              struct mmal_msg_port_parameter_get_reply
-+                      port_parameter_get_reply;
-+
-+              struct mmal_msg_event_to_host event_to_host;
-+
-+              u8 payload[MMAL_MSG_MAX_PAYLOAD];
-+      } u;
-+};
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-@@ -0,0 +1,755 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ */
-+
-+/* common parameters */
-+
-+/** @name Parameter groups
-+ * Parameters are divided into groups, and then allocated sequentially within
-+ * a group using an enum.
-+ * @{
-+ */
-+
-+#ifndef MMAL_PARAMETERS_H
-+#define MMAL_PARAMETERS_H
-+
-+/** Common parameter ID group, used with many types of component. */
-+#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
-+/** Camera-specific parameter ID group. */
-+#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
-+/** Video-specific parameter ID group. */
-+#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
-+/** Audio-specific parameter ID group. */
-+#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
-+/** Clock-specific parameter ID group. */
-+#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
-+/** Miracast-specific parameter ID group. */
-+#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
-+
-+/* Common parameters */
-+enum mmal_parameter_common_type {
-+      /**< Never a valid parameter ID */
-+      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
-+
-+              /**< MMAL_PARAMETER_ENCODING_T */
-+      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+              /**< MMAL_PARAMETER_URI_T */
-+      MMAL_PARAMETER_URI,
-+              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
-+      MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
-+              /** MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ZERO_COPY,
-+              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
-+      MMAL_PARAMETER_BUFFER_REQUIREMENTS,
-+              /**< MMAL_PARAMETER_STATISTICS_T */
-+      MMAL_PARAMETER_STATISTICS,
-+              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
-+      MMAL_PARAMETER_CORE_STATISTICS,
-+              /**< MMAL_PARAMETER_MEM_USAGE_T */
-+      MMAL_PARAMETER_MEM_USAGE,
-+              /**< MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
-+              /**< MMAL_PARAMETER_SEEK_T */
-+      MMAL_PARAMETER_SEEK,
-+              /**< MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_POWERMON_ENABLE,
-+              /**< MMAL_PARAMETER_LOGGING_T */
-+      MMAL_PARAMETER_LOGGING,
-+              /**< MMAL_PARAMETER_UINT64_T */
-+      MMAL_PARAMETER_SYSTEM_TIME,
-+              /**< MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_NO_IMAGE_PADDING,
-+};
-+
-+/* camera parameters */
-+
-+enum mmal_parameter_camera_type {
-+      /* 0 */
-+              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
-+      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
-+              MMAL_PARAMETER_GROUP_CAMERA,
-+              /**< Unused? */
-+      MMAL_PARAMETER_CAPTURE_QUALITY,
-+              /**< @ref MMAL_PARAMETER_INT32_T */
-+      MMAL_PARAMETER_ROTATION,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_EXIF_DISABLE,
-+              /**< @ref MMAL_PARAMETER_EXIF_T */
-+      MMAL_PARAMETER_EXIF,
-+              /**< @ref MMAL_PARAM_AWBMODE_T */
-+      MMAL_PARAMETER_AWB_MODE,
-+              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
-+      MMAL_PARAMETER_IMAGE_EFFECT,
-+              /**< @ref MMAL_PARAMETER_COLOURFX_T */
-+      MMAL_PARAMETER_COLOUR_EFFECT,
-+              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
-+      MMAL_PARAMETER_FLICKER_AVOID,
-+              /**< @ref MMAL_PARAMETER_FLASH_T */
-+      MMAL_PARAMETER_FLASH,
-+              /**< @ref MMAL_PARAMETER_REDEYE_T */
-+      MMAL_PARAMETER_REDEYE,
-+              /**< @ref MMAL_PARAMETER_FOCUS_T */
-+      MMAL_PARAMETER_FOCUS,
-+              /**< Unused? */
-+      MMAL_PARAMETER_FOCAL_LENGTHS,
-+              /**< @ref MMAL_PARAMETER_INT32_T */
-+      MMAL_PARAMETER_EXPOSURE_COMP,
-+              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
-+      MMAL_PARAMETER_ZOOM,
-+              /**< @ref MMAL_PARAMETER_MIRROR_T */
-+      MMAL_PARAMETER_MIRROR,
-+
-+      /* 0x10 */
-+              /**< @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_CAMERA_NUM,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_CAPTURE,
-+              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
-+      MMAL_PARAMETER_EXPOSURE_MODE,
-+              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
-+      MMAL_PARAMETER_EXP_METERING_MODE,
-+              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
-+      MMAL_PARAMETER_FOCUS_STATUS,
-+              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
-+      MMAL_PARAMETER_CAMERA_CONFIG,
-+              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
-+      MMAL_PARAMETER_CAPTURE_STATUS,
-+              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
-+      MMAL_PARAMETER_FACE_TRACK,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
-+              /**< @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_JPEG_Q_FACTOR,
-+              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
-+      MMAL_PARAMETER_FRAME_RATE,
-+              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
-+      MMAL_PARAMETER_USE_STC,
-+              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
-+      MMAL_PARAMETER_CAMERA_INFO,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_STABILISATION,
-+              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
-+      MMAL_PARAMETER_FACE_TRACK_RESULTS,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
-+
-+      /* 0x20 */
-+              /**< @ref MMAL_PARAMETER_URI_T */
-+      MMAL_PARAMETER_DPF_FILE,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ENABLE_DPF_FILE,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
-+              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
-+      MMAL_PARAMETER_CAPTURE_MODE,
-+              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
-+      MMAL_PARAMETER_FOCUS_REGIONS,
-+              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
-+      MMAL_PARAMETER_INPUT_CROP,
-+              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
-+      MMAL_PARAMETER_SENSOR_INFORMATION,
-+              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
-+      MMAL_PARAMETER_FLASH_SELECT,
-+              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
-+      MMAL_PARAMETER_FIELD_OF_VIEW,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
-+              /**< @ref MMAL_PARAMETER_DRC_T */
-+      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
-+              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
-+      MMAL_PARAMETER_ALGORITHM_CONTROL,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_SHARPNESS,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_CONTRAST,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_BRIGHTNESS,
-+              /**< @ref MMAL_PARAMETER_RATIONAL_T */
-+      MMAL_PARAMETER_SATURATION,
-+
-+      /* 0x30 */
-+              /**< @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_ISO,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ANTISHAKE,
-+              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
-+      MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
-+              /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
-+              /** @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_CAMERA_MIN_ISO,
-+              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
-+      MMAL_PARAMETER_CAMERA_USE_CASE,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_CAPTURE_STATS_PASS,
-+              /** @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
-+              /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_ENABLE_REGISTER_FILE,
-+              /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
-+              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
-+      MMAL_PARAMETER_CONFIGFILE_REGISTERS,
-+              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
-+      MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_JPEG_ATTACH_LOG,
-+              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
-+      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
-+              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
-+      MMAL_PARAMETER_FPS_RANGE,
-+              /**< @ref MMAL_PARAMETER_INT32_T */
-+      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
-+
-+      /* 0x40 */
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_FLASH_REQUIRED,
-+              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_SW_SATURATION_DISABLE,
-+      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_SHUTTER_SPEED,
-+              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
-+      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
-+};
-+
-+struct mmal_parameter_rational {
-+      s32 num;    /**< Numerator */
-+      s32 den;    /**< Denominator */
-+};
-+
-+enum mmal_parameter_camera_config_timestamp_mode {
-+      MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
-+      MMAL_PARAM_TIMESTAMP_MODE_RAW_STC,  /* Use the raw STC value
-+                                           * for the frame timestamp
-+                                           */
-+      MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
-+                                            * but subtract the
-+                                            * timestamp of the first
-+                                            * frame sent to give a
-+                                            * zero based timestamp.
-+                                            */
-+};
-+
-+struct mmal_parameter_fps_range {
-+      /**< Low end of the permitted framerate range */
-+      struct mmal_parameter_rational  fps_low;
-+      /**< High end of the permitted framerate range */
-+      struct mmal_parameter_rational  fps_high;
-+};
-+
-+/* camera configuration parameter */
-+struct mmal_parameter_camera_config {
-+      /* Parameters for setting up the image pools */
-+      u32 max_stills_w; /* Max size of stills capture */
-+      u32 max_stills_h;
-+      u32 stills_yuv422; /* Allow YUV422 stills capture */
-+      u32 one_shot_stills; /* Continuous or one shot stills captures. */
-+
-+      u32 max_preview_video_w; /* Max size of the preview or video
-+                                * capture frames
-+                                */
-+      u32 max_preview_video_h;
-+      u32 num_preview_video_frames;
-+
-+      /** Sets the height of the circular buffer for stills capture. */
-+      u32 stills_capture_circular_buffer_height;
-+
-+      /** Allows preview/encode to resume as fast as possible after the stills
-+       * input frame has been received, and then processes the still frame in
-+       * the background whilst preview/encode has resumed.
-+       * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
-+       */
-+      u32 fast_preview_resume;
-+
-+      /** Selects algorithm for timestamping frames if
-+       * there is no clock component connected.
-+       * enum mmal_parameter_camera_config_timestamp_mode
-+       */
-+      s32 use_stc_timestamp;
-+};
-+
-+enum mmal_parameter_exposuremode {
-+      MMAL_PARAM_EXPOSUREMODE_OFF,
-+      MMAL_PARAM_EXPOSUREMODE_AUTO,
-+      MMAL_PARAM_EXPOSUREMODE_NIGHT,
-+      MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
-+      MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
-+      MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
-+      MMAL_PARAM_EXPOSUREMODE_SPORTS,
-+      MMAL_PARAM_EXPOSUREMODE_SNOW,
-+      MMAL_PARAM_EXPOSUREMODE_BEACH,
-+      MMAL_PARAM_EXPOSUREMODE_VERYLONG,
-+      MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
-+      MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
-+      MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
-+};
-+
-+enum mmal_parameter_exposuremeteringmode {
-+      MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
-+      MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
-+      MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
-+      MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
-+};
-+
-+enum mmal_parameter_awbmode {
-+      MMAL_PARAM_AWBMODE_OFF,
-+      MMAL_PARAM_AWBMODE_AUTO,
-+      MMAL_PARAM_AWBMODE_SUNLIGHT,
-+      MMAL_PARAM_AWBMODE_CLOUDY,
-+      MMAL_PARAM_AWBMODE_SHADE,
-+      MMAL_PARAM_AWBMODE_TUNGSTEN,
-+      MMAL_PARAM_AWBMODE_FLUORESCENT,
-+      MMAL_PARAM_AWBMODE_INCANDESCENT,
-+      MMAL_PARAM_AWBMODE_FLASH,
-+      MMAL_PARAM_AWBMODE_HORIZON,
-+};
-+
-+enum mmal_parameter_imagefx {
-+      MMAL_PARAM_IMAGEFX_NONE,
-+      MMAL_PARAM_IMAGEFX_NEGATIVE,
-+      MMAL_PARAM_IMAGEFX_SOLARIZE,
-+      MMAL_PARAM_IMAGEFX_POSTERIZE,
-+      MMAL_PARAM_IMAGEFX_WHITEBOARD,
-+      MMAL_PARAM_IMAGEFX_BLACKBOARD,
-+      MMAL_PARAM_IMAGEFX_SKETCH,
-+      MMAL_PARAM_IMAGEFX_DENOISE,
-+      MMAL_PARAM_IMAGEFX_EMBOSS,
-+      MMAL_PARAM_IMAGEFX_OILPAINT,
-+      MMAL_PARAM_IMAGEFX_HATCH,
-+      MMAL_PARAM_IMAGEFX_GPEN,
-+      MMAL_PARAM_IMAGEFX_PASTEL,
-+      MMAL_PARAM_IMAGEFX_WATERCOLOUR,
-+      MMAL_PARAM_IMAGEFX_FILM,
-+      MMAL_PARAM_IMAGEFX_BLUR,
-+      MMAL_PARAM_IMAGEFX_SATURATION,
-+      MMAL_PARAM_IMAGEFX_COLOURSWAP,
-+      MMAL_PARAM_IMAGEFX_WASHEDOUT,
-+      MMAL_PARAM_IMAGEFX_POSTERISE,
-+      MMAL_PARAM_IMAGEFX_COLOURPOINT,
-+      MMAL_PARAM_IMAGEFX_COLOURBALANCE,
-+      MMAL_PARAM_IMAGEFX_CARTOON,
-+};
-+
-+enum MMAL_PARAM_FLICKERAVOID_T {
-+      MMAL_PARAM_FLICKERAVOID_OFF,
-+      MMAL_PARAM_FLICKERAVOID_AUTO,
-+      MMAL_PARAM_FLICKERAVOID_50HZ,
-+      MMAL_PARAM_FLICKERAVOID_60HZ,
-+      MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
-+};
-+
-+struct mmal_parameter_awbgains {
-+      struct mmal_parameter_rational r_gain;  /**< Red gain */
-+      struct mmal_parameter_rational b_gain;  /**< Blue gain */
-+};
-+
-+/** Manner of video rate control */
-+enum mmal_parameter_rate_control_mode {
-+      MMAL_VIDEO_RATECONTROL_DEFAULT,
-+      MMAL_VIDEO_RATECONTROL_VARIABLE,
-+      MMAL_VIDEO_RATECONTROL_CONSTANT,
-+      MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
-+      MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
-+};
-+
-+enum mmal_video_profile {
-+      MMAL_VIDEO_PROFILE_H263_BASELINE,
-+      MMAL_VIDEO_PROFILE_H263_H320CODING,
-+      MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
-+      MMAL_VIDEO_PROFILE_H263_ISWV2,
-+      MMAL_VIDEO_PROFILE_H263_ISWV3,
-+      MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
-+      MMAL_VIDEO_PROFILE_H263_INTERNET,
-+      MMAL_VIDEO_PROFILE_H263_INTERLACE,
-+      MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
-+      MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
-+      MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
-+      MMAL_VIDEO_PROFILE_MP4V_CORE,
-+      MMAL_VIDEO_PROFILE_MP4V_MAIN,
-+      MMAL_VIDEO_PROFILE_MP4V_NBIT,
-+      MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
-+      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
-+      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
-+      MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
-+      MMAL_VIDEO_PROFILE_MP4V_HYBRID,
-+      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
-+      MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
-+      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
-+      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
-+      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
-+      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
-+      MMAL_VIDEO_PROFILE_H264_BASELINE,
-+      MMAL_VIDEO_PROFILE_H264_MAIN,
-+      MMAL_VIDEO_PROFILE_H264_EXTENDED,
-+      MMAL_VIDEO_PROFILE_H264_HIGH,
-+      MMAL_VIDEO_PROFILE_H264_HIGH10,
-+      MMAL_VIDEO_PROFILE_H264_HIGH422,
-+      MMAL_VIDEO_PROFILE_H264_HIGH444,
-+      MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
-+      MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
-+};
-+
-+enum mmal_video_level {
-+      MMAL_VIDEO_LEVEL_H263_10,
-+      MMAL_VIDEO_LEVEL_H263_20,
-+      MMAL_VIDEO_LEVEL_H263_30,
-+      MMAL_VIDEO_LEVEL_H263_40,
-+      MMAL_VIDEO_LEVEL_H263_45,
-+      MMAL_VIDEO_LEVEL_H263_50,
-+      MMAL_VIDEO_LEVEL_H263_60,
-+      MMAL_VIDEO_LEVEL_H263_70,
-+      MMAL_VIDEO_LEVEL_MP4V_0,
-+      MMAL_VIDEO_LEVEL_MP4V_0b,
-+      MMAL_VIDEO_LEVEL_MP4V_1,
-+      MMAL_VIDEO_LEVEL_MP4V_2,
-+      MMAL_VIDEO_LEVEL_MP4V_3,
-+      MMAL_VIDEO_LEVEL_MP4V_4,
-+      MMAL_VIDEO_LEVEL_MP4V_4a,
-+      MMAL_VIDEO_LEVEL_MP4V_5,
-+      MMAL_VIDEO_LEVEL_MP4V_6,
-+      MMAL_VIDEO_LEVEL_H264_1,
-+      MMAL_VIDEO_LEVEL_H264_1b,
-+      MMAL_VIDEO_LEVEL_H264_11,
-+      MMAL_VIDEO_LEVEL_H264_12,
-+      MMAL_VIDEO_LEVEL_H264_13,
-+      MMAL_VIDEO_LEVEL_H264_2,
-+      MMAL_VIDEO_LEVEL_H264_21,
-+      MMAL_VIDEO_LEVEL_H264_22,
-+      MMAL_VIDEO_LEVEL_H264_3,
-+      MMAL_VIDEO_LEVEL_H264_31,
-+      MMAL_VIDEO_LEVEL_H264_32,
-+      MMAL_VIDEO_LEVEL_H264_4,
-+      MMAL_VIDEO_LEVEL_H264_41,
-+      MMAL_VIDEO_LEVEL_H264_42,
-+      MMAL_VIDEO_LEVEL_H264_5,
-+      MMAL_VIDEO_LEVEL_H264_51,
-+      MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
-+};
-+
-+struct mmal_parameter_video_profile {
-+      enum mmal_video_profile profile;
-+      enum mmal_video_level level;
-+};
-+
-+/* video parameters */
-+
-+enum mmal_parameter_video_type {
-+      /** @ref MMAL_DISPLAYREGION_T */
-+      MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
-+      MMAL_PARAMETER_SUPPORTED_PROFILES,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
-+      MMAL_PARAMETER_PROFILE,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_INTRAPERIOD,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
-+      MMAL_PARAMETER_RATECONTROL,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
-+      MMAL_PARAMETER_NALUNITFORMAT,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T.
-+       * Setting the value to zero resets to the default (one slice per
-+       * frame).
-+       */
-+      MMAL_PARAMETER_MB_ROWS_PER_SLICE,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
-+      MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
-+      MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
-+      MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
-+      MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
-+      /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
-+      MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
-+      MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
-+      MMAL_PARAMETER_VIDEO_BIT_RATE,
-+
-+      /** @ref MMAL_PARAMETER_FRAME_RATE_T */
-+      MMAL_PARAMETER_VIDEO_FRAME_RATE,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
-+
-+      MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
-+      /** @ref MMAL_PARAMETER_UINT32_T.
-+       * Changing this parameter from the default can reduce frame rate
-+       * because image buffers need to be re-pitched.
-+       */
-+      MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T.
-+       * Changing this parameter from the default can reduce frame rate
-+       * because image buffers need to be re-pitched.
-+       */
-+      MMAL_PARAMETER_VIDEO_ALIGN_VERT,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
-+      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
-+
-+      /**< @ref MMAL_PARAMETER_UINT32_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
-+
-+      /**< @ref MMAL_PARAMETER_UINT32_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
-+
-+      /* H264 specific parameters */
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
-+
-+      /** @ref MMAL_PARAMETER_UINT32_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
-+      MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
-+
-+      /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
-+
-+      /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
-+      MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
-+
-+      /** @ref MMAL_PARAMETER_BYTES_T */
-+      MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3,
-+
-+      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS,
-+
-+      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
-+
-+      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
-+};
-+
-+/** Valid mirror modes */
-+enum mmal_parameter_mirror {
-+      MMAL_PARAM_MIRROR_NONE,
-+      MMAL_PARAM_MIRROR_VERTICAL,
-+      MMAL_PARAM_MIRROR_HORIZONTAL,
-+      MMAL_PARAM_MIRROR_BOTH,
-+};
-+
-+enum mmal_parameter_displaytransform {
-+      MMAL_DISPLAY_ROT0 = 0,
-+      MMAL_DISPLAY_MIRROR_ROT0 = 1,
-+      MMAL_DISPLAY_MIRROR_ROT180 = 2,
-+      MMAL_DISPLAY_ROT180 = 3,
-+      MMAL_DISPLAY_MIRROR_ROT90 = 4,
-+      MMAL_DISPLAY_ROT270 = 5,
-+      MMAL_DISPLAY_ROT90 = 6,
-+      MMAL_DISPLAY_MIRROR_ROT270 = 7,
-+};
-+
-+enum mmal_parameter_displaymode {
-+      MMAL_DISPLAY_MODE_FILL = 0,
-+      MMAL_DISPLAY_MODE_LETTERBOX = 1,
-+};
-+
-+enum mmal_parameter_displayset {
-+      MMAL_DISPLAY_SET_NONE = 0,
-+      MMAL_DISPLAY_SET_NUM = 1,
-+      MMAL_DISPLAY_SET_FULLSCREEN = 2,
-+      MMAL_DISPLAY_SET_TRANSFORM = 4,
-+      MMAL_DISPLAY_SET_DEST_RECT = 8,
-+      MMAL_DISPLAY_SET_SRC_RECT = 0x10,
-+      MMAL_DISPLAY_SET_MODE = 0x20,
-+      MMAL_DISPLAY_SET_PIXEL = 0x40,
-+      MMAL_DISPLAY_SET_NOASPECT = 0x80,
-+      MMAL_DISPLAY_SET_LAYER = 0x100,
-+      MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
-+      MMAL_DISPLAY_SET_ALPHA = 0x400,
-+};
-+
-+/* rectangle, used lots so it gets its own struct */
-+struct vchiq_mmal_rect {
-+      s32 x;
-+      s32 y;
-+      s32 width;
-+      s32 height;
-+};
-+
-+struct mmal_parameter_displayregion {
-+      /** Bitfield that indicates which fields are set and should be
-+       * used. All other fields will maintain their current value.
-+       * \ref MMAL_DISPLAYSET_T defines the bits that can be
-+       * combined.
-+       */
-+      u32 set;
-+
-+      /** Describes the display output device, with 0 typically
-+       * being a directly connected LCD display.  The actual values
-+       * will depend on the hardware.  Code using hard-wired numbers
-+       * (e.g. 2) is certain to fail.
-+       */
-+
-+      u32 display_num;
-+      /** Indicates that we are using the full device screen area,
-+       * rather than a window of the display.  If zero, then
-+       * dest_rect is used to specify a region of the display to
-+       * use.
-+       */
-+
-+      s32 fullscreen;
-+      /** Indicates any rotation or flipping used to map frames onto
-+       * the natural display orientation.
-+       */
-+      u32 transform; /* enum mmal_parameter_displaytransform */
-+
-+      /** Where to display the frame within the screen, if
-+       * fullscreen is zero.
-+       */
-+      struct vchiq_mmal_rect dest_rect;
-+
-+      /** Indicates which area of the frame to display. If all
-+       * values are zero, the whole frame will be used.
-+       */
-+      struct vchiq_mmal_rect src_rect;
-+
-+      /** If set to non-zero, indicates that any display scaling
-+       * should disregard the aspect ratio of the frame region being
-+       * displayed.
-+       */
-+      s32 noaspect;
-+
-+      /** Indicates how the image should be scaled to fit the
-+       * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
-+       * that the image should fill the screen by potentially
-+       * cropping the frames.  Setting \code mode \endcode to \code
-+       * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
-+       * source region should be displayed and black bars added if
-+       * necessary.
-+       */
-+      u32 mode; /* enum mmal_parameter_displaymode */
-+
-+      /** If non-zero, defines the width of a source pixel relative
-+       * to \code pixel_y \endcode.  If zero, then pixels default to
-+       * being square.
-+       */
-+      u32 pixel_x;
-+
-+      /** If non-zero, defines the height of a source pixel relative
-+       * to \code pixel_x \endcode.  If zero, then pixels default to
-+       * being square.
-+       */
-+      u32 pixel_y;
-+
-+      /** Sets the relative depth of the images, with greater values
-+       * being in front of smaller values.
-+       */
-+      u32 layer;
-+
-+      /** Set to non-zero to ensure copy protection is used on
-+       * output.
-+       */
-+      s32 copyprotect_required;
-+
-+      /** Level of opacity of the layer, where zero is fully
-+       * transparent and 255 is fully opaque.
-+       */
-+      u32 alpha;
-+};
-+
-+#define MMAL_MAX_IMAGEFX_PARAMETERS 5
-+
-+struct mmal_parameter_imagefx_parameters {
-+      enum mmal_parameter_imagefx effect;
-+      u32 num_effect_params;
-+      u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
-+};
-+
-+#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4
-+#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2
-+#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16
-+
-+struct mmal_parameter_camera_info_camera_t {
-+      u32    port_id;
-+      u32    max_width;
-+      u32    max_height;
-+      u32    lens_present;
-+      u8     camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN];
-+};
-+
-+enum mmal_parameter_camera_info_flash_type_t {
-+      /* Make values explicit to ensure they match values in config ini */
-+      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0,
-+      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED   = 1,
-+      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2,
-+      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF
-+};
-+
-+struct mmal_parameter_camera_info_flash_t {
-+      enum mmal_parameter_camera_info_flash_type_t flash_type;
-+};
-+
-+struct mmal_parameter_camera_info_t {
-+      u32                            num_cameras;
-+      u32                            num_flashes;
-+      struct mmal_parameter_camera_info_camera_t
-+                              cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
-+      struct mmal_parameter_camera_info_flash_t
-+                              flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
-+};
-+
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -0,0 +1,166 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ *          Dave Stevenson @ Broadcom
-+ *            (now dave.stevenson@raspberrypi.org)
-+ *          Simon Mellor @ Broadcom
-+ *          Luke Diamand @ Broadcom
-+ *
-+ * MMAL interface to VCHIQ message passing
-+ */
-+
-+#ifndef MMAL_VCHIQ_H
-+#define MMAL_VCHIQ_H
-+
-+#include "mmal-msg-format.h"
-+
-+#define MAX_PORT_COUNT 4
-+
-+/* Maximum size of the format extradata. */
-+#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
-+
-+struct vchiq_mmal_instance;
-+
-+enum vchiq_mmal_es_type {
-+      MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
-+      MMAL_ES_TYPE_CONTROL,     /**< Elementary stream of control commands */
-+      MMAL_ES_TYPE_AUDIO,       /**< Audio elementary stream */
-+      MMAL_ES_TYPE_VIDEO,       /**< Video elementary stream */
-+      MMAL_ES_TYPE_SUBPICTURE   /**< Sub-picture elementary stream */
-+};
-+
-+struct vchiq_mmal_port_buffer {
-+      unsigned int num; /* number of buffers */
-+      u32 size; /* size of buffers */
-+      u32 alignment; /* alignment of buffers */
-+};
-+
-+struct vchiq_mmal_port;
-+
-+typedef void (*vchiq_mmal_buffer_cb)(
-+              struct vchiq_mmal_instance  *instance,
-+              struct vchiq_mmal_port *port,
-+              int status, struct mmal_buffer *buffer,
-+              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
-+
-+struct vchiq_mmal_port {
-+      bool enabled;
-+      u32 handle;
-+      u32 type; /* port type, cached to use on port info set */
-+      u32 index; /* port index, cached to use on port info set */
-+
-+      /* component port belongs to, allows simple deref */
-+      struct vchiq_mmal_component *component;
-+
-+      struct vchiq_mmal_port *connected; /* port conencted to */
-+
-+      /* buffer info */
-+      struct vchiq_mmal_port_buffer minimum_buffer;
-+      struct vchiq_mmal_port_buffer recommended_buffer;
-+      struct vchiq_mmal_port_buffer current_buffer;
-+
-+      /* stream format */
-+      struct mmal_es_format_local format;
-+      /* elementary stream format */
-+      union mmal_es_specific_format es;
-+
-+      /* data buffers to fill */
-+      struct list_head buffers;
-+      /* lock to serialise adding and removing buffers from list */
-+      spinlock_t slock;
-+
-+      /* Count of buffers the VPU has yet to return */
-+      atomic_t buffers_with_vpu;
-+      /* callback on buffer completion */
-+      vchiq_mmal_buffer_cb buffer_cb;
-+      /* callback context */
-+      void *cb_ctx;
-+};
-+
-+struct vchiq_mmal_component {
-+      bool enabled;
-+      u32 handle;  /* VideoCore handle for component */
-+      u32 inputs;  /* Number of input ports */
-+      u32 outputs; /* Number of output ports */
-+      u32 clocks;  /* Number of clock ports */
-+      struct vchiq_mmal_port control; /* control port */
-+      struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
-+      struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
-+      struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
-+};
-+
-+int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
-+int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
-+
-+/* Initialise a mmal component and its ports
-+ *
-+ */
-+int vchiq_mmal_component_init(
-+              struct vchiq_mmal_instance *instance,
-+              const char *name,
-+              struct vchiq_mmal_component **component_out);
-+
-+int vchiq_mmal_component_finalise(
-+              struct vchiq_mmal_instance *instance,
-+              struct vchiq_mmal_component *component);
-+
-+int vchiq_mmal_component_enable(
-+              struct vchiq_mmal_instance *instance,
-+              struct vchiq_mmal_component *component);
-+
-+int vchiq_mmal_component_disable(
-+              struct vchiq_mmal_instance *instance,
-+              struct vchiq_mmal_component *component);
-+
-+/* enable a mmal port
-+ *
-+ * enables a port and if a buffer callback provided enque buffer
-+ * headers as appropriate for the port.
-+ */
-+int vchiq_mmal_port_enable(
-+              struct vchiq_mmal_instance *instance,
-+              struct vchiq_mmal_port *port,
-+              vchiq_mmal_buffer_cb buffer_cb);
-+
-+/* disable a port
-+ *
-+ * disable a port will dequeue any pending buffers
-+ */
-+int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
-+                          struct vchiq_mmal_port *port);
-+
-+int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
-+                                struct vchiq_mmal_port *port,
-+                                u32 parameter,
-+                                void *value,
-+                                u32 value_size);
-+
-+int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
-+                                struct vchiq_mmal_port *port,
-+                                u32 parameter,
-+                                void *value,
-+                                u32 *value_size);
-+
-+int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
-+                             struct vchiq_mmal_port *port);
-+
-+int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
-+                                 struct vchiq_mmal_port *src,
-+                                 struct vchiq_mmal_port *dst);
-+
-+int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
-+                     u32 *major_out,
-+                     u32 *minor_out);
-+
-+int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
-+                           struct vchiq_mmal_port *port,
-+                           struct mmal_buffer *buf);
-+
-+int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
-+                        struct mmal_buffer *buf);
-+int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
-+#endif /* MMAL_VCHIQ_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0235-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch b/target/linux/brcm2708/patches-4.19/950-0235-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch
deleted file mode 100644 (file)
index 7e4100f..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-From f94642597f63c71b2ccffddd4f447190c131af56 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:51:13 +0100
-Subject: [PATCH] staging: mmal-vchiq: Allocate and free components as
- required
-
-The existing code assumed that there would only ever be 4 components,
-and never freed the entries once used.
-Allow arbitrary creation and destruction of components.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 29 ++++++++++++-------
- .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  1 +
- 2 files changed, 20 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -38,8 +38,11 @@ MODULE_AUTHOR("Dave Stevenson, <dave.ste
- MODULE_LICENSE("GPL");
- MODULE_VERSION("0.0.1");
--/* maximum number of components supported */
--#define VCHIQ_MMAL_MAX_COMPONENTS 4
-+/*
-+ * maximum number of components supported.
-+ * This matches the maximum permitted by default on the VPU
-+ */
-+#define VCHIQ_MMAL_MAX_COMPONENTS 64
- /*#define FULL_MSG_DUMP 1*/
-@@ -174,8 +177,6 @@ struct vchiq_mmal_instance {
-       /* protect accesses to context_map */
-       struct mutex context_map_lock;
--      /* component to use next */
--      int component_idx;
-       struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
-       /* ordered workqueue to process all bulk operations */
-@@ -1632,18 +1633,24 @@ int vchiq_mmal_component_init(struct vch
- {
-       int ret;
-       int idx;                /* port index */
--      struct vchiq_mmal_component *component;
-+      struct vchiq_mmal_component *component = NULL;
-       if (mutex_lock_interruptible(&instance->vchiq_mutex))
-               return -EINTR;
--      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
-+      for (idx = 0; idx < VCHIQ_MMAL_MAX_COMPONENTS; idx++) {
-+              if (!instance->component[idx].in_use) {
-+                      component = &instance->component[idx];
-+                      component->in_use = 1;
-+                      break;
-+              }
-+      }
-+
-+      if (!component) {
-               ret = -EINVAL;  /* todo is this correct error? */
-               goto unlock;
-       }
--      component = &instance->component[instance->component_idx];
--
-       ret = create_component(instance, component, name);
-       if (ret < 0) {
-               pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
-@@ -1694,8 +1701,6 @@ int vchiq_mmal_component_init(struct vch
-                       goto release_component;
-       }
--      instance->component_idx++;
--
-       *component_out = component;
-       mutex_unlock(&instance->vchiq_mutex);
-@@ -1705,6 +1710,8 @@ int vchiq_mmal_component_init(struct vch
- release_component:
-       destroy_component(instance, component);
- unlock:
-+      if (component)
-+              component->in_use = 0;
-       mutex_unlock(&instance->vchiq_mutex);
-       return ret;
-@@ -1727,6 +1734,8 @@ int vchiq_mmal_component_finalise(struct
-       ret = destroy_component(instance, component);
-+      component->in_use = 0;
-+
-       mutex_unlock(&instance->vchiq_mutex);
-       return ret;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -82,6 +82,7 @@ struct vchiq_mmal_port {
- };
- struct vchiq_mmal_component {
-+      u32 in_use:1;
-       bool enabled;
-       u32 handle;  /* VideoCore handle for component */
-       u32 inputs;  /* Number of input ports */
diff --git a/target/linux/brcm2708/patches-4.19/950-0235-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0235-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch
new file mode 100644 (file)
index 0000000..dd65541
--- /dev/null
@@ -0,0 +1,38 @@
+From 301a6a16ec8a8b1a7b89c0cc6df30e79a460214a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:57:09 +0100
+Subject: [PATCH] staging: mmal-vchiq: Make timeout a defined parameter
+
+The timeout period for VPU communications is a useful thing
+to extend when debugging.
+Set it via a define, rather than a magic number buried in the code.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -44,6 +44,12 @@ MODULE_VERSION("0.0.1");
+  */
+ #define VCHIQ_MMAL_MAX_COMPONENTS 64
++/*
++ * Timeout for synchronous msg responses in seconds.
++ * Helpful to increase this if stopping in the VPU debugger.
++ */
++#define SYNC_MSG_TIMEOUT      3
++
+ /*#define FULL_MSG_DUMP 1*/
+ #ifdef DEBUG
+@@ -692,7 +698,7 @@ static int send_synchronous_mmal_msg(str
+       }
+       timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
+-                                            3 * HZ);
++                                            SYNC_MSG_TIMEOUT * HZ);
+       if (timeout == 0) {
+               pr_err("timed out waiting for sync completion\n");
+               ret = -ETIME;
diff --git a/target/linux/brcm2708/patches-4.19/950-0236-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch b/target/linux/brcm2708/patches-4.19/950-0236-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch
deleted file mode 100644 (file)
index 401b8bf..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-From 3789c3b08b56f471878c493fd80a2eee776b527c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 16:20:46 +0000
-Subject: [PATCH] staging: mmal-vchiq: Avoid use of bool in structures
-
-Fixes up a checkpatch error "Avoid using bool structure members
-because of possible alignment issues".
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c  | 14 +++++++-------
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h  |  4 ++--
- 2 files changed, 9 insertions(+), 9 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -861,9 +861,9 @@ static int port_info_get(struct vchiq_mm
-               goto release_msg;
-       if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
--              port->enabled = false;
-+              port->enabled = 0;
-       else
--              port->enabled = true;
-+              port->enabled = 1;
-       /* copy the values out of the message */
-       port->handle = rmsg->u.port_info_get_reply.port_handle;
-@@ -1300,7 +1300,7 @@ static int port_disable(struct vchiq_mma
-       if (!port->enabled)
-               return 0;
--      port->enabled = false;
-+      port->enabled = 0;
-       ret = port_action_port(instance, port,
-                              MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
-@@ -1352,7 +1352,7 @@ static int port_enable(struct vchiq_mmal
-       if (ret)
-               goto done;
--      port->enabled = true;
-+      port->enabled = 1;
-       if (port->buffer_cb) {
-               /* send buffer headers to videocore */
-@@ -1524,7 +1524,7 @@ int vchiq_mmal_port_connect_tunnel(struc
-                       pr_err("failed disconnecting src port\n");
-                       goto release_unlock;
-               }
--              src->connected->enabled = false;
-+              src->connected->enabled = 0;
-               src->connected = NULL;
-       }
-@@ -1760,7 +1760,7 @@ int vchiq_mmal_component_enable(struct v
-       ret = enable_component(instance, component);
-       if (ret == 0)
--              component->enabled = true;
-+              component->enabled = 1;
-       mutex_unlock(&instance->vchiq_mutex);
-@@ -1786,7 +1786,7 @@ int vchiq_mmal_component_disable(struct
-       ret = disable_component(instance, component);
-       if (ret == 0)
--              component->enabled = false;
-+              component->enabled = 0;
-       mutex_unlock(&instance->vchiq_mutex);
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -48,7 +48,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
-               unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
- struct vchiq_mmal_port {
--      bool enabled;
-+      u32 enabled:1;
-       u32 handle;
-       u32 type; /* port type, cached to use on port info set */
-       u32 index; /* port index, cached to use on port info set */
-@@ -83,7 +83,7 @@ struct vchiq_mmal_port {
- struct vchiq_mmal_component {
-       u32 in_use:1;
--      bool enabled;
-+      u32 enabled:1;
-       u32 handle;  /* VideoCore handle for component */
-       u32 inputs;  /* Number of input ports */
-       u32 outputs; /* Number of output ports */
diff --git a/target/linux/brcm2708/patches-4.19/950-0236-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch b/target/linux/brcm2708/patches-4.19/950-0236-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch
new file mode 100644 (file)
index 0000000..468f036
--- /dev/null
@@ -0,0 +1,280 @@
+From 862ee4fbd8c6b984f920b88908e33951e51134ca Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 17:33:37 +0100
+Subject: [PATCH] staging: mmal-vchiq: Make a mmal_buf struct for
+ passing parameters
+
+The callback from vchi_mmal to the client was growing lots of extra
+parameters. Consolidate them into a single struct instead of
+growing the list further.
+The struct is associated with the client buffer, therefore there
+are various changes to setup various containers for the struct,
+and pass the appropriate members.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 62 ++++++++++++-------
+ .../vc04_services/vchiq-mmal/mmal-common.h    |  5 ++
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 29 ++++++---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  3 +-
+ 4 files changed, 64 insertions(+), 35 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -72,6 +72,12 @@ static const struct v4l2_fract
+       tpf_max     = {.numerator = 1,          .denominator = FPS_MIN},
+       tpf_default = {.numerator = 1000,       .denominator = 30000};
++/* Container for MMAL and VB2 buffers*/
++struct vb2_mmal_buffer {
++      struct vb2_v4l2_buffer  vb;
++      struct mmal_buffer      mmal;
++};
++
+ /* video formats */
+ static struct mmal_fmt formats[] = {
+       {
+@@ -267,14 +273,15 @@ static int buffer_init(struct vb2_buffer
+ {
+       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
+-      struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
++      struct vb2_mmal_buffer *buf =
++                              container_of(vb2, struct vb2_mmal_buffer, vb);
+       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
+                __func__, dev, vb);
+-      buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
+-      buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
++      buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
++      buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
+-      return mmal_vchi_buffer_init(dev->instance, buf);
++      return mmal_vchi_buffer_init(dev->instance, &buf->mmal);
+ }
+ static int buffer_prepare(struct vb2_buffer *vb)
+@@ -303,11 +310,13 @@ static void buffer_cleanup(struct vb2_bu
+ {
+       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
+-      struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
++      struct vb2_mmal_buffer *buf =
++                              container_of(vb2, struct vb2_mmal_buffer, vb);
+       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
+                __func__, dev, vb);
+-      mmal_vchi_buffer_cleanup(buf);
++
++      mmal_vchi_buffer_cleanup(&buf->mmal);
+ }
+ static inline bool is_capturing(struct bm2835_mmal_dev *dev)
+@@ -319,14 +328,16 @@ static inline bool is_capturing(struct b
+ static void buffer_cb(struct vchiq_mmal_instance *instance,
+                     struct vchiq_mmal_port *port,
+                     int status,
+-                    struct mmal_buffer *buf,
+-                    unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
++                    struct mmal_buffer *mmal_buf)
+ {
+       struct bm2835_mmal_dev *dev = port->cb_ctx;
++      struct vb2_mmal_buffer *buf =
++                      container_of(mmal_buf, struct vb2_mmal_buffer, mmal);
+       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
+-               __func__, status, buf, length, mmal_flags, pts);
++               __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags,
++               mmal_buf->pts);
+       if (status != 0) {
+               /* error in transfer */
+@@ -337,7 +348,7 @@ static void buffer_cb(struct vchiq_mmal_
+               return;
+       }
+-      if (length == 0) {
++      if (mmal_buf->length == 0) {
+               /* stream ended */
+               if (dev->capture.frame_count) {
+                       /* empty buffer whilst capturing - expected to be an
+@@ -353,7 +364,8 @@ static void buffer_cb(struct vchiq_mmal_
+                                       &dev->capture.frame_count,
+                                       sizeof(dev->capture.frame_count));
+                       }
+-                      if (vchiq_mmal_submit_buffer(instance, port, buf))
++                      if (vchiq_mmal_submit_buffer(instance, port,
++                                                   &buf->mmal))
+                               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                                        "Failed to return EOS buffer");
+               } else {
+@@ -382,16 +394,16 @@ static void buffer_cb(struct vchiq_mmal_
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                        "Buffer time set as current time - %lld",
+                        buf->vb.vb2_buf.timestamp);
+-      } else if (pts != 0) {
++      } else if (mmal_buf->pts != 0) {
+               ktime_t timestamp;
+-              s64 runtime_us = pts -
++              s64 runtime_us = mmal_buf->pts -
+                   dev->capture.vc_start_timestamp;
+               timestamp = ktime_add_us(dev->capture.kernel_start_ts,
+                                        runtime_us);
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                        "Convert start time %llu and %llu with offset %llu to %llu\n",
+                        ktime_to_ns(dev->capture.kernel_start_ts),
+-                       dev->capture.vc_start_timestamp, pts,
++                       dev->capture.vc_start_timestamp, mmal_buf->pts,
+                        ktime_to_ns(timestamp));
+               if (timestamp < dev->capture.last_timestamp) {
+                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+@@ -416,15 +428,15 @@ static void buffer_cb(struct vchiq_mmal_
+       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
+       buf->vb.sequence = dev->capture.sequence++;
+-      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
+-      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
++      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
++      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+               buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                "Buffer has ts %llu", dev->capture.last_timestamp);
+       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+-      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
++      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
+           is_capturing(dev)) {
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                        "Grab another frame as buffer has EOS");
+@@ -507,14 +519,16 @@ static void buffer_queue(struct vb2_buff
+ {
+       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
+-      struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
++      struct vb2_mmal_buffer *buf =
++                              container_of(vb2, struct vb2_mmal_buffer, vb);
+       int ret;
+       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                "%s: dev:%p buf:%p, idx %u\n",
+                __func__, dev, buf, vb2->vb2_buf.index);
+-      ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
++      ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port,
++                                     &buf->mmal);
+       if (ret < 0)
+               v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
+                        __func__);
+@@ -628,7 +642,7 @@ static void stop_streaming(struct vb2_qu
+       dev->capture.frame_count = 0;
+       /* ensure a format has actually been set */
+-      if (!dev->capture.port) {
++      if (!port) {
+               v4l2_err(&dev->v4l2_dev,
+                        "no capture port - stream not started?\n");
+               return;
+@@ -648,11 +662,11 @@ static void stop_streaming(struct vb2_qu
+       /* disable the connection from camera to encoder */
+       ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port);
+-      if (!ret && dev->capture.camera_port != dev->capture.port) {
++      if (!ret && dev->capture.camera_port != port) {
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                        "disabling port\n");
+-              ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port);
+-      } else if (dev->capture.camera_port != dev->capture.port) {
++              ret = vchiq_mmal_port_disable(dev->instance, port);
++      } else if (dev->capture.camera_port != port) {
+               v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
+                        ret);
+       }
+@@ -1954,7 +1968,7 @@ static int bcm2835_mmal_probe(struct pla
+               q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+               q->drv_priv = dev;
+-              q->buf_struct_size = sizeof(struct mmal_buffer);
++              q->buf_struct_size = sizeof(struct vb2_mmal_buffer);
+               q->ops = &bm2835_mmal_video_qops;
+               q->mem_ops = &vb2_vmalloc_memops;
+               q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -50,6 +50,11 @@ struct mmal_buffer {
+       unsigned long buffer_size; /* size of allocated buffer */
+       struct mmal_msg_context *msg_context;
++
++      unsigned long length;
++      u32 mmal_flags;
++      s64 dts;
++      s64 pts;
+ };
+ /* */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -259,17 +259,25 @@ static void buffer_work_cb(struct work_s
+ {
+       struct mmal_msg_context *msg_context =
+               container_of(work, struct mmal_msg_context, u.bulk.work);
++      struct mmal_buffer *buffer = msg_context->u.bulk.buffer;
++
++      if (!buffer) {
++              pr_err("%s: ctx: %p, No mmal buffer to pass details\n",
++                     __func__, msg_context);
++              return;
++      }
++
++      buffer->length = msg_context->u.bulk.buffer_used;
++      buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
++      buffer->dts = msg_context->u.bulk.dts;
++      buffer->pts = msg_context->u.bulk.pts;
+       atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
+       msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
+                                           msg_context->u.bulk.port,
+                                           msg_context->u.bulk.status,
+-                                          msg_context->u.bulk.buffer,
+-                                          msg_context->u.bulk.buffer_used,
+-                                          msg_context->u.bulk.mmal_flags,
+-                                          msg_context->u.bulk.dts,
+-                                          msg_context->u.bulk.pts);
++                                          msg_context->u.bulk.buffer);
+ }
+ /* workqueue scheduled callback to handle receiving buffers
+@@ -1327,11 +1335,14 @@ static int port_disable(struct vchiq_mma
+                       mmalbuf = list_entry(buf_head, struct mmal_buffer,
+                                            list);
+                       list_del(buf_head);
+-                      if (port->buffer_cb)
++                      if (port->buffer_cb) {
++                              mmalbuf->length = 0;
++                              mmalbuf->mmal_flags = 0;
++                              mmalbuf->dts = MMAL_TIME_UNKNOWN;
++                              mmalbuf->pts = MMAL_TIME_UNKNOWN;
+                               port->buffer_cb(instance,
+-                                              port, 0, mmalbuf, 0, 0,
+-                                              MMAL_TIME_UNKNOWN,
+-                                              MMAL_TIME_UNKNOWN);
++                                              port, 0, mmalbuf);
++                      }
+               }
+               spin_unlock_irqrestore(&port->slock, flags);
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -44,8 +44,7 @@ struct vchiq_mmal_port;
+ typedef void (*vchiq_mmal_buffer_cb)(
+               struct vchiq_mmal_instance  *instance,
+               struct vchiq_mmal_port *port,
+-              int status, struct mmal_buffer *buffer,
+-              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
++              int status, struct mmal_buffer *buffer);
+ struct vchiq_mmal_port {
+       u32 enabled:1;
diff --git a/target/linux/brcm2708/patches-4.19/950-0237-staging-mmal-vchiq-Add-support-for-event-callbacks.patch b/target/linux/brcm2708/patches-4.19/950-0237-staging-mmal-vchiq-Add-support-for-event-callbacks.patch
new file mode 100644 (file)
index 0000000..b79bdb8
--- /dev/null
@@ -0,0 +1,356 @@
+From adab474d1f91594d6d96d44054586ba36d7f26d4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 18:15:38 +0100
+Subject: [PATCH] staging: mmal-vchiq: Add support for event callbacks.
+
+(Preparation for the codec driver).
+The codec uses the event mechanism to report things such as
+resolution changes. It is signalled by the cmd field of the buffer
+being non-zero.
+
+Add support for passing this information out to the client.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-common.h    |   1 +
+ .../vc04_services/vchiq-mmal/mmal-msg.h       |  35 ++++
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 170 ++++++++++++++++--
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h     |   4 +
+ 4 files changed, 196 insertions(+), 14 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -51,6 +51,7 @@ struct mmal_buffer {
+       struct mmal_msg_context *msg_context;
++      u32 cmd;                /* MMAL command. 0=data. */
+       unsigned long length;
+       u32 mmal_flags;
+       s64 dts;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
+@@ -346,6 +346,41 @@ struct mmal_msg_port_parameter_get_reply
+ /* event messages */
+ #define MMAL_WORKER_EVENT_SPACE 256
++/* Four CC's for events */
++#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
++
++#define MMAL_EVENT_ERROR              MMAL_FOURCC('E', 'R', 'R', 'O')
++#define MMAL_EVENT_EOS                        MMAL_FOURCC('E', 'E', 'O', 'S')
++#define MMAL_EVENT_FORMAT_CHANGED     MMAL_FOURCC('E', 'F', 'C', 'H')
++#define MMAL_EVENT_PARAMETER_CHANGED  MMAL_FOURCC('E', 'P', 'C', 'H')
++
++/* Structs for each of the event message payloads */
++struct mmal_msg_event_eos {
++      u32 port_type;  /**< Type of port that received the end of stream */
++      u32 port_index; /**< Index of port that received the end of stream */
++};
++
++/** Format changed event data. */
++struct mmal_msg_event_format_changed {
++      /* Minimum size of buffers the port requires */
++      u32 buffer_size_min;
++      /* Minimum number of buffers the port requires */
++      u32 buffer_num_min;
++      /* Size of buffers the port recommends for optimal performance.
++       * A value of zero means no special recommendation.
++       */
++      u32 buffer_size_recommended;
++      /* Number of buffers the port recommends for optimal
++       * performance. A value of zero means no special recommendation.
++       */
++      u32 buffer_num_recommended;
++
++      u32 es_ptr;
++      struct mmal_es_format format;
++      union mmal_es_specific_format es;
++      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
++};
++
+ struct mmal_msg_event_to_host {
+       u32 client_component;   /* component context */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -151,6 +151,8 @@ struct mmal_msg_context {
+                       /* Presentation and Decode timestamps */
+                       s64 pts;
+                       s64 dts;
++                      /* MMAL buffer command flag */
++                      u32 cmd;
+                       int status;     /* context status */
+@@ -238,18 +240,6 @@ release_msg_context(struct mmal_msg_cont
+       kfree(msg_context);
+ }
+-/* deals with receipt of event to host message */
+-static void event_to_host_cb(struct vchiq_mmal_instance *instance,
+-                           struct mmal_msg *msg, u32 msg_len)
+-{
+-      pr_debug("unhandled event\n");
+-      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
+-               msg->u.event_to_host.client_component,
+-               msg->u.event_to_host.port_type,
+-               msg->u.event_to_host.port_num,
+-               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
+-}
+-
+ /* workqueue scheduled callback
+  *
+  * we do this because it is important we do not call any other vchiq
+@@ -271,13 +261,18 @@ static void buffer_work_cb(struct work_s
+       buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
+       buffer->dts = msg_context->u.bulk.dts;
+       buffer->pts = msg_context->u.bulk.pts;
++      buffer->cmd = msg_context->u.bulk.cmd;
+-      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
++      if (!buffer->cmd)
++              atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
+       msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
+                                           msg_context->u.bulk.port,
+                                           msg_context->u.bulk.status,
+                                           msg_context->u.bulk.buffer);
++
++      if (buffer->cmd)
++              mutex_unlock(&msg_context->u.bulk.port->event_context_mutex);
+ }
+ /* workqueue scheduled callback to handle receiving buffers
+@@ -356,6 +351,7 @@ static int bulk_receive(struct vchiq_mma
+       msg_context->u.bulk.buffer_used = rd_len;
+       msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
+       msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
++      msg_context->u.bulk.cmd = msg->u.buffer_from_host.buffer_header.cmd;
+       queue_work(msg_context->instance->bulk_wq,
+                  &msg_context->u.bulk.buffer_to_host_work);
+@@ -457,6 +453,103 @@ buffer_from_host(struct vchiq_mmal_insta
+       return ret;
+ }
++/* deals with receipt of event to host message */
++static void event_to_host_cb(struct vchiq_mmal_instance *instance,
++                           struct mmal_msg *msg, u32 msg_len)
++{
++      /* FIXME: Not going to work on 64 bit */
++      struct vchiq_mmal_component *component =
++              (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
++      struct vchiq_mmal_port *port = NULL;
++      struct mmal_msg_context *msg_context;
++      u32 port_num = msg->u.event_to_host.port_num;
++
++      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
++              pr_err("%s: MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n",
++                     __func__);
++              return;
++      }
++
++      switch (msg->u.event_to_host.port_type) {
++      case MMAL_PORT_TYPE_CONTROL:
++              if (port_num) {
++                      pr_err("%s: port_num of %u >= number of ports 1",
++                             __func__, port_num);
++                      return;
++              }
++              port = &component->control;
++              break;
++      case MMAL_PORT_TYPE_INPUT:
++              if (port_num >= component->inputs) {
++                      pr_err("%s: port_num of %u >= number of ports %u",
++                             __func__, port_num,
++                             port_num >= component->inputs);
++                      return;
++              }
++              port = &component->input[port_num];
++              break;
++      case MMAL_PORT_TYPE_OUTPUT:
++              if (port_num >= component->outputs) {
++                      pr_err("%s: port_num of %u >= number of ports %u",
++                             __func__, port_num,
++                             port_num >= component->outputs);
++                      return;
++              }
++              port = &component->output[port_num];
++              break;
++      case MMAL_PORT_TYPE_CLOCK:
++              if (port_num >= component->clocks) {
++                      pr_err("%s: port_num of %u >= number of ports %u",
++                             __func__, port_num,
++                             port_num >= component->clocks);
++                      return;
++              }
++              port = &component->clock[port_num];
++              break;
++      default:
++              break;
++      }
++
++      if (!mutex_trylock(&port->event_context_mutex)) {
++              pr_err("dropping event 0x%x\n", msg->u.event_to_host.cmd);
++              return;
++      }
++      msg_context = port->event_context;
++
++      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
++              /* message reception had an error */
++              //pr_warn
++              pr_err("%s: error %d in reply\n", __func__, msg->h.status);
++
++              msg_context->u.bulk.status = msg->h.status;
++      } else if (msg->u.event_to_host.length > MMAL_WORKER_EVENT_SPACE) {
++              /* data is not in message, queue a bulk receive */
++              pr_err("%s: payload not in message - bulk receive??! NOT SUPPORTED\n",
++                     __func__);
++              msg_context->u.bulk.status = -1;
++      } else {
++              memcpy(msg_context->u.bulk.buffer->buffer,
++                     msg->u.event_to_host.data,
++                     msg->u.event_to_host.length);
++
++              msg_context->u.bulk.buffer_used =
++                  msg->u.event_to_host.length;
++
++              msg_context->u.bulk.mmal_flags = 0;
++              msg_context->u.bulk.dts = MMAL_TIME_UNKNOWN;
++              msg_context->u.bulk.pts = MMAL_TIME_UNKNOWN;
++              msg_context->u.bulk.cmd = msg->u.event_to_host.cmd;
++
++              pr_debug("event component:%u port type:%d num:%d cmd:0x%x length:%d\n",
++                       msg->u.event_to_host.client_component,
++                       msg->u.event_to_host.port_type,
++                       msg->u.event_to_host.port_num,
++                       msg->u.event_to_host.cmd, msg->u.event_to_host.length);
++      }
++
++      schedule_work(&msg_context->u.bulk.work);
++}
++
+ /* deals with receipt of buffer to host message */
+ static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
+                             struct mmal_msg *msg, u32 msg_len)
+@@ -1340,6 +1433,7 @@ static int port_disable(struct vchiq_mma
+                               mmalbuf->mmal_flags = 0;
+                               mmalbuf->dts = MMAL_TIME_UNKNOWN;
+                               mmalbuf->pts = MMAL_TIME_UNKNOWN;
++                              mmalbuf->cmd = 0;
+                               port->buffer_cb(instance,
+                                               port, 0, mmalbuf);
+                       }
+@@ -1641,6 +1735,43 @@ int mmal_vchi_buffer_cleanup(struct mmal
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
++static void init_event_context(struct vchiq_mmal_instance *instance,
++                             struct vchiq_mmal_port *port)
++{
++      struct mmal_msg_context *ctx = get_msg_context(instance);
++
++      mutex_init(&port->event_context_mutex);
++
++      port->event_context = ctx;
++      ctx->u.bulk.instance = instance;
++      ctx->u.bulk.port = port;
++      ctx->u.bulk.buffer =
++              kzalloc(sizeof(*ctx->u.bulk.buffer), GFP_KERNEL);
++      if (!ctx->u.bulk.buffer)
++              goto release_msg_context;
++      ctx->u.bulk.buffer->buffer = kzalloc(MMAL_WORKER_EVENT_SPACE,
++                                           GFP_KERNEL);
++      if (!ctx->u.bulk.buffer->buffer)
++              goto release_buffer;
++
++      INIT_WORK(&ctx->u.bulk.work, buffer_work_cb);
++      return;
++
++release_buffer:
++      kfree(ctx->u.bulk.buffer);
++release_msg_context:
++      release_msg_context(ctx);
++}
++
++static void free_event_context(struct vchiq_mmal_port *port)
++{
++      struct mmal_msg_context *ctx = port->event_context;
++
++      kfree(ctx->u.bulk.buffer->buffer);
++      kfree(ctx->u.bulk.buffer);
++      release_msg_context(ctx);
++}
++
+ /* Initialise a mmal component and its ports
+  *
+  */
+@@ -1684,6 +1815,7 @@ int vchiq_mmal_component_init(struct vch
+       ret = port_info_get(instance, &component->control);
+       if (ret < 0)
+               goto release_component;
++      init_event_context(instance, &component->control);
+       for (idx = 0; idx < component->inputs; idx++) {
+               component->input[idx].type = MMAL_PORT_TYPE_INPUT;
+@@ -1694,6 +1826,7 @@ int vchiq_mmal_component_init(struct vch
+               ret = port_info_get(instance, &component->input[idx]);
+               if (ret < 0)
+                       goto release_component;
++              init_event_context(instance, &component->input[idx]);
+       }
+       for (idx = 0; idx < component->outputs; idx++) {
+@@ -1705,6 +1838,7 @@ int vchiq_mmal_component_init(struct vch
+               ret = port_info_get(instance, &component->output[idx]);
+               if (ret < 0)
+                       goto release_component;
++              init_event_context(instance, &component->output[idx]);
+       }
+       for (idx = 0; idx < component->clocks; idx++) {
+@@ -1716,6 +1850,7 @@ int vchiq_mmal_component_init(struct vch
+               ret = port_info_get(instance, &component->clock[idx]);
+               if (ret < 0)
+                       goto release_component;
++              init_event_context(instance, &component->clock[idx]);
+       }
+       *component_out = component;
+@@ -1741,7 +1876,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
+ int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
+                                 struct vchiq_mmal_component *component)
+ {
+-      int ret;
++      int ret, idx;
+       if (mutex_lock_interruptible(&instance->vchiq_mutex))
+               return -EINTR;
+@@ -1753,6 +1888,13 @@ int vchiq_mmal_component_finalise(struct
+       component->in_use = 0;
++      for (idx = 0; idx < component->inputs; idx++)
++              free_event_context(&component->input[idx]);
++      for (idx = 0; idx < component->outputs; idx++)
++              free_event_context(&component->output[idx]);
++      for (idx = 0; idx < component->clocks; idx++)
++              free_event_context(&component->clock[idx]);
++
+       mutex_unlock(&instance->vchiq_mutex);
+       return ret;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -78,6 +78,10 @@ struct vchiq_mmal_port {
+       vchiq_mmal_buffer_cb buffer_cb;
+       /* callback context */
+       void *cb_ctx;
++
++      /* ensure serialised use of the one event context structure */
++      struct mutex event_context_mutex;
++      struct mmal_msg_context *event_context;
+ };
+ struct vchiq_mmal_component {
diff --git a/target/linux/brcm2708/patches-4.19/950-0237-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0237-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch
deleted file mode 100644 (file)
index dd65541..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 301a6a16ec8a8b1a7b89c0cc6df30e79a460214a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:57:09 +0100
-Subject: [PATCH] staging: mmal-vchiq: Make timeout a defined parameter
-
-The timeout period for VPU communications is a useful thing
-to extend when debugging.
-Set it via a define, rather than a magic number buried in the code.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -44,6 +44,12 @@ MODULE_VERSION("0.0.1");
-  */
- #define VCHIQ_MMAL_MAX_COMPONENTS 64
-+/*
-+ * Timeout for synchronous msg responses in seconds.
-+ * Helpful to increase this if stopping in the VPU debugger.
-+ */
-+#define SYNC_MSG_TIMEOUT      3
-+
- /*#define FULL_MSG_DUMP 1*/
- #ifdef DEBUG
-@@ -692,7 +698,7 @@ static int send_synchronous_mmal_msg(str
-       }
-       timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
--                                            3 * HZ);
-+                                            SYNC_MSG_TIMEOUT * HZ);
-       if (timeout == 0) {
-               pr_err("timed out waiting for sync completion\n");
-               ret = -ETIME;
diff --git a/target/linux/brcm2708/patches-4.19/950-0238-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch b/target/linux/brcm2708/patches-4.19/950-0238-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch
deleted file mode 100644 (file)
index 468f036..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-From 862ee4fbd8c6b984f920b88908e33951e51134ca Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 17:33:37 +0100
-Subject: [PATCH] staging: mmal-vchiq: Make a mmal_buf struct for
- passing parameters
-
-The callback from vchi_mmal to the client was growing lots of extra
-parameters. Consolidate them into a single struct instead of
-growing the list further.
-The struct is associated with the client buffer, therefore there
-are various changes to setup various containers for the struct,
-and pass the appropriate members.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c           | 62 ++++++++++++-------
- .../vc04_services/vchiq-mmal/mmal-common.h    |  5 ++
- .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 29 ++++++---
- .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  3 +-
- 4 files changed, 64 insertions(+), 35 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -72,6 +72,12 @@ static const struct v4l2_fract
-       tpf_max     = {.numerator = 1,          .denominator = FPS_MIN},
-       tpf_default = {.numerator = 1000,       .denominator = 30000};
-+/* Container for MMAL and VB2 buffers*/
-+struct vb2_mmal_buffer {
-+      struct vb2_v4l2_buffer  vb;
-+      struct mmal_buffer      mmal;
-+};
-+
- /* video formats */
- static struct mmal_fmt formats[] = {
-       {
-@@ -267,14 +273,15 @@ static int buffer_init(struct vb2_buffer
- {
-       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-       struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
--      struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
-+      struct vb2_mmal_buffer *buf =
-+                              container_of(vb2, struct vb2_mmal_buffer, vb);
-       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
-                __func__, dev, vb);
--      buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
--      buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
-+      buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-+      buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
--      return mmal_vchi_buffer_init(dev->instance, buf);
-+      return mmal_vchi_buffer_init(dev->instance, &buf->mmal);
- }
- static int buffer_prepare(struct vb2_buffer *vb)
-@@ -303,11 +310,13 @@ static void buffer_cleanup(struct vb2_bu
- {
-       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-       struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
--      struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
-+      struct vb2_mmal_buffer *buf =
-+                              container_of(vb2, struct vb2_mmal_buffer, vb);
-       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
-                __func__, dev, vb);
--      mmal_vchi_buffer_cleanup(buf);
-+
-+      mmal_vchi_buffer_cleanup(&buf->mmal);
- }
- static inline bool is_capturing(struct bm2835_mmal_dev *dev)
-@@ -319,14 +328,16 @@ static inline bool is_capturing(struct b
- static void buffer_cb(struct vchiq_mmal_instance *instance,
-                     struct vchiq_mmal_port *port,
-                     int status,
--                    struct mmal_buffer *buf,
--                    unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
-+                    struct mmal_buffer *mmal_buf)
- {
-       struct bm2835_mmal_dev *dev = port->cb_ctx;
-+      struct vb2_mmal_buffer *buf =
-+                      container_of(mmal_buf, struct vb2_mmal_buffer, mmal);
-       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
--               __func__, status, buf, length, mmal_flags, pts);
-+               __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags,
-+               mmal_buf->pts);
-       if (status != 0) {
-               /* error in transfer */
-@@ -337,7 +348,7 @@ static void buffer_cb(struct vchiq_mmal_
-               return;
-       }
--      if (length == 0) {
-+      if (mmal_buf->length == 0) {
-               /* stream ended */
-               if (dev->capture.frame_count) {
-                       /* empty buffer whilst capturing - expected to be an
-@@ -353,7 +364,8 @@ static void buffer_cb(struct vchiq_mmal_
-                                       &dev->capture.frame_count,
-                                       sizeof(dev->capture.frame_count));
-                       }
--                      if (vchiq_mmal_submit_buffer(instance, port, buf))
-+                      if (vchiq_mmal_submit_buffer(instance, port,
-+                                                   &buf->mmal))
-                               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                                        "Failed to return EOS buffer");
-               } else {
-@@ -382,16 +394,16 @@ static void buffer_cb(struct vchiq_mmal_
-               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                        "Buffer time set as current time - %lld",
-                        buf->vb.vb2_buf.timestamp);
--      } else if (pts != 0) {
-+      } else if (mmal_buf->pts != 0) {
-               ktime_t timestamp;
--              s64 runtime_us = pts -
-+              s64 runtime_us = mmal_buf->pts -
-                   dev->capture.vc_start_timestamp;
-               timestamp = ktime_add_us(dev->capture.kernel_start_ts,
-                                        runtime_us);
-               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                        "Convert start time %llu and %llu with offset %llu to %llu\n",
-                        ktime_to_ns(dev->capture.kernel_start_ts),
--                       dev->capture.vc_start_timestamp, pts,
-+                       dev->capture.vc_start_timestamp, mmal_buf->pts,
-                        ktime_to_ns(timestamp));
-               if (timestamp < dev->capture.last_timestamp) {
-                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-@@ -416,15 +428,15 @@ static void buffer_cb(struct vchiq_mmal_
-       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-       buf->vb.sequence = dev->capture.sequence++;
--      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
--      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-+      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
-+      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-               buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                "Buffer has ts %llu", dev->capture.last_timestamp);
-       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
--      if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
-+      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
-           is_capturing(dev)) {
-               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                        "Grab another frame as buffer has EOS");
-@@ -507,14 +519,16 @@ static void buffer_queue(struct vb2_buff
- {
-       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-       struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
--      struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
-+      struct vb2_mmal_buffer *buf =
-+                              container_of(vb2, struct vb2_mmal_buffer, vb);
-       int ret;
-       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                "%s: dev:%p buf:%p, idx %u\n",
-                __func__, dev, buf, vb2->vb2_buf.index);
--      ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
-+      ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port,
-+                                     &buf->mmal);
-       if (ret < 0)
-               v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
-                        __func__);
-@@ -628,7 +642,7 @@ static void stop_streaming(struct vb2_qu
-       dev->capture.frame_count = 0;
-       /* ensure a format has actually been set */
--      if (!dev->capture.port) {
-+      if (!port) {
-               v4l2_err(&dev->v4l2_dev,
-                        "no capture port - stream not started?\n");
-               return;
-@@ -648,11 +662,11 @@ static void stop_streaming(struct vb2_qu
-       /* disable the connection from camera to encoder */
-       ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port);
--      if (!ret && dev->capture.camera_port != dev->capture.port) {
-+      if (!ret && dev->capture.camera_port != port) {
-               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                        "disabling port\n");
--              ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port);
--      } else if (dev->capture.camera_port != dev->capture.port) {
-+              ret = vchiq_mmal_port_disable(dev->instance, port);
-+      } else if (dev->capture.camera_port != port) {
-               v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
-                        ret);
-       }
-@@ -1954,7 +1968,7 @@ static int bcm2835_mmal_probe(struct pla
-               q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-               q->drv_priv = dev;
--              q->buf_struct_size = sizeof(struct mmal_buffer);
-+              q->buf_struct_size = sizeof(struct vb2_mmal_buffer);
-               q->ops = &bm2835_mmal_video_qops;
-               q->mem_ops = &vb2_vmalloc_memops;
-               q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -50,6 +50,11 @@ struct mmal_buffer {
-       unsigned long buffer_size; /* size of allocated buffer */
-       struct mmal_msg_context *msg_context;
-+
-+      unsigned long length;
-+      u32 mmal_flags;
-+      s64 dts;
-+      s64 pts;
- };
- /* */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -259,17 +259,25 @@ static void buffer_work_cb(struct work_s
- {
-       struct mmal_msg_context *msg_context =
-               container_of(work, struct mmal_msg_context, u.bulk.work);
-+      struct mmal_buffer *buffer = msg_context->u.bulk.buffer;
-+
-+      if (!buffer) {
-+              pr_err("%s: ctx: %p, No mmal buffer to pass details\n",
-+                     __func__, msg_context);
-+              return;
-+      }
-+
-+      buffer->length = msg_context->u.bulk.buffer_used;
-+      buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
-+      buffer->dts = msg_context->u.bulk.dts;
-+      buffer->pts = msg_context->u.bulk.pts;
-       atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-       msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
-                                           msg_context->u.bulk.port,
-                                           msg_context->u.bulk.status,
--                                          msg_context->u.bulk.buffer,
--                                          msg_context->u.bulk.buffer_used,
--                                          msg_context->u.bulk.mmal_flags,
--                                          msg_context->u.bulk.dts,
--                                          msg_context->u.bulk.pts);
-+                                          msg_context->u.bulk.buffer);
- }
- /* workqueue scheduled callback to handle receiving buffers
-@@ -1327,11 +1335,14 @@ static int port_disable(struct vchiq_mma
-                       mmalbuf = list_entry(buf_head, struct mmal_buffer,
-                                            list);
-                       list_del(buf_head);
--                      if (port->buffer_cb)
-+                      if (port->buffer_cb) {
-+                              mmalbuf->length = 0;
-+                              mmalbuf->mmal_flags = 0;
-+                              mmalbuf->dts = MMAL_TIME_UNKNOWN;
-+                              mmalbuf->pts = MMAL_TIME_UNKNOWN;
-                               port->buffer_cb(instance,
--                                              port, 0, mmalbuf, 0, 0,
--                                              MMAL_TIME_UNKNOWN,
--                                              MMAL_TIME_UNKNOWN);
-+                                              port, 0, mmalbuf);
-+                      }
-               }
-               spin_unlock_irqrestore(&port->slock, flags);
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -44,8 +44,7 @@ struct vchiq_mmal_port;
- typedef void (*vchiq_mmal_buffer_cb)(
-               struct vchiq_mmal_instance  *instance,
-               struct vchiq_mmal_port *port,
--              int status, struct mmal_buffer *buffer,
--              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
-+              int status, struct mmal_buffer *buffer);
- struct vchiq_mmal_port {
-       u32 enabled:1;
diff --git a/target/linux/brcm2708/patches-4.19/950-0238-staging-vc04_services-Support-sending-data-to-MMAL-p.patch b/target/linux/brcm2708/patches-4.19/950-0238-staging-vc04_services-Support-sending-data-to-MMAL-p.patch
new file mode 100644 (file)
index 0000000..9688bc8
--- /dev/null
@@ -0,0 +1,42 @@
+From 483bef9dcddc4bcb9f4e250d91b31361a919b7ed Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 18:26:02 +0100
+Subject: [PATCH] staging: vc04_services: Support sending data to MMAL
+ ports
+
+Add the ability to send data to ports. This only supports
+zero copy mode as the required bulk transfer setup calls
+are not done.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c      | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -428,11 +428,19 @@ buffer_from_host(struct vchiq_mmal_insta
+       m.u.buffer_from_host.buffer_header.data =
+               (u32)(unsigned long)buf->buffer;
+       m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
+-      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
+-      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
+-      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
+-      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
+-      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
++      if (port->type == MMAL_PORT_TYPE_OUTPUT) {
++              m.u.buffer_from_host.buffer_header.length = 0;
++              m.u.buffer_from_host.buffer_header.offset = 0;
++              m.u.buffer_from_host.buffer_header.flags = 0;
++              m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
++              m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
++      } else {
++              m.u.buffer_from_host.buffer_header.length = buf->length;
++              m.u.buffer_from_host.buffer_header.offset = 0;
++              m.u.buffer_from_host.buffer_header.flags = buf->mmal_flags;
++              m.u.buffer_from_host.buffer_header.pts = buf->pts;
++              m.u.buffer_from_host.buffer_header.dts = buf->dts;
++      }
+       /* clear buffer type sepecific data */
+       memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
diff --git a/target/linux/brcm2708/patches-4.19/950-0239-staging-mmal-vchiq-Add-support-for-event-callbacks.patch b/target/linux/brcm2708/patches-4.19/950-0239-staging-mmal-vchiq-Add-support-for-event-callbacks.patch
deleted file mode 100644 (file)
index b79bdb8..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-From adab474d1f91594d6d96d44054586ba36d7f26d4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 18:15:38 +0100
-Subject: [PATCH] staging: mmal-vchiq: Add support for event callbacks.
-
-(Preparation for the codec driver).
-The codec uses the event mechanism to report things such as
-resolution changes. It is signalled by the cmd field of the buffer
-being non-zero.
-
-Add support for passing this information out to the client.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-common.h    |   1 +
- .../vc04_services/vchiq-mmal/mmal-msg.h       |  35 ++++
- .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 170 ++++++++++++++++--
- .../vc04_services/vchiq-mmal/mmal-vchiq.h     |   4 +
- 4 files changed, 196 insertions(+), 14 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -51,6 +51,7 @@ struct mmal_buffer {
-       struct mmal_msg_context *msg_context;
-+      u32 cmd;                /* MMAL command. 0=data. */
-       unsigned long length;
-       u32 mmal_flags;
-       s64 dts;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-@@ -346,6 +346,41 @@ struct mmal_msg_port_parameter_get_reply
- /* event messages */
- #define MMAL_WORKER_EVENT_SPACE 256
-+/* Four CC's for events */
-+#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
-+
-+#define MMAL_EVENT_ERROR              MMAL_FOURCC('E', 'R', 'R', 'O')
-+#define MMAL_EVENT_EOS                        MMAL_FOURCC('E', 'E', 'O', 'S')
-+#define MMAL_EVENT_FORMAT_CHANGED     MMAL_FOURCC('E', 'F', 'C', 'H')
-+#define MMAL_EVENT_PARAMETER_CHANGED  MMAL_FOURCC('E', 'P', 'C', 'H')
-+
-+/* Structs for each of the event message payloads */
-+struct mmal_msg_event_eos {
-+      u32 port_type;  /**< Type of port that received the end of stream */
-+      u32 port_index; /**< Index of port that received the end of stream */
-+};
-+
-+/** Format changed event data. */
-+struct mmal_msg_event_format_changed {
-+      /* Minimum size of buffers the port requires */
-+      u32 buffer_size_min;
-+      /* Minimum number of buffers the port requires */
-+      u32 buffer_num_min;
-+      /* Size of buffers the port recommends for optimal performance.
-+       * A value of zero means no special recommendation.
-+       */
-+      u32 buffer_size_recommended;
-+      /* Number of buffers the port recommends for optimal
-+       * performance. A value of zero means no special recommendation.
-+       */
-+      u32 buffer_num_recommended;
-+
-+      u32 es_ptr;
-+      struct mmal_es_format format;
-+      union mmal_es_specific_format es;
-+      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
-+};
-+
- struct mmal_msg_event_to_host {
-       u32 client_component;   /* component context */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -151,6 +151,8 @@ struct mmal_msg_context {
-                       /* Presentation and Decode timestamps */
-                       s64 pts;
-                       s64 dts;
-+                      /* MMAL buffer command flag */
-+                      u32 cmd;
-                       int status;     /* context status */
-@@ -238,18 +240,6 @@ release_msg_context(struct mmal_msg_cont
-       kfree(msg_context);
- }
--/* deals with receipt of event to host message */
--static void event_to_host_cb(struct vchiq_mmal_instance *instance,
--                           struct mmal_msg *msg, u32 msg_len)
--{
--      pr_debug("unhandled event\n");
--      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
--               msg->u.event_to_host.client_component,
--               msg->u.event_to_host.port_type,
--               msg->u.event_to_host.port_num,
--               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
--}
--
- /* workqueue scheduled callback
-  *
-  * we do this because it is important we do not call any other vchiq
-@@ -271,13 +261,18 @@ static void buffer_work_cb(struct work_s
-       buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
-       buffer->dts = msg_context->u.bulk.dts;
-       buffer->pts = msg_context->u.bulk.pts;
-+      buffer->cmd = msg_context->u.bulk.cmd;
--      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-+      if (!buffer->cmd)
-+              atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-       msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
-                                           msg_context->u.bulk.port,
-                                           msg_context->u.bulk.status,
-                                           msg_context->u.bulk.buffer);
-+
-+      if (buffer->cmd)
-+              mutex_unlock(&msg_context->u.bulk.port->event_context_mutex);
- }
- /* workqueue scheduled callback to handle receiving buffers
-@@ -356,6 +351,7 @@ static int bulk_receive(struct vchiq_mma
-       msg_context->u.bulk.buffer_used = rd_len;
-       msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
-       msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
-+      msg_context->u.bulk.cmd = msg->u.buffer_from_host.buffer_header.cmd;
-       queue_work(msg_context->instance->bulk_wq,
-                  &msg_context->u.bulk.buffer_to_host_work);
-@@ -457,6 +453,103 @@ buffer_from_host(struct vchiq_mmal_insta
-       return ret;
- }
-+/* deals with receipt of event to host message */
-+static void event_to_host_cb(struct vchiq_mmal_instance *instance,
-+                           struct mmal_msg *msg, u32 msg_len)
-+{
-+      /* FIXME: Not going to work on 64 bit */
-+      struct vchiq_mmal_component *component =
-+              (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
-+      struct vchiq_mmal_port *port = NULL;
-+      struct mmal_msg_context *msg_context;
-+      u32 port_num = msg->u.event_to_host.port_num;
-+
-+      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
-+              pr_err("%s: MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n",
-+                     __func__);
-+              return;
-+      }
-+
-+      switch (msg->u.event_to_host.port_type) {
-+      case MMAL_PORT_TYPE_CONTROL:
-+              if (port_num) {
-+                      pr_err("%s: port_num of %u >= number of ports 1",
-+                             __func__, port_num);
-+                      return;
-+              }
-+              port = &component->control;
-+              break;
-+      case MMAL_PORT_TYPE_INPUT:
-+              if (port_num >= component->inputs) {
-+                      pr_err("%s: port_num of %u >= number of ports %u",
-+                             __func__, port_num,
-+                             port_num >= component->inputs);
-+                      return;
-+              }
-+              port = &component->input[port_num];
-+              break;
-+      case MMAL_PORT_TYPE_OUTPUT:
-+              if (port_num >= component->outputs) {
-+                      pr_err("%s: port_num of %u >= number of ports %u",
-+                             __func__, port_num,
-+                             port_num >= component->outputs);
-+                      return;
-+              }
-+              port = &component->output[port_num];
-+              break;
-+      case MMAL_PORT_TYPE_CLOCK:
-+              if (port_num >= component->clocks) {
-+                      pr_err("%s: port_num of %u >= number of ports %u",
-+                             __func__, port_num,
-+                             port_num >= component->clocks);
-+                      return;
-+              }
-+              port = &component->clock[port_num];
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      if (!mutex_trylock(&port->event_context_mutex)) {
-+              pr_err("dropping event 0x%x\n", msg->u.event_to_host.cmd);
-+              return;
-+      }
-+      msg_context = port->event_context;
-+
-+      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
-+              /* message reception had an error */
-+              //pr_warn
-+              pr_err("%s: error %d in reply\n", __func__, msg->h.status);
-+
-+              msg_context->u.bulk.status = msg->h.status;
-+      } else if (msg->u.event_to_host.length > MMAL_WORKER_EVENT_SPACE) {
-+              /* data is not in message, queue a bulk receive */
-+              pr_err("%s: payload not in message - bulk receive??! NOT SUPPORTED\n",
-+                     __func__);
-+              msg_context->u.bulk.status = -1;
-+      } else {
-+              memcpy(msg_context->u.bulk.buffer->buffer,
-+                     msg->u.event_to_host.data,
-+                     msg->u.event_to_host.length);
-+
-+              msg_context->u.bulk.buffer_used =
-+                  msg->u.event_to_host.length;
-+
-+              msg_context->u.bulk.mmal_flags = 0;
-+              msg_context->u.bulk.dts = MMAL_TIME_UNKNOWN;
-+              msg_context->u.bulk.pts = MMAL_TIME_UNKNOWN;
-+              msg_context->u.bulk.cmd = msg->u.event_to_host.cmd;
-+
-+              pr_debug("event component:%u port type:%d num:%d cmd:0x%x length:%d\n",
-+                       msg->u.event_to_host.client_component,
-+                       msg->u.event_to_host.port_type,
-+                       msg->u.event_to_host.port_num,
-+                       msg->u.event_to_host.cmd, msg->u.event_to_host.length);
-+      }
-+
-+      schedule_work(&msg_context->u.bulk.work);
-+}
-+
- /* deals with receipt of buffer to host message */
- static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
-                             struct mmal_msg *msg, u32 msg_len)
-@@ -1340,6 +1433,7 @@ static int port_disable(struct vchiq_mma
-                               mmalbuf->mmal_flags = 0;
-                               mmalbuf->dts = MMAL_TIME_UNKNOWN;
-                               mmalbuf->pts = MMAL_TIME_UNKNOWN;
-+                              mmalbuf->cmd = 0;
-                               port->buffer_cb(instance,
-                                               port, 0, mmalbuf);
-                       }
-@@ -1641,6 +1735,43 @@ int mmal_vchi_buffer_cleanup(struct mmal
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
-+static void init_event_context(struct vchiq_mmal_instance *instance,
-+                             struct vchiq_mmal_port *port)
-+{
-+      struct mmal_msg_context *ctx = get_msg_context(instance);
-+
-+      mutex_init(&port->event_context_mutex);
-+
-+      port->event_context = ctx;
-+      ctx->u.bulk.instance = instance;
-+      ctx->u.bulk.port = port;
-+      ctx->u.bulk.buffer =
-+              kzalloc(sizeof(*ctx->u.bulk.buffer), GFP_KERNEL);
-+      if (!ctx->u.bulk.buffer)
-+              goto release_msg_context;
-+      ctx->u.bulk.buffer->buffer = kzalloc(MMAL_WORKER_EVENT_SPACE,
-+                                           GFP_KERNEL);
-+      if (!ctx->u.bulk.buffer->buffer)
-+              goto release_buffer;
-+
-+      INIT_WORK(&ctx->u.bulk.work, buffer_work_cb);
-+      return;
-+
-+release_buffer:
-+      kfree(ctx->u.bulk.buffer);
-+release_msg_context:
-+      release_msg_context(ctx);
-+}
-+
-+static void free_event_context(struct vchiq_mmal_port *port)
-+{
-+      struct mmal_msg_context *ctx = port->event_context;
-+
-+      kfree(ctx->u.bulk.buffer->buffer);
-+      kfree(ctx->u.bulk.buffer);
-+      release_msg_context(ctx);
-+}
-+
- /* Initialise a mmal component and its ports
-  *
-  */
-@@ -1684,6 +1815,7 @@ int vchiq_mmal_component_init(struct vch
-       ret = port_info_get(instance, &component->control);
-       if (ret < 0)
-               goto release_component;
-+      init_event_context(instance, &component->control);
-       for (idx = 0; idx < component->inputs; idx++) {
-               component->input[idx].type = MMAL_PORT_TYPE_INPUT;
-@@ -1694,6 +1826,7 @@ int vchiq_mmal_component_init(struct vch
-               ret = port_info_get(instance, &component->input[idx]);
-               if (ret < 0)
-                       goto release_component;
-+              init_event_context(instance, &component->input[idx]);
-       }
-       for (idx = 0; idx < component->outputs; idx++) {
-@@ -1705,6 +1838,7 @@ int vchiq_mmal_component_init(struct vch
-               ret = port_info_get(instance, &component->output[idx]);
-               if (ret < 0)
-                       goto release_component;
-+              init_event_context(instance, &component->output[idx]);
-       }
-       for (idx = 0; idx < component->clocks; idx++) {
-@@ -1716,6 +1850,7 @@ int vchiq_mmal_component_init(struct vch
-               ret = port_info_get(instance, &component->clock[idx]);
-               if (ret < 0)
-                       goto release_component;
-+              init_event_context(instance, &component->clock[idx]);
-       }
-       *component_out = component;
-@@ -1741,7 +1876,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
- int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
-                                 struct vchiq_mmal_component *component)
- {
--      int ret;
-+      int ret, idx;
-       if (mutex_lock_interruptible(&instance->vchiq_mutex))
-               return -EINTR;
-@@ -1753,6 +1888,13 @@ int vchiq_mmal_component_finalise(struct
-       component->in_use = 0;
-+      for (idx = 0; idx < component->inputs; idx++)
-+              free_event_context(&component->input[idx]);
-+      for (idx = 0; idx < component->outputs; idx++)
-+              free_event_context(&component->output[idx]);
-+      for (idx = 0; idx < component->clocks; idx++)
-+              free_event_context(&component->clock[idx]);
-+
-       mutex_unlock(&instance->vchiq_mutex);
-       return ret;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -78,6 +78,10 @@ struct vchiq_mmal_port {
-       vchiq_mmal_buffer_cb buffer_cb;
-       /* callback context */
-       void *cb_ctx;
-+
-+      /* ensure serialised use of the one event context structure */
-+      struct mutex event_context_mutex;
-+      struct mmal_msg_context *event_context;
- };
- struct vchiq_mmal_component {
diff --git a/target/linux/brcm2708/patches-4.19/950-0239-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch b/target/linux/brcm2708/patches-4.19/950-0239-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch
new file mode 100644 (file)
index 0000000..6c54743
--- /dev/null
@@ -0,0 +1,36 @@
+From 2a5a03926a8c6ae7375355de00814234e4e303ed Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 16:57:40 +0100
+Subject: [PATCH] staging: vc04_services: Fixup vchiq-mmal include
+ ordering
+
+There were dependencies on including the headers in the correct
+order. Fix up the headers so that they include the other
+headers that they depend on themselves.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h   | 1 +
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
+@@ -38,6 +38,7 @@
+ #include "mmal-msg-common.h"
+ #include "mmal-msg-format.h"
+ #include "mmal-msg-port.h"
++#include "mmal-vchiq.h"
+ enum mmal_msg_type {
+       MMAL_MSG_TYPE_QUIT = 1,
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -16,6 +16,7 @@
+ #ifndef MMAL_VCHIQ_H
+ #define MMAL_VCHIQ_H
++#include "mmal-common.h"
+ #include "mmal-msg-format.h"
+ #define MAX_PORT_COUNT 4
diff --git a/target/linux/brcm2708/patches-4.19/950-0240-staging-vc04_services-Add-new-vc-sm-cma-driver.patch b/target/linux/brcm2708/patches-4.19/950-0240-staging-vc04_services-Add-new-vc-sm-cma-driver.patch
new file mode 100644 (file)
index 0000000..9e9af47
--- /dev/null
@@ -0,0 +1,1881 @@
+From 2994fdc0a9d48be68d6e403bc8ddadecfc8d8796 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 10:27:11 +0100
+Subject: [PATCH] staging: vc04_services: Add new vc-sm-cma driver
+
+This new driver allows contiguous memory blocks to be imported
+into the VideoCore VPU memory map, and manages the lifetime of
+those objects, only releasing the source dmabuf once the VPU has
+confirmed it has finished with it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/Kconfig         |   1 +
+ drivers/staging/vc04_services/Makefile        |   1 +
+ .../staging/vc04_services/vc-sm-cma/Kconfig   |  10 +
+ .../staging/vc04_services/vc-sm-cma/Makefile  |   8 +
+ drivers/staging/vc04_services/vc-sm-cma/TODO  |   2 +
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 838 ++++++++++++++++++
+ .../staging/vc04_services/vc-sm-cma/vc_sm.h   |  59 ++
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  | 498 +++++++++++
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h  |  59 ++
+ .../vc04_services/vc-sm-cma/vc_sm_defs.h      | 298 +++++++
+ .../vc04_services/vc-sm-cma/vc_sm_knl.h       |  28 +
+ 11 files changed, 1802 insertions(+)
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Kconfig
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Makefile
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/TODO
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
+
+--- a/drivers/staging/vc04_services/Kconfig
++++ b/drivers/staging/vc04_services/Kconfig
+@@ -22,6 +22,7 @@ source "drivers/staging/vc04_services/bc
+ source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
+ source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
++source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
+ endif
+--- a/drivers/staging/vc04_services/Makefile
++++ b/drivers/staging/vc04_services/Makefile
+@@ -13,6 +13,7 @@ vchiq-objs := \
+ obj-$(CONFIG_SND_BCM2835)     += bcm2835-audio/
+ obj-$(CONFIG_VIDEO_BCM2835)   += bcm2835-camera/
+ obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
++obj-$(CONFIG_BCM_VC_SM_CMA)   += vc-sm-cma/
+ ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
+@@ -0,0 +1,10 @@
++config BCM_VC_SM_CMA
++      tristate "VideoCore Shared Memory (CMA) driver"
++      depends on BCM2835_VCHIQ
++      select RBTREE
++      select DMA_SHARED_BUFFER
++      help
++        Say Y here to enable the shared memory interface that
++        supports sharing dmabufs with VideoCore.
++        This operates over the VCHIQ interface to a service
++        running on VideoCore.
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
+@@ -0,0 +1,8 @@
++ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vchi -Idrivers/staging/vc04_services/interface/vchiq_arm
++# -I"drivers/staging/android/ion/" -I"$(srctree)/fs/"
++ccflags-y += -D__VCCOREVER__=0
++
++vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
++      vc_sm.o vc_sm_cma_vchi.o
++
++obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
+@@ -0,0 +1,2 @@
++1) Convert to a platform driver.
++
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -0,0 +1,838 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * VideoCore Shared Memory driver using CMA.
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ * Dave Stevenson <dave.stevenson@raspberrypi.org>
++ *
++ * Based on vmcs_sm driver from Broadcom Corporation for some API,
++ * and taking some code for CMA/dmabuf handling from the Android Ion
++ * driver (Google/Linaro).
++ *
++ * This is cut down version to only support import of dma_bufs from
++ * other kernel drivers. A more complete implementation of the old
++ * vmcs_sm functionality can follow later.
++ *
++ */
++
++/* ---- Include Files ----------------------------------------------------- */
++#include <linux/cdev.h>
++#include <linux/device.h>
++#include <linux/debugfs.h>
++#include <linux/dma-mapping.h>
++#include <linux/dma-buf.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/proc_fs.h>
++#include <linux/slab.h>
++#include <linux/seq_file.h>
++#include <linux/syscalls.h>
++#include <linux/types.h>
++
++#include "vchiq_connected.h"
++#include "vc_sm_cma_vchi.h"
++
++#include "vc_sm.h"
++#include "vc_sm_knl.h"
++
++/* ---- Private Constants and Types --------------------------------------- */
++
++#define DEVICE_NAME           "vcsm-cma"
++#define DEVICE_MINOR          0
++
++#define VC_SM_RESOURCE_NAME_DEFAULT       "sm-host-resource"
++
++#define VC_SM_DIR_ROOT_NAME   "vcsm-cma"
++#define VC_SM_STATE           "state"
++
++/* Private file data associated with each opened device. */
++struct vc_sm_privdata_t {
++      pid_t pid;                      /* PID of creator. */
++
++      int restart_sys;                /* Tracks restart on interrupt. */
++      enum vc_sm_msg_type int_action; /* Interrupted action. */
++      u32 int_trans_id;               /* Interrupted transaction. */
++};
++
++typedef int (*VC_SM_SHOW) (struct seq_file *s, void *v);
++struct sm_pde_t {
++      VC_SM_SHOW show;          /* Debug fs function hookup. */
++      struct dentry *dir_entry; /* Debug fs directory entry. */
++      void *priv_data;          /* Private data */
++};
++
++/* Global state information. */
++struct sm_state_t {
++      struct platform_device *pdev;
++
++      struct miscdevice dev;
++      struct sm_instance *sm_handle;  /* Handle for videocore service. */
++
++      struct mutex map_lock;          /* Global map lock. */
++      struct list_head buffer_list;   /* List of buffer. */
++
++      struct vc_sm_privdata_t *data_knl;  /* Kernel internal data tracking. */
++      struct dentry *dir_root;        /* Debug fs entries root. */
++      struct sm_pde_t dir_state;      /* Debug fs entries state sub-tree. */
++
++      bool require_released_callback; /* VPU will send a released msg when it
++                                       * has finished with a resource.
++                                       */
++      u32 int_trans_id;               /* Interrupted transaction. */
++};
++
++/* ---- Private Variables ----------------------------------------------- */
++
++static struct sm_state_t *sm_state;
++static int sm_inited;
++
++/* ---- Private Function Prototypes -------------------------------------- */
++
++/* ---- Private Functions ------------------------------------------------ */
++
++static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
++{
++      struct sm_pde_t *sm_pde;
++
++      sm_pde = (struct sm_pde_t *)(s->private);
++
++      if (sm_pde && sm_pde->show)
++              sm_pde->show(s, v);
++
++      return 0;
++}
++
++static int vc_sm_cma_single_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, vc_sm_cma_seq_file_show, inode->i_private);
++}
++
++static const struct file_operations vc_sm_cma_debug_fs_fops = {
++      .open = vc_sm_cma_single_open,
++      .read = seq_read,
++      .llseek = seq_lseek,
++      .release = single_release,
++};
++
++static int vc_sm_cma_global_state_show(struct seq_file *s, void *v)
++{
++      struct vc_sm_buffer *resource = NULL;
++      int resource_count = 0;
++
++      if (!sm_state)
++              return 0;
++
++      seq_printf(s, "\nVC-ServiceHandle     0x%x\n",
++                 (unsigned int)sm_state->sm_handle);
++
++      /* Log all applicable mapping(s). */
++
++      mutex_lock(&sm_state->map_lock);
++      seq_puts(s, "\nResources\n");
++      if (!list_empty(&sm_state->buffer_list)) {
++              list_for_each_entry(resource, &sm_state->buffer_list,
++                                  global_buffer_list) {
++                      resource_count++;
++
++                      seq_printf(s, "\nResource                %p\n",
++                                 resource);
++                      seq_printf(s, "           NAME         %s\n",
++                                 resource->name);
++                      seq_printf(s, "           SIZE         %d\n",
++                                 resource->size);
++                      seq_printf(s, "           DMABUF       %p\n",
++                                 resource->dma_buf);
++                      seq_printf(s, "           ATTACH       %p\n",
++                                 resource->attach);
++                      seq_printf(s, "           SG_TABLE     %p\n",
++                                 resource->sg_table);
++                      seq_printf(s, "           SGT          %p\n",
++                                 resource->sgt);
++                      seq_printf(s, "           DMA_ADDR     %pad\n",
++                                 &resource->dma_addr);
++                      seq_printf(s, "           VC_HANDLE     %08x\n",
++                                 resource->vc_handle);
++                      seq_printf(s, "           VC_MAPPING    %d\n",
++                                 resource->vpu_state);
++              }
++      }
++      seq_printf(s, "\n\nTotal resource count:   %d\n\n", resource_count);
++
++      mutex_unlock(&sm_state->map_lock);
++
++      return 0;
++}
++
++/*
++ * Adds a buffer to the private data list which tracks all the allocated
++ * data.
++ */
++static void vc_sm_add_resource(struct vc_sm_privdata_t *privdata,
++                             struct vc_sm_buffer *buffer)
++{
++      mutex_lock(&sm_state->map_lock);
++      list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
++      mutex_unlock(&sm_state->map_lock);
++
++      pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
++               __func__, buffer, buffer->name, buffer->size);
++}
++
++/*
++ * Release an allocation.
++ * All refcounting is done via the dma buf object.
++ */
++static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
++{
++      mutex_lock(&sm_state->map_lock);
++      mutex_lock(&buffer->lock);
++
++      pr_debug("[%s]: buffer %p (name %s, size %d)\n",
++               __func__, buffer, buffer->name, buffer->size);
++
++      if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
++              struct vc_sm_free_t free = { buffer->vc_handle, 0 };
++              int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
++                                           &sm_state->int_trans_id);
++              if (status != 0 && status != -EINTR) {
++                      pr_err("[%s]: failed to free memory on videocore (status: %u, trans_id: %u)\n",
++                             __func__, status, sm_state->int_trans_id);
++              }
++
++              if (sm_state->require_released_callback) {
++                      /* Need to wait for the VPU to confirm the free */
++
++                      /* Retain a reference on this until the VPU has
++                       * released it
++                       */
++                      buffer->vpu_state = VPU_UNMAPPING;
++                      goto defer;
++              }
++              buffer->vpu_state = VPU_NOT_MAPPED;
++              buffer->vc_handle = 0;
++      }
++      if (buffer->vc_handle) {
++              /* We've sent the unmap request but not had the response. */
++              pr_err("[%s]: Waiting for VPU unmap response on %p\n",
++                     __func__, buffer);
++              goto defer;
++      }
++      if (buffer->in_use) {
++              /* Don't release dmabuf here - we await the release */
++              pr_err("[%s]: buffer %p is still in use\n",
++                     __func__, buffer);
++              goto defer;
++      }
++
++      /* Handle cleaning up imported dmabufs */
++      if (buffer->sgt) {
++              dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
++                                       DMA_BIDIRECTIONAL);
++              buffer->sgt = NULL;
++      }
++      if (buffer->attach) {
++              dma_buf_detach(buffer->dma_buf, buffer->attach);
++              buffer->attach = NULL;
++      }
++
++      /* Release the dma_buf (whether ours or imported) */
++      if (buffer->import_dma_buf) {
++              dma_buf_put(buffer->import_dma_buf);
++              buffer->import_dma_buf = NULL;
++              buffer->dma_buf = NULL;
++      } else if (buffer->dma_buf) {
++              dma_buf_put(buffer->dma_buf);
++              buffer->dma_buf = NULL;
++      }
++
++      if (buffer->sg_table && !buffer->import_dma_buf) {
++              /* Our own allocation that we need to dma_unmap_sg */
++              dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
++                           buffer->sg_table->nents, DMA_BIDIRECTIONAL);
++      }
++
++      /* Free the local resource. Start by removing it from the list */
++      buffer->private = NULL;
++      list_del(&buffer->global_buffer_list);
++
++      mutex_unlock(&buffer->lock);
++      mutex_unlock(&sm_state->map_lock);
++
++      mutex_destroy(&buffer->lock);
++
++      kfree(buffer);
++      return;
++
++defer:
++      mutex_unlock(&buffer->lock);
++      mutex_unlock(&sm_state->map_lock);
++}
++
++/* Create support for private data tracking. */
++static struct vc_sm_privdata_t *vc_sm_cma_create_priv_data(pid_t id)
++{
++      char alloc_name[32];
++      struct vc_sm_privdata_t *file_data = NULL;
++
++      /* Allocate private structure. */
++      file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
++
++      if (!file_data)
++              return NULL;
++
++      snprintf(alloc_name, sizeof(alloc_name), "%d", id);
++
++      file_data->pid = id;
++
++      return file_data;
++}
++
++/* Dma_buf operations for chaining through to an imported dma_buf */
++static
++int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
++                              struct dma_buf_attachment *attachment)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return -EINVAL;
++      return res->import_dma_buf->ops->attach(res->import_dma_buf,
++                                              attachment);
++}
++
++static
++void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
++                                struct dma_buf_attachment *attachment)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return;
++      res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
++}
++
++static
++struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
++                                        enum dma_data_direction direction)
++{
++      struct vc_sm_buffer *res = attachment->dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return NULL;
++      return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
++}
++
++static
++void vc_sm_import_unmap_dma_buf(struct dma_buf_attachment *attachment,
++                              struct sg_table *table,
++                              enum dma_data_direction direction)
++{
++      struct vc_sm_buffer *res = attachment->dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return;
++      res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
++}
++
++static
++int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
++               dmabuf, res, res->import_dma_buf);
++      if (!res->import_dma_buf) {
++              pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
++                     __func__, dmabuf);
++              return -EINVAL;
++      }
++      return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
++}
++
++static
++void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
++      if (!res->import_dma_buf)
++              return;
++
++      res->in_use = 0;
++
++      vc_sm_release_resource(res, 0);
++}
++
++static
++void *vc_sm_import_dma_buf_kmap(struct dma_buf *dmabuf,
++                              unsigned long offset)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return NULL;
++      return res->import_dma_buf->ops->map(res->import_dma_buf,
++                                                    offset);
++}
++
++static
++void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
++                               unsigned long offset, void *ptr)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return;
++      res->import_dma_buf->ops->unmap(res->import_dma_buf,
++                                             offset, ptr);
++}
++
++static
++int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
++                                        enum dma_data_direction direction)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return -EINVAL;
++      return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
++                                                          direction);
++}
++
++static
++int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
++                                      enum dma_data_direction direction)
++{
++      struct vc_sm_buffer *res = dmabuf->priv;
++
++      if (!res->import_dma_buf)
++              return -EINVAL;
++      return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
++                                                        direction);
++}
++
++static const struct dma_buf_ops dma_buf_import_ops = {
++      .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,
++      .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,
++      .end_cpu_access = vc_sm_import_dma_buf_end_cpu_access,
++      .map = vc_sm_import_dma_buf_kmap,
++      .unmap = vc_sm_import_dma_buf_kunmap,
++};
++
++/* Import a dma_buf to be shared with VC. */
++int
++vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
++                               struct dma_buf *dma_buf,
++                               struct dma_buf **imported_buf)
++{
++      DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
++      struct vc_sm_buffer *buffer = NULL;
++      struct vc_sm_import import = { };
++      struct vc_sm_import_result result = { };
++      struct dma_buf_attachment *attach = NULL;
++      struct sg_table *sgt = NULL;
++      int ret = 0;
++      int status;
++
++      /* Setup our allocation parameters */
++      pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
++
++      get_dma_buf(dma_buf);
++      dma_buf = dma_buf;
++
++      attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
++      if (IS_ERR(attach)) {
++              ret = PTR_ERR(attach);
++              goto error;
++      }
++
++      sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
++      if (IS_ERR(sgt)) {
++              ret = PTR_ERR(sgt);
++              goto error;
++      }
++
++      /* Verify that the address block is contiguous */
++      if (sgt->nents != 1) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      /* Allocate local buffer to track this allocation. */
++      buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
++      if (!buffer) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      import.type = VC_SM_ALLOC_NON_CACHED;
++      import.addr = (uint32_t)sg_dma_address(sgt->sgl);
++      if ((import.addr & 0xC0000000) != 0xC0000000) {
++              pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
++                     __func__, import.addr);
++              import.addr |= 0xC0000000;
++      }
++      import.size = sg_dma_len(sgt->sgl);
++      import.allocator = current->tgid;
++      import.kernel_id = (uint32_t)buffer;    //FIXME: 64 bit support needed.
++
++      memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
++             sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
++
++      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
++               __func__, import.name, import.type, (void *)import.addr,
++               import.size);
++
++      /* Allocate the videocore buffer. */
++      status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
++                                     &sm_state->int_trans_id);
++      if (status == -EINTR) {
++              pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
++                       __func__, sm_state->int_trans_id);
++              ret = -ERESTARTSYS;
++              private->restart_sys = -EINTR;
++              private->int_action = VC_SM_MSG_TYPE_IMPORT;
++              goto error;
++      } else if (status || !result.res_handle) {
++              pr_debug("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
++                       __func__, status, sm_state->int_trans_id);
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      mutex_init(&buffer->lock);
++      INIT_LIST_HEAD(&buffer->attachments);
++      memcpy(buffer->name, import.name,
++             min(sizeof(buffer->name), sizeof(import.name) - 1));
++
++      /* Keep track of the buffer we created. */
++      buffer->private = private;
++      buffer->vc_handle = result.res_handle;
++      buffer->size = import.size;
++      buffer->vpu_state = VPU_MAPPED;
++
++      buffer->import_dma_buf = dma_buf;
++
++      buffer->attach = attach;
++      buffer->sgt = sgt;
++      buffer->dma_addr = sg_dma_address(sgt->sgl);
++      buffer->in_use = 1;
++
++      /*
++       * We're done - we need to export a new dmabuf chaining through most
++       * functions, but enabling us to release our own internal references
++       * here.
++       */
++      exp_info.ops = &dma_buf_import_ops;
++      exp_info.size = import.size;
++      exp_info.flags = O_RDWR;
++      exp_info.priv = buffer;
++
++      buffer->dma_buf = dma_buf_export(&exp_info);
++      if (IS_ERR(buffer->dma_buf)) {
++              ret = PTR_ERR(buffer->dma_buf);
++              goto error;
++      }
++
++      vc_sm_add_resource(private, buffer);
++
++      *imported_buf = buffer->dma_buf;
++
++      return 0;
++
++error:
++      if (result.res_handle) {
++              struct vc_sm_free_t free = { result.res_handle, 0 };
++
++              vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
++                                  &sm_state->int_trans_id);
++      }
++      kfree(buffer);
++      if (sgt)
++              dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
++      if (attach)
++              dma_buf_detach(dma_buf, attach);
++      dma_buf_put(dma_buf);
++      return ret;
++}
++
++/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
++void
++vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
++              int reply_len)
++{
++      switch (reply->trans_id & ~0x80000000) {
++      case VC_SM_MSG_TYPE_CLIENT_VERSION:
++      {
++              /* Acknowledge that the firmware supports the version command */
++              pr_debug("%s: firmware acked version msg. Require release cb\n",
++                       __func__);
++              sm_state->require_released_callback = true;
++      }
++      break;
++      case VC_SM_MSG_TYPE_RELEASED:
++      {
++              struct vc_sm_released *release = (struct vc_sm_released *)reply;
++              struct vc_sm_buffer *buffer =
++                              (struct vc_sm_buffer *)release->kernel_id;
++
++              /*
++               * FIXME: Need to check buffer is still valid and allocated
++               * before continuing
++               */
++              pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
++                       __func__, release->addr, release->size,
++                       release->kernel_id, release->vc_handle);
++              mutex_lock(&buffer->lock);
++              buffer->vc_handle = 0;
++              buffer->vpu_state = VPU_NOT_MAPPED;
++              mutex_unlock(&buffer->lock);
++
++              vc_sm_release_resource(buffer, 0);
++      }
++      break;
++      default:
++              pr_err("%s: Unknown vpu cmd %x\n", __func__, reply->trans_id);
++              break;
++      }
++}
++
++/* Videocore connected.  */
++static void vc_sm_connected_init(void)
++{
++      int ret;
++      VCHI_INSTANCE_T vchi_instance;
++      struct vc_sm_version version;
++      struct vc_sm_result_t version_result;
++
++      pr_info("[%s]: start\n", __func__);
++
++      /*
++       * Initialize and create a VCHI connection for the shared memory service
++       * running on videocore.
++       */
++      ret = vchi_initialise(&vchi_instance);
++      if (ret) {
++              pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
++                     __func__, ret);
++
++              ret = -EIO;
++              goto err_free_mem;
++      }
++
++      ret = vchi_connect(vchi_instance);
++      if (ret) {
++              pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
++                     __func__, ret);
++
++              ret = -EIO;
++              goto err_free_mem;
++      }
++
++      /* Initialize an instance of the shared memory service. */
++      sm_state->sm_handle = vc_sm_cma_vchi_init(vchi_instance, 1,
++                                                vc_sm_vpu_event);
++      if (!sm_state->sm_handle) {
++              pr_err("[%s]: failed to initialize shared memory service\n",
++                     __func__);
++
++              ret = -EPERM;
++              goto err_free_mem;
++      }
++
++      /* Create a debug fs directory entry (root). */
++      sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
++      if (!sm_state->dir_root) {
++              pr_err("[%s]: failed to create \'%s\' directory entry\n",
++                     __func__, VC_SM_DIR_ROOT_NAME);
++
++              ret = -EPERM;
++              goto err_stop_sm_service;
++      }
++
++      sm_state->dir_state.show = &vc_sm_cma_global_state_show;
++      sm_state->dir_state.dir_entry =
++              debugfs_create_file(VC_SM_STATE, 0444, sm_state->dir_root,
++                                  &sm_state->dir_state,
++                                  &vc_sm_cma_debug_fs_fops);
++
++      INIT_LIST_HEAD(&sm_state->buffer_list);
++
++      sm_state->data_knl = vc_sm_cma_create_priv_data(0);
++      if (!sm_state->data_knl) {
++              pr_err("[%s]: failed to create kernel private data tracker\n",
++                     __func__);
++              goto err_remove_shared_memory;
++      }
++
++      version.version = 1;
++      ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
++                                          &version_result,
++                                          &sm_state->int_trans_id);
++      if (ret) {
++              pr_err("[%s]: Failed to send version request %d\n", __func__,
++                     ret);
++      }
++
++      /* Done! */
++      sm_inited = 1;
++      pr_info("[%s]: installed successfully\n", __func__);
++      return;
++
++err_remove_shared_memory:
++      debugfs_remove_recursive(sm_state->dir_root);
++err_stop_sm_service:
++      vc_sm_cma_vchi_stop(&sm_state->sm_handle);
++err_free_mem:
++      kfree(sm_state);
++      pr_info("[%s]: failed, ret %d\n", __func__, ret);
++}
++
++/* Driver loading. */
++static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      int err;
++
++      pr_info("%s: Videocore shared memory driver\n", __func__);
++
++      sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
++      if (!sm_state)
++              return -ENOMEM;
++      sm_state->pdev = pdev;
++      mutex_init(&sm_state->map_lock);
++
++      dev->coherent_dma_mask = DMA_BIT_MASK(32);
++      dev->dma_mask = &dev->coherent_dma_mask;
++      err = of_dma_configure(dev, NULL, true);
++      if (err) {
++              dev_err(dev, "Unable to setup DMA: %d\n", err);
++              return err;
++      }
++
++      vchiq_add_connected_callback(vc_sm_connected_init);
++      return 0;
++}
++
++/* Driver unloading. */
++static int bcm2835_vc_sm_cma_remove(struct platform_device *pdev)
++{
++      pr_debug("[%s]: start\n", __func__);
++      if (sm_inited) {
++              /* Remove shared memory device. */
++              misc_deregister(&sm_state->dev);
++
++              /* Remove all proc entries. */
++              //debugfs_remove_recursive(sm_state->dir_root);
++
++              /* Stop the videocore shared memory service. */
++              vc_sm_cma_vchi_stop(&sm_state->sm_handle);
++
++              /* Free the memory for the state structure. */
++              mutex_destroy(&sm_state->map_lock);
++              kfree(sm_state);
++      }
++
++      pr_debug("[%s]: end\n", __func__);
++      return 0;
++}
++
++/* Get an internal resource handle mapped from the external one. */
++int vc_sm_cma_int_handle(int handle)
++{
++      struct dma_buf *dma_buf = (struct dma_buf *)handle;
++      struct vc_sm_buffer *res;
++
++      /* Validate we can work with this device. */
++      if (!sm_state || !handle) {
++              pr_err("[%s]: invalid input\n", __func__);
++              return 0;
++      }
++
++      res = (struct vc_sm_buffer *)dma_buf->priv;
++      return res->vc_handle;
++}
++EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
++
++/* Free a previously allocated shared memory handle and block. */
++int vc_sm_cma_free(int handle)
++{
++      struct dma_buf *dma_buf = (struct dma_buf *)handle;
++
++      /* Validate we can work with this device. */
++      if (!sm_state || !handle) {
++              pr_err("[%s]: invalid input\n", __func__);
++              return -EPERM;
++      }
++
++      pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
++
++      dma_buf_put(dma_buf);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(vc_sm_cma_free);
++
++/* Import a dmabuf to be shared with VC. */
++int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
++{
++      struct dma_buf *new_dma_buf;
++      struct vc_sm_buffer *res;
++      int ret;
++
++      /* Validate we can work with this device. */
++      if (!sm_state || !src_dmabuf || !handle) {
++              pr_err("[%s]: invalid input\n", __func__);
++              return -EPERM;
++      }
++
++      ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
++                                             &new_dma_buf);
++
++      if (!ret) {
++              pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
++              res = (struct vc_sm_buffer *)new_dma_buf->priv;
++
++              /* Assign valid handle at this time.*/
++              *handle = (int)new_dma_buf;
++      } else {
++              /*
++               * succeeded in importing the dma_buf, but then
++               * failed to look it up again. How?
++               * Release the fd again.
++               */
++              pr_err("%s: imported vc_sm_cma_get_buffer failed %d\n",
++                     __func__, ret);
++      }
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vc_sm_cma_import_dmabuf);
++
++static struct platform_driver bcm2835_vcsm_cma_driver = {
++      .probe = bcm2835_vc_sm_cma_probe,
++      .remove = bcm2835_vc_sm_cma_remove,
++      .driver = {
++                 .name = DEVICE_NAME,
++                 .owner = THIS_MODULE,
++                 },
++};
++
++module_platform_driver(bcm2835_vcsm_cma_driver);
++
++MODULE_AUTHOR("Dave Stevenson");
++MODULE_DESCRIPTION("VideoCore CMA Shared Memory Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:vcsm-cma");
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+@@ -0,0 +1,59 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory driver using CMA.
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ */
++
++#ifndef VC_SM_H
++#define VC_SM_H
++
++#include <linux/device.h>
++#include <linux/dma-direction.h>
++#include <linux/kref.h>
++#include <linux/mm_types.h>
++#include <linux/mutex.h>
++#include <linux/rbtree.h>
++#include <linux/sched.h>
++#include <linux/shrinker.h>
++#include <linux/types.h>
++#include <linux/miscdevice.h>
++
++#define VC_SM_MAX_NAME_LEN 32
++
++enum vc_sm_vpu_mapping_state {
++      VPU_NOT_MAPPED,
++      VPU_MAPPED,
++      VPU_UNMAPPING
++};
++
++struct vc_sm_buffer {
++      struct list_head global_buffer_list;    /* Global list of buffers. */
++
++      size_t size;
++
++      /* Lock over all the following state for this buffer */
++      struct mutex lock;
++      struct sg_table *sg_table;
++      struct list_head attachments;
++
++      char name[VC_SM_MAX_NAME_LEN];
++
++      int in_use:1;   /* Kernel is still using this resource */
++
++      enum vc_sm_vpu_mapping_state vpu_state;
++      u32 vc_handle;  /* VideoCore handle for this buffer */
++
++      /* DMABUF related fields */
++      struct dma_buf *import_dma_buf;
++      struct dma_buf *dma_buf;
++      struct dma_buf_attachment *attach;
++      struct sg_table *sgt;
++      dma_addr_t dma_addr;
++
++      struct vc_sm_privdata_t *private;
++};
++
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -0,0 +1,498 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ * Copyright 2011-2012 Broadcom Corporation.  All rights reserved.
++ *
++ * Based on vmcs_sm driver from Broadcom Corporation.
++ *
++ */
++
++/* ---- Include Files ----------------------------------------------------- */
++#include <linux/completion.h>
++#include <linux/kernel.h>
++#include <linux/kthread.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/semaphore.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++
++#include "vc_sm_cma_vchi.h"
++
++#define VC_SM_VER  1
++#define VC_SM_MIN_VER 0
++
++/* ---- Private Constants and Types -------------------------------------- */
++
++/* Command blocks come from a pool */
++#define SM_MAX_NUM_CMD_RSP_BLKS 32
++
++struct sm_cmd_rsp_blk {
++      struct list_head head;  /* To create lists */
++      /* To be signaled when the response is there */
++      struct completion cmplt;
++
++      u16 id;
++      u16 length;
++
++      u8 msg[VC_SM_MAX_MSG_LEN];
++
++      uint32_t wait:1;
++      uint32_t sent:1;
++      uint32_t alloc:1;
++
++};
++
++struct sm_instance {
++      u32 num_connections;
++      VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
++      struct task_struct *io_thread;
++      struct completion io_cmplt;
++
++      vpu_event_cb vpu_event;
++
++      /* Mutex over the following lists */
++      struct mutex lock;
++      u32 trans_id;
++      struct list_head cmd_list;
++      struct list_head rsp_list;
++      struct list_head dead_list;
++
++      struct sm_cmd_rsp_blk free_blk[SM_MAX_NUM_CMD_RSP_BLKS];
++
++      /* Mutex over the free_list */
++      struct mutex free_lock;
++      struct list_head free_list;
++
++      struct semaphore free_sema;
++
++};
++
++/* ---- Private Variables ------------------------------------------------ */
++
++/* ---- Private Function Prototypes -------------------------------------- */
++
++/* ---- Private Functions ------------------------------------------------ */
++static int
++bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
++                     void *data,
++                     unsigned int size)
++{
++      return vchi_queue_kernel_message(handle,
++                                       data,
++                                       size);
++}
++
++static struct
++sm_cmd_rsp_blk *vc_vchi_cmd_create(struct sm_instance *instance,
++                                 enum vc_sm_msg_type id, void *msg,
++                                 u32 size, int wait)
++{
++      struct sm_cmd_rsp_blk *blk;
++      struct vc_sm_msg_hdr_t *hdr;
++
++      if (down_interruptible(&instance->free_sema)) {
++              blk = kmalloc(sizeof(*blk), GFP_KERNEL);
++              if (!blk)
++                      return NULL;
++
++              blk->alloc = 1;
++              init_completion(&blk->cmplt);
++      } else {
++              mutex_lock(&instance->free_lock);
++              blk =
++                  list_first_entry(&instance->free_list,
++                                   struct sm_cmd_rsp_blk, head);
++              list_del(&blk->head);
++              mutex_unlock(&instance->free_lock);
++      }
++
++      blk->sent = 0;
++      blk->wait = wait;
++      blk->length = sizeof(*hdr) + size;
++
++      hdr = (struct vc_sm_msg_hdr_t *)blk->msg;
++      hdr->type = id;
++      mutex_lock(&instance->lock);
++      instance->trans_id++;
++      /*
++       * Retain the top bit for identifying asynchronous events, or VPU cmds.
++       */
++      instance->trans_id &= ~0x80000000;
++      hdr->trans_id = instance->trans_id;
++      blk->id = instance->trans_id;
++      mutex_unlock(&instance->lock);
++
++      if (size)
++              memcpy(hdr->body, msg, size);
++
++      return blk;
++}
++
++static void
++vc_vchi_cmd_delete(struct sm_instance *instance, struct sm_cmd_rsp_blk *blk)
++{
++      if (blk->alloc) {
++              kfree(blk);
++              return;
++      }
++
++      mutex_lock(&instance->free_lock);
++      list_add(&blk->head, &instance->free_list);
++      mutex_unlock(&instance->free_lock);
++      up(&instance->free_sema);
++}
++
++static void vc_sm_cma_vchi_rx_ack(struct sm_instance *instance,
++                                struct sm_cmd_rsp_blk *cmd,
++                                struct vc_sm_result_t *reply,
++                                u32 reply_len)
++{
++      mutex_lock(&instance->lock);
++      list_for_each_entry(cmd,
++                          &instance->rsp_list,
++                          head) {
++              if (cmd->id == reply->trans_id)
++                      break;
++      }
++      mutex_unlock(&instance->lock);
++
++      if (&cmd->head == &instance->rsp_list) {
++              //pr_debug("%s: received response %u, throw away...",
++              pr_err("%s: received response %u, throw away...",
++                     __func__,
++                     reply->trans_id);
++      } else if (reply_len > sizeof(cmd->msg)) {
++              pr_err("%s: reply too big (%u) %u, throw away...",
++                     __func__, reply_len,
++                   reply->trans_id);
++      } else {
++              memcpy(cmd->msg, reply,
++                     reply_len);
++              complete(&cmd->cmplt);
++      }
++}
++
++static int vc_sm_cma_vchi_videocore_io(void *arg)
++{
++      struct sm_instance *instance = arg;
++      struct sm_cmd_rsp_blk *cmd = NULL, *cmd_tmp;
++      struct vc_sm_result_t *reply;
++      u32 reply_len;
++      s32 status;
++      int svc_use = 1;
++
++      while (1) {
++              if (svc_use)
++                      vchi_service_release(instance->vchi_handle[0]);
++              svc_use = 0;
++              if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
++                      vchi_service_use(instance->vchi_handle[0]);
++                      svc_use = 1;
++
++                      do {
++                              /*
++                               * Get new command and move it to response list
++                               */
++                              mutex_lock(&instance->lock);
++                              if (list_empty(&instance->cmd_list)) {
++                                      /* no more commands to process */
++                                      mutex_unlock(&instance->lock);
++                                      break;
++                              }
++                              cmd =
++                                  list_first_entry(&instance->cmd_list,
++                                                   struct sm_cmd_rsp_blk,
++                                                   head);
++                              list_move(&cmd->head, &instance->rsp_list);
++                              cmd->sent = 1;
++                              mutex_unlock(&instance->lock);
++
++                              /* Send the command */
++                              status = bcm2835_vchi_msg_queue(
++                                              instance->vchi_handle[0],
++                                              cmd->msg, cmd->length);
++                              if (status) {
++                                      pr_err("%s: failed to queue message (%d)",
++                                             __func__, status);
++                              }
++
++                              /* If no reply is needed then we're done */
++                              if (!cmd->wait) {
++                                      mutex_lock(&instance->lock);
++                                      list_del(&cmd->head);
++                                      mutex_unlock(&instance->lock);
++                                      vc_vchi_cmd_delete(instance, cmd);
++                                      continue;
++                              }
++
++                              if (status) {
++                                      complete(&cmd->cmplt);
++                                      continue;
++                              }
++
++                      } while (1);
++
++                      while (!vchi_msg_peek(instance->vchi_handle[0],
++                                            (void **)&reply, &reply_len,
++                                            VCHI_FLAGS_NONE)) {
++                              if (reply->trans_id & 0x80000000) {
++                                      /* Async event or cmd from the VPU */
++                                      if (instance->vpu_event)
++                                              instance->vpu_event(
++                                                      instance, reply,
++                                                      reply_len);
++                              } else {
++                                      vc_sm_cma_vchi_rx_ack(instance, cmd,
++                                                            reply, reply_len);
++                              }
++
++                              vchi_msg_remove(instance->vchi_handle[0]);
++                      }
++
++                      /* Go through the dead list and free them */
++                      mutex_lock(&instance->lock);
++                      list_for_each_entry_safe(cmd, cmd_tmp,
++                                               &instance->dead_list, head) {
++                              list_del(&cmd->head);
++                              vc_vchi_cmd_delete(instance, cmd);
++                      }
++                      mutex_unlock(&instance->lock);
++              }
++      }
++
++      return 0;
++}
++
++static void vc_sm_cma_vchi_callback(void *param,
++                                  const VCHI_CALLBACK_REASON_T reason,
++                                  void *msg_handle)
++{
++      struct sm_instance *instance = param;
++
++      (void)msg_handle;
++
++      switch (reason) {
++      case VCHI_CALLBACK_MSG_AVAILABLE:
++              complete(&instance->io_cmplt);
++              break;
++
++      case VCHI_CALLBACK_SERVICE_CLOSED:
++              pr_info("%s: service CLOSED!!", __func__);
++      default:
++              break;
++      }
++}
++
++struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
++                                      unsigned int num_connections,
++                                      vpu_event_cb vpu_event)
++{
++      u32 i;
++      struct sm_instance *instance;
++      int status;
++
++      pr_debug("%s: start", __func__);
++
++      if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
++              pr_err("%s: unsupported number of connections %u (max=%u)",
++                     __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
++
++              goto err_null;
++      }
++      /* Allocate memory for this instance */
++      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++
++      /* Misc initialisations */
++      mutex_init(&instance->lock);
++      init_completion(&instance->io_cmplt);
++      INIT_LIST_HEAD(&instance->cmd_list);
++      INIT_LIST_HEAD(&instance->rsp_list);
++      INIT_LIST_HEAD(&instance->dead_list);
++      INIT_LIST_HEAD(&instance->free_list);
++      sema_init(&instance->free_sema, SM_MAX_NUM_CMD_RSP_BLKS);
++      mutex_init(&instance->free_lock);
++      for (i = 0; i < SM_MAX_NUM_CMD_RSP_BLKS; i++) {
++              init_completion(&instance->free_blk[i].cmplt);
++              list_add(&instance->free_blk[i].head, &instance->free_list);
++      }
++
++      /* Open the VCHI service connections */
++      instance->num_connections = num_connections;
++      for (i = 0; i < num_connections; i++) {
++              SERVICE_CREATION_T params = {
++                      .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
++                      .service_id = VC_SM_SERVER_NAME,
++                      .callback = vc_sm_cma_vchi_callback,
++                      .callback_param = instance,
++              };
++
++              status = vchi_service_open(vchi_instance,
++                                         &params, &instance->vchi_handle[i]);
++              if (status) {
++                      pr_err("%s: failed to open VCHI service (%d)",
++                             __func__, status);
++
++                      goto err_close_services;
++              }
++      }
++
++      /* Create the thread which takes care of all io to/from videoocore. */
++      instance->io_thread = kthread_create(&vc_sm_cma_vchi_videocore_io,
++                                           (void *)instance, "SMIO");
++      if (!instance->io_thread) {
++              pr_err("%s: failed to create SMIO thread", __func__);
++
++              goto err_close_services;
++      }
++      instance->vpu_event = vpu_event;
++      set_user_nice(instance->io_thread, -10);
++      wake_up_process(instance->io_thread);
++
++      pr_debug("%s: success - instance 0x%x", __func__,
++               (unsigned int)instance);
++      return instance;
++
++err_close_services:
++      for (i = 0; i < instance->num_connections; i++) {
++              if (instance->vchi_handle[i])
++                      vchi_service_close(instance->vchi_handle[i]);
++      }
++      kfree(instance);
++err_null:
++      pr_debug("%s: FAILED", __func__);
++      return NULL;
++}
++
++int vc_sm_cma_vchi_stop(struct sm_instance **handle)
++{
++      struct sm_instance *instance;
++      u32 i;
++
++      if (!handle) {
++              pr_err("%s: invalid pointer to handle %p", __func__, handle);
++              goto lock;
++      }
++
++      if (!*handle) {
++              pr_err("%s: invalid handle %p", __func__, *handle);
++              goto lock;
++      }
++
++      instance = *handle;
++
++      /* Close all VCHI service connections */
++      for (i = 0; i < instance->num_connections; i++) {
++              s32 success;
++
++              vchi_service_use(instance->vchi_handle[i]);
++
++              success = vchi_service_close(instance->vchi_handle[i]);
++      }
++
++      kfree(instance);
++
++      *handle = NULL;
++      return 0;
++
++lock:
++      return -EINVAL;
++}
++
++static int vc_sm_cma_vchi_send_msg(struct sm_instance *handle,
++                                 enum vc_sm_msg_type msg_id, void *msg,
++                                 u32 msg_size, void *result, u32 result_size,
++                                 u32 *cur_trans_id, u8 wait_reply)
++{
++      int status = 0;
++      struct sm_instance *instance = handle;
++      struct sm_cmd_rsp_blk *cmd_blk;
++
++      if (!handle) {
++              pr_err("%s: invalid handle", __func__);
++              return -EINVAL;
++      }
++      if (!msg) {
++              pr_err("%s: invalid msg pointer", __func__);
++              return -EINVAL;
++      }
++
++      cmd_blk =
++          vc_vchi_cmd_create(instance, msg_id, msg, msg_size, wait_reply);
++      if (!cmd_blk) {
++              pr_err("[%s]: failed to allocate global tracking resource",
++                     __func__);
++              return -ENOMEM;
++      }
++
++      if (cur_trans_id)
++              *cur_trans_id = cmd_blk->id;
++
++      mutex_lock(&instance->lock);
++      list_add_tail(&cmd_blk->head, &instance->cmd_list);
++      mutex_unlock(&instance->lock);
++      complete(&instance->io_cmplt);
++
++      if (!wait_reply)
++              /* We're done */
++              return 0;
++
++      /* Wait for the response */
++      if (wait_for_completion_interruptible(&cmd_blk->cmplt)) {
++              mutex_lock(&instance->lock);
++              if (!cmd_blk->sent) {
++                      list_del(&cmd_blk->head);
++                      mutex_unlock(&instance->lock);
++                      vc_vchi_cmd_delete(instance, cmd_blk);
++                      return -ENXIO;
++              }
++
++              list_move(&cmd_blk->head, &instance->dead_list);
++              mutex_unlock(&instance->lock);
++              complete(&instance->io_cmplt);
++              return -EINTR;  /* We're done */
++      }
++
++      if (result && result_size) {
++              memcpy(result, cmd_blk->msg, result_size);
++      } else {
++              struct vc_sm_result_t *res =
++                      (struct vc_sm_result_t *)cmd_blk->msg;
++              status = (res->success == 0) ? 0 : -ENXIO;
++      }
++
++      mutex_lock(&instance->lock);
++      list_del(&cmd_blk->head);
++      mutex_unlock(&instance->lock);
++      vc_vchi_cmd_delete(instance, cmd_blk);
++      return status;
++}
++
++int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
++                      u32 *cur_trans_id)
++{
++      return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_FREE,
++                                 msg, sizeof(*msg), 0, 0, cur_trans_id, 0);
++}
++
++int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
++                        struct vc_sm_import_result *result, u32 *cur_trans_id)
++{
++      return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_IMPORT,
++                                 msg, sizeof(*msg), result, sizeof(*result),
++                                 cur_trans_id, 1);
++}
++
++int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
++                                struct vc_sm_version *msg,
++                                struct vc_sm_result_t *result,
++                                u32 *cur_trans_id)
++{
++      return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_CLIENT_VERSION,
++                                 //msg, sizeof(*msg), result, sizeof(*result),
++                                 //cur_trans_id, 1);
++                                 msg, sizeof(*msg), NULL, 0,
++                                 cur_trans_id, 0);
++}
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
+@@ -0,0 +1,59 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ * Copyright 2011-2012 Broadcom Corporation.  All rights reserved.
++ *
++ * Based on vmcs_sm driver from Broadcom Corporation.
++ *
++ */
++
++#ifndef __VC_SM_CMA_VCHI_H__INCLUDED__
++#define __VC_SM_CMA_VCHI_H__INCLUDED__
++
++#include "interface/vchi/vchi.h"
++
++#include "vc_sm_defs.h"
++
++/*
++ * Forward declare.
++ */
++struct sm_instance;
++
++typedef void (*vpu_event_cb)(struct sm_instance *instance,
++                           struct vc_sm_result_t *reply, int reply_len);
++
++/*
++ * Initialize the shared memory service, opens up vchi connection to talk to it.
++ */
++struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
++                                      unsigned int num_connections,
++                                      vpu_event_cb vpu_event);
++
++/*
++ * Terminates the shared memory service.
++ */
++int vc_sm_cma_vchi_stop(struct sm_instance **handle);
++
++/*
++ * Ask the shared memory service to free up some memory that was previously
++ * allocated by the vc_sm_cma_vchi_alloc function call.
++ */
++int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
++                      u32 *cur_trans_id);
++
++/*
++ * Import a contiguous block of memory and wrap it in a GPU MEM_HANDLE_T.
++ */
++int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
++                        struct vc_sm_import_result *result,
++                        u32 *cur_trans_id);
++
++int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
++                                struct vc_sm_version *msg,
++                                struct vc_sm_result_t *result,
++                                u32 *cur_trans_id);
++
++#endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
+@@ -0,0 +1,298 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
++ * All IPC messages are copied across to this file, even if the vc-sm-cma
++ * driver is not currently using them.
++ *
++ ****************************************************************************
++ */
++
++#ifndef __VC_SM_DEFS_H__INCLUDED__
++#define __VC_SM_DEFS_H__INCLUDED__
++
++/* FourCC code used for VCHI connection */
++#define VC_SM_SERVER_NAME MAKE_FOURCC("SMEM")
++
++/* Maximum message length */
++#define VC_SM_MAX_MSG_LEN (sizeof(union vc_sm_msg_union_t) + \
++      sizeof(struct vc_sm_msg_hdr_t))
++#define VC_SM_MAX_RSP_LEN (sizeof(union vc_sm_msg_union_t))
++
++/* Resource name maximum size */
++#define VC_SM_RESOURCE_NAME 32
++
++/*
++ * Version to be reported to the VPU
++ * VPU assumes 0 (aka 1) which does not require the released callback, nor
++ * expect the client to handle VC_MEM_REQUESTS.
++ * Version 2 requires the released callback, and must support VC_MEM_REQUESTS.
++ */
++#define VC_SM_PROTOCOL_VERSION        2
++
++enum vc_sm_msg_type {
++      /* Message types supported for HOST->VC direction */
++
++      /* Allocate shared memory block */
++      VC_SM_MSG_TYPE_ALLOC,
++      /* Lock allocated shared memory block */
++      VC_SM_MSG_TYPE_LOCK,
++      /* Unlock allocated shared memory block */
++      VC_SM_MSG_TYPE_UNLOCK,
++      /* Unlock allocated shared memory block, do not answer command */
++      VC_SM_MSG_TYPE_UNLOCK_NOANS,
++      /* Free shared memory block */
++      VC_SM_MSG_TYPE_FREE,
++      /* Resize a shared memory block */
++      VC_SM_MSG_TYPE_RESIZE,
++      /* Walk the allocated shared memory block(s) */
++      VC_SM_MSG_TYPE_WALK_ALLOC,
++
++      /* A previously applied action will need to be reverted */
++      VC_SM_MSG_TYPE_ACTION_CLEAN,
++
++      /*
++       * Import a physical address and wrap into a MEM_HANDLE_T.
++       * Release with VC_SM_MSG_TYPE_FREE.
++       */
++      VC_SM_MSG_TYPE_IMPORT,
++      /*
++       *Tells VC the protocol version supported by this client.
++       * 2 supports the async/cmd messages from the VPU for final release
++       * of memory, and for VC allocations.
++       */
++      VC_SM_MSG_TYPE_CLIENT_VERSION,
++      /* Response to VC request for memory */
++      VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
++
++      /*
++       * Asynchronous/cmd messages supported for VC->HOST direction.
++       * Signalled by setting the top bit in vc_sm_result_t trans_id.
++       */
++
++      /*
++       * VC has finished with an imported memory allocation.
++       * Release any Linux reference counts on the underlying block.
++       */
++      VC_SM_MSG_TYPE_RELEASED,
++      /* VC request for memory */
++      VC_SM_MSG_TYPE_VC_MEM_REQUEST,
++
++      VC_SM_MSG_TYPE_MAX
++};
++
++/* Type of memory to be allocated */
++enum vc_sm_alloc_type_t {
++      VC_SM_ALLOC_CACHED,
++      VC_SM_ALLOC_NON_CACHED,
++};
++
++/* Message header for all messages in HOST->VC direction */
++struct vc_sm_msg_hdr_t {
++      u32 type;
++      u32 trans_id;
++      u8 body[0];
++
++};
++
++/* Request to allocate memory (HOST->VC) */
++struct vc_sm_alloc_t {
++      /* type of memory to allocate */
++      enum vc_sm_alloc_type_t type;
++      /* byte amount of data to allocate per unit */
++      u32 base_unit;
++      /* number of unit to allocate */
++      u32 num_unit;
++      /* alignment to be applied on allocation */
++      u32 alignment;
++      /* identity of who allocated this block */
++      u32 allocator;
++      /* resource name (for easier tracking on vc side) */
++      char name[VC_SM_RESOURCE_NAME];
++
++};
++
++/* Result of a requested memory allocation (VC->HOST) */
++struct vc_sm_alloc_result_t {
++      /* Transaction identifier */
++      u32 trans_id;
++
++      /* Resource handle */
++      u32 res_handle;
++      /* Pointer to resource buffer */
++      u32 res_mem;
++      /* Resource base size (bytes) */
++      u32 res_base_size;
++      /* Resource number */
++      u32 res_num;
++
++};
++
++/* Request to free a previously allocated memory (HOST->VC) */
++struct vc_sm_free_t {
++      /* Resource handle (returned from alloc) */
++      u32 res_handle;
++      /* Resource buffer (returned from alloc) */
++      u32 res_mem;
++
++};
++
++/* Request to lock a previously allocated memory (HOST->VC) */
++struct vc_sm_lock_unlock_t {
++      /* Resource handle (returned from alloc) */
++      u32 res_handle;
++      /* Resource buffer (returned from alloc) */
++      u32 res_mem;
++
++};
++
++/* Request to resize a previously allocated memory (HOST->VC) */
++struct vc_sm_resize_t {
++      /* Resource handle (returned from alloc) */
++      u32 res_handle;
++      /* Resource buffer (returned from alloc) */
++      u32 res_mem;
++      /* Resource *new* size requested (bytes) */
++      u32 res_new_size;
++
++};
++
++/* Result of a requested memory lock (VC->HOST) */
++struct vc_sm_lock_result_t {
++      /* Transaction identifier */
++      u32 trans_id;
++
++      /* Resource handle */
++      u32 res_handle;
++      /* Pointer to resource buffer */
++      u32 res_mem;
++      /*
++       * Pointer to former resource buffer if the memory
++       * was reallocated
++       */
++      u32 res_old_mem;
++
++};
++
++/* Generic result for a request (VC->HOST) */
++struct vc_sm_result_t {
++      /* Transaction identifier */
++      u32 trans_id;
++
++      s32 success;
++
++};
++
++/* Request to revert a previously applied action (HOST->VC) */
++struct vc_sm_action_clean_t {
++      /* Action of interest */
++      enum vc_sm_msg_type res_action;
++      /* Transaction identifier for the action of interest */
++      u32 action_trans_id;
++
++};
++
++/* Request to remove all data associated with a given allocator (HOST->VC) */
++struct vc_sm_free_all_t {
++      /* Allocator identifier */
++      u32 allocator;
++};
++
++/* Request to import memory (HOST->VC) */
++struct vc_sm_import {
++      /* type of memory to allocate */
++      enum vc_sm_alloc_type_t type;
++      /* pointer to the VC (ie physical) address of the allocated memory */
++      u32 addr;
++      /* size of buffer */
++      u32 size;
++      /* opaque handle returned in RELEASED messages */
++      u32 kernel_id;
++      /* Allocator identifier */
++      u32 allocator;
++      /* resource name (for easier tracking on vc side) */
++      char     name[VC_SM_RESOURCE_NAME];
++};
++
++/* Result of a requested memory import (VC->HOST) */
++struct vc_sm_import_result {
++      /* Transaction identifier */
++      u32 trans_id;
++
++      /* Resource handle */
++      u32 res_handle;
++};
++
++/* Notification that VC has finished with an allocation (VC->HOST) */
++struct vc_sm_released {
++      /* cmd type / trans_id */
++      u32 cmd;
++
++      /* pointer to the VC (ie physical) address of the allocated memory */
++      u32 addr;
++      /* size of buffer */
++      u32 size;
++      /* opaque handle returned in RELEASED messages */
++      u32 kernel_id;
++      u32 vc_handle;
++};
++
++/*
++ * Client informing VC as to the protocol version it supports.
++ * >=2 requires the released callback, and supports VC asking for memory.
++ * Failure means that the firmware doesn't support this call, and therefore the
++ * client should either fail, or NOT rely on getting the released callback.
++ */
++struct vc_sm_version {
++      u32 version;
++};
++
++/* Request FROM VideoCore for some memory */
++struct vc_sm_vc_mem_request {
++      /* cmd type */
++      u32 cmd;
++
++      /* trans_id (from VPU) */
++      u32 trans_id;
++      /* size of buffer */
++      u32 size;
++      /* alignment of buffer */
++      u32 align;
++      /* resource name (for easier tracking) */
++      char     name[VC_SM_RESOURCE_NAME];
++};
++
++/* Response from the kernel to provide the VPU with some memory */
++struct vc_sm_vc_mem_request_result {
++      /* Transaction identifier for the VPU */
++      u32 trans_id;
++      /* pointer to the physical address of the allocated memory */
++      u32 addr;
++      /* opaque handle returned in RELEASED messages */
++      u32 kernel_id;
++};
++
++/* Union of ALL messages */
++union vc_sm_msg_union_t {
++      struct vc_sm_alloc_t alloc;
++      struct vc_sm_alloc_result_t alloc_result;
++      struct vc_sm_free_t free;
++      struct vc_sm_lock_unlock_t lock_unlock;
++      struct vc_sm_action_clean_t action_clean;
++      struct vc_sm_resize_t resize;
++      struct vc_sm_lock_result_t lock_result;
++      struct vc_sm_result_t result;
++      struct vc_sm_free_all_t free_all;
++      struct vc_sm_import import;
++      struct vc_sm_import_result import_result;
++      struct vc_sm_version version;
++      struct vc_sm_released released;
++      struct vc_sm_vc_mem_request vc_request;
++      struct vc_sm_vc_mem_request_result vc_request_result;
++};
++
++#endif /* __VC_SM_DEFS_H__INCLUDED__ */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
++ *
++ */
++
++#ifndef __VC_SM_KNL_H__INCLUDED__
++#define __VC_SM_KNL_H__INCLUDED__
++
++#if !defined(__KERNEL__)
++#error "This interface is for kernel use only..."
++#endif
++
++/* Free a previously allocated or imported shared memory handle and block. */
++int vc_sm_cma_free(int handle);
++
++/* Get an internal resource handle mapped from the external one. */
++int vc_sm_cma_int_handle(int handle);
++
++/* Import a block of memory into the GPU space. */
++int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
++
++#endif /* __VC_SM_KNL_H__INCLUDED__ */
diff --git a/target/linux/brcm2708/patches-4.19/950-0240-staging-vc04_services-Support-sending-data-to-MMAL-p.patch b/target/linux/brcm2708/patches-4.19/950-0240-staging-vc04_services-Support-sending-data-to-MMAL-p.patch
deleted file mode 100644 (file)
index 9688bc8..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 483bef9dcddc4bcb9f4e250d91b31361a919b7ed Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 18:26:02 +0100
-Subject: [PATCH] staging: vc04_services: Support sending data to MMAL
- ports
-
-Add the ability to send data to ports. This only supports
-zero copy mode as the required bulk transfer setup calls
-are not done.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-vchiq.c      | 18 +++++++++++++-----
- 1 file changed, 13 insertions(+), 5 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -428,11 +428,19 @@ buffer_from_host(struct vchiq_mmal_insta
-       m.u.buffer_from_host.buffer_header.data =
-               (u32)(unsigned long)buf->buffer;
-       m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
--      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
--      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
--      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
--      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
--      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
-+      if (port->type == MMAL_PORT_TYPE_OUTPUT) {
-+              m.u.buffer_from_host.buffer_header.length = 0;
-+              m.u.buffer_from_host.buffer_header.offset = 0;
-+              m.u.buffer_from_host.buffer_header.flags = 0;
-+              m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
-+              m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
-+      } else {
-+              m.u.buffer_from_host.buffer_header.length = buf->length;
-+              m.u.buffer_from_host.buffer_header.offset = 0;
-+              m.u.buffer_from_host.buffer_header.flags = buf->mmal_flags;
-+              m.u.buffer_from_host.buffer_header.pts = buf->pts;
-+              m.u.buffer_from_host.buffer_header.dts = buf->dts;
-+      }
-       /* clear buffer type sepecific data */
-       memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
diff --git a/target/linux/brcm2708/patches-4.19/950-0241-staging-vc-sm-cma-Fixup-driver-for-older-VCHI-APIs.patch b/target/linux/brcm2708/patches-4.19/950-0241-staging-vc-sm-cma-Fixup-driver-for-older-VCHI-APIs.patch
new file mode 100644 (file)
index 0000000..4f16e0b
--- /dev/null
@@ -0,0 +1,42 @@
+From 9eb40722f3ef0d338ed97667a7391f3d74812332 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 30 Oct 2018 11:42:48 +0000
+Subject: [PATCH] staging: vc-sm-cma: Fixup driver for older VCHI APIs
+
+Original patch was based off staging which included some cleanups
+of the VCHI APIs. Those aren't present here, so switch back to
+the older API.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c          | 2 +-
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -632,7 +632,7 @@ static void vc_sm_connected_init(void)
+               goto err_free_mem;
+       }
+-      ret = vchi_connect(vchi_instance);
++      ret = vchi_connect(NULL, 0, vchi_instance);
+       if (ret) {
+               pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
+                      __func__, ret);
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -325,8 +325,13 @@ struct sm_instance *vc_sm_cma_vchi_init(
+               SERVICE_CREATION_T params = {
+                       .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
+                       .service_id = VC_SM_SERVER_NAME,
++                      .rx_fifo_size = 0,
++                      .tx_fifo_size = 0,
+                       .callback = vc_sm_cma_vchi_callback,
+                       .callback_param = instance,
++                      .want_unaligned_bulk_rx = 0,
++                      .want_unaligned_bulk_tx = 0,
++                      .want_crc = 0
+               };
+               status = vchi_service_open(vchi_instance,
diff --git a/target/linux/brcm2708/patches-4.19/950-0241-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch b/target/linux/brcm2708/patches-4.19/950-0241-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch
deleted file mode 100644 (file)
index 6c54743..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From 2a5a03926a8c6ae7375355de00814234e4e303ed Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 16:57:40 +0100
-Subject: [PATCH] staging: vc04_services: Fixup vchiq-mmal include
- ordering
-
-There were dependencies on including the headers in the correct
-order. Fix up the headers so that they include the other
-headers that they depend on themselves.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h   | 1 +
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-@@ -38,6 +38,7 @@
- #include "mmal-msg-common.h"
- #include "mmal-msg-format.h"
- #include "mmal-msg-port.h"
-+#include "mmal-vchiq.h"
- enum mmal_msg_type {
-       MMAL_MSG_TYPE_QUIT = 1,
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -16,6 +16,7 @@
- #ifndef MMAL_VCHIQ_H
- #define MMAL_VCHIQ_H
-+#include "mmal-common.h"
- #include "mmal-msg-format.h"
- #define MAX_PORT_COUNT 4
diff --git a/target/linux/brcm2708/patches-4.19/950-0242-staging-vc04_services-Add-new-vc-sm-cma-driver.patch b/target/linux/brcm2708/patches-4.19/950-0242-staging-vc04_services-Add-new-vc-sm-cma-driver.patch
deleted file mode 100644 (file)
index 9e9af47..0000000
+++ /dev/null
@@ -1,1881 +0,0 @@
-From 2994fdc0a9d48be68d6e403bc8ddadecfc8d8796 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 10:27:11 +0100
-Subject: [PATCH] staging: vc04_services: Add new vc-sm-cma driver
-
-This new driver allows contiguous memory blocks to be imported
-into the VideoCore VPU memory map, and manages the lifetime of
-those objects, only releasing the source dmabuf once the VPU has
-confirmed it has finished with it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/Kconfig         |   1 +
- drivers/staging/vc04_services/Makefile        |   1 +
- .../staging/vc04_services/vc-sm-cma/Kconfig   |  10 +
- .../staging/vc04_services/vc-sm-cma/Makefile  |   8 +
- drivers/staging/vc04_services/vc-sm-cma/TODO  |   2 +
- .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 838 ++++++++++++++++++
- .../staging/vc04_services/vc-sm-cma/vc_sm.h   |  59 ++
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  | 498 +++++++++++
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h  |  59 ++
- .../vc04_services/vc-sm-cma/vc_sm_defs.h      | 298 +++++++
- .../vc04_services/vc-sm-cma/vc_sm_knl.h       |  28 +
- 11 files changed, 1802 insertions(+)
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Kconfig
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Makefile
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/TODO
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-
---- a/drivers/staging/vc04_services/Kconfig
-+++ b/drivers/staging/vc04_services/Kconfig
-@@ -22,6 +22,7 @@ source "drivers/staging/vc04_services/bc
- source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
- source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
-+source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
- endif
---- a/drivers/staging/vc04_services/Makefile
-+++ b/drivers/staging/vc04_services/Makefile
-@@ -13,6 +13,7 @@ vchiq-objs := \
- obj-$(CONFIG_SND_BCM2835)     += bcm2835-audio/
- obj-$(CONFIG_VIDEO_BCM2835)   += bcm2835-camera/
- obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
-+obj-$(CONFIG_BCM_VC_SM_CMA)   += vc-sm-cma/
- ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-@@ -0,0 +1,10 @@
-+config BCM_VC_SM_CMA
-+      tristate "VideoCore Shared Memory (CMA) driver"
-+      depends on BCM2835_VCHIQ
-+      select RBTREE
-+      select DMA_SHARED_BUFFER
-+      help
-+        Say Y here to enable the shared memory interface that
-+        supports sharing dmabufs with VideoCore.
-+        This operates over the VCHIQ interface to a service
-+        running on VideoCore.
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
-@@ -0,0 +1,8 @@
-+ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vchi -Idrivers/staging/vc04_services/interface/vchiq_arm
-+# -I"drivers/staging/android/ion/" -I"$(srctree)/fs/"
-+ccflags-y += -D__VCCOREVER__=0
-+
-+vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
-+      vc_sm.o vc_sm_cma_vchi.o
-+
-+obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
-@@ -0,0 +1,2 @@
-+1) Convert to a platform driver.
-+
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -0,0 +1,838 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * VideoCore Shared Memory driver using CMA.
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ * Dave Stevenson <dave.stevenson@raspberrypi.org>
-+ *
-+ * Based on vmcs_sm driver from Broadcom Corporation for some API,
-+ * and taking some code for CMA/dmabuf handling from the Android Ion
-+ * driver (Google/Linaro).
-+ *
-+ * This is cut down version to only support import of dma_bufs from
-+ * other kernel drivers. A more complete implementation of the old
-+ * vmcs_sm functionality can follow later.
-+ *
-+ */
-+
-+/* ---- Include Files ----------------------------------------------------- */
-+#include <linux/cdev.h>
-+#include <linux/device.h>
-+#include <linux/debugfs.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/dma-buf.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/proc_fs.h>
-+#include <linux/slab.h>
-+#include <linux/seq_file.h>
-+#include <linux/syscalls.h>
-+#include <linux/types.h>
-+
-+#include "vchiq_connected.h"
-+#include "vc_sm_cma_vchi.h"
-+
-+#include "vc_sm.h"
-+#include "vc_sm_knl.h"
-+
-+/* ---- Private Constants and Types --------------------------------------- */
-+
-+#define DEVICE_NAME           "vcsm-cma"
-+#define DEVICE_MINOR          0
-+
-+#define VC_SM_RESOURCE_NAME_DEFAULT       "sm-host-resource"
-+
-+#define VC_SM_DIR_ROOT_NAME   "vcsm-cma"
-+#define VC_SM_STATE           "state"
-+
-+/* Private file data associated with each opened device. */
-+struct vc_sm_privdata_t {
-+      pid_t pid;                      /* PID of creator. */
-+
-+      int restart_sys;                /* Tracks restart on interrupt. */
-+      enum vc_sm_msg_type int_action; /* Interrupted action. */
-+      u32 int_trans_id;               /* Interrupted transaction. */
-+};
-+
-+typedef int (*VC_SM_SHOW) (struct seq_file *s, void *v);
-+struct sm_pde_t {
-+      VC_SM_SHOW show;          /* Debug fs function hookup. */
-+      struct dentry *dir_entry; /* Debug fs directory entry. */
-+      void *priv_data;          /* Private data */
-+};
-+
-+/* Global state information. */
-+struct sm_state_t {
-+      struct platform_device *pdev;
-+
-+      struct miscdevice dev;
-+      struct sm_instance *sm_handle;  /* Handle for videocore service. */
-+
-+      struct mutex map_lock;          /* Global map lock. */
-+      struct list_head buffer_list;   /* List of buffer. */
-+
-+      struct vc_sm_privdata_t *data_knl;  /* Kernel internal data tracking. */
-+      struct dentry *dir_root;        /* Debug fs entries root. */
-+      struct sm_pde_t dir_state;      /* Debug fs entries state sub-tree. */
-+
-+      bool require_released_callback; /* VPU will send a released msg when it
-+                                       * has finished with a resource.
-+                                       */
-+      u32 int_trans_id;               /* Interrupted transaction. */
-+};
-+
-+/* ---- Private Variables ----------------------------------------------- */
-+
-+static struct sm_state_t *sm_state;
-+static int sm_inited;
-+
-+/* ---- Private Function Prototypes -------------------------------------- */
-+
-+/* ---- Private Functions ------------------------------------------------ */
-+
-+static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
-+{
-+      struct sm_pde_t *sm_pde;
-+
-+      sm_pde = (struct sm_pde_t *)(s->private);
-+
-+      if (sm_pde && sm_pde->show)
-+              sm_pde->show(s, v);
-+
-+      return 0;
-+}
-+
-+static int vc_sm_cma_single_open(struct inode *inode, struct file *file)
-+{
-+      return single_open(file, vc_sm_cma_seq_file_show, inode->i_private);
-+}
-+
-+static const struct file_operations vc_sm_cma_debug_fs_fops = {
-+      .open = vc_sm_cma_single_open,
-+      .read = seq_read,
-+      .llseek = seq_lseek,
-+      .release = single_release,
-+};
-+
-+static int vc_sm_cma_global_state_show(struct seq_file *s, void *v)
-+{
-+      struct vc_sm_buffer *resource = NULL;
-+      int resource_count = 0;
-+
-+      if (!sm_state)
-+              return 0;
-+
-+      seq_printf(s, "\nVC-ServiceHandle     0x%x\n",
-+                 (unsigned int)sm_state->sm_handle);
-+
-+      /* Log all applicable mapping(s). */
-+
-+      mutex_lock(&sm_state->map_lock);
-+      seq_puts(s, "\nResources\n");
-+      if (!list_empty(&sm_state->buffer_list)) {
-+              list_for_each_entry(resource, &sm_state->buffer_list,
-+                                  global_buffer_list) {
-+                      resource_count++;
-+
-+                      seq_printf(s, "\nResource                %p\n",
-+                                 resource);
-+                      seq_printf(s, "           NAME         %s\n",
-+                                 resource->name);
-+                      seq_printf(s, "           SIZE         %d\n",
-+                                 resource->size);
-+                      seq_printf(s, "           DMABUF       %p\n",
-+                                 resource->dma_buf);
-+                      seq_printf(s, "           ATTACH       %p\n",
-+                                 resource->attach);
-+                      seq_printf(s, "           SG_TABLE     %p\n",
-+                                 resource->sg_table);
-+                      seq_printf(s, "           SGT          %p\n",
-+                                 resource->sgt);
-+                      seq_printf(s, "           DMA_ADDR     %pad\n",
-+                                 &resource->dma_addr);
-+                      seq_printf(s, "           VC_HANDLE     %08x\n",
-+                                 resource->vc_handle);
-+                      seq_printf(s, "           VC_MAPPING    %d\n",
-+                                 resource->vpu_state);
-+              }
-+      }
-+      seq_printf(s, "\n\nTotal resource count:   %d\n\n", resource_count);
-+
-+      mutex_unlock(&sm_state->map_lock);
-+
-+      return 0;
-+}
-+
-+/*
-+ * Adds a buffer to the private data list which tracks all the allocated
-+ * data.
-+ */
-+static void vc_sm_add_resource(struct vc_sm_privdata_t *privdata,
-+                             struct vc_sm_buffer *buffer)
-+{
-+      mutex_lock(&sm_state->map_lock);
-+      list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
-+      mutex_unlock(&sm_state->map_lock);
-+
-+      pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
-+               __func__, buffer, buffer->name, buffer->size);
-+}
-+
-+/*
-+ * Release an allocation.
-+ * All refcounting is done via the dma buf object.
-+ */
-+static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
-+{
-+      mutex_lock(&sm_state->map_lock);
-+      mutex_lock(&buffer->lock);
-+
-+      pr_debug("[%s]: buffer %p (name %s, size %d)\n",
-+               __func__, buffer, buffer->name, buffer->size);
-+
-+      if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
-+              struct vc_sm_free_t free = { buffer->vc_handle, 0 };
-+              int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
-+                                           &sm_state->int_trans_id);
-+              if (status != 0 && status != -EINTR) {
-+                      pr_err("[%s]: failed to free memory on videocore (status: %u, trans_id: %u)\n",
-+                             __func__, status, sm_state->int_trans_id);
-+              }
-+
-+              if (sm_state->require_released_callback) {
-+                      /* Need to wait for the VPU to confirm the free */
-+
-+                      /* Retain a reference on this until the VPU has
-+                       * released it
-+                       */
-+                      buffer->vpu_state = VPU_UNMAPPING;
-+                      goto defer;
-+              }
-+              buffer->vpu_state = VPU_NOT_MAPPED;
-+              buffer->vc_handle = 0;
-+      }
-+      if (buffer->vc_handle) {
-+              /* We've sent the unmap request but not had the response. */
-+              pr_err("[%s]: Waiting for VPU unmap response on %p\n",
-+                     __func__, buffer);
-+              goto defer;
-+      }
-+      if (buffer->in_use) {
-+              /* Don't release dmabuf here - we await the release */
-+              pr_err("[%s]: buffer %p is still in use\n",
-+                     __func__, buffer);
-+              goto defer;
-+      }
-+
-+      /* Handle cleaning up imported dmabufs */
-+      if (buffer->sgt) {
-+              dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
-+                                       DMA_BIDIRECTIONAL);
-+              buffer->sgt = NULL;
-+      }
-+      if (buffer->attach) {
-+              dma_buf_detach(buffer->dma_buf, buffer->attach);
-+              buffer->attach = NULL;
-+      }
-+
-+      /* Release the dma_buf (whether ours or imported) */
-+      if (buffer->import_dma_buf) {
-+              dma_buf_put(buffer->import_dma_buf);
-+              buffer->import_dma_buf = NULL;
-+              buffer->dma_buf = NULL;
-+      } else if (buffer->dma_buf) {
-+              dma_buf_put(buffer->dma_buf);
-+              buffer->dma_buf = NULL;
-+      }
-+
-+      if (buffer->sg_table && !buffer->import_dma_buf) {
-+              /* Our own allocation that we need to dma_unmap_sg */
-+              dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-+                           buffer->sg_table->nents, DMA_BIDIRECTIONAL);
-+      }
-+
-+      /* Free the local resource. Start by removing it from the list */
-+      buffer->private = NULL;
-+      list_del(&buffer->global_buffer_list);
-+
-+      mutex_unlock(&buffer->lock);
-+      mutex_unlock(&sm_state->map_lock);
-+
-+      mutex_destroy(&buffer->lock);
-+
-+      kfree(buffer);
-+      return;
-+
-+defer:
-+      mutex_unlock(&buffer->lock);
-+      mutex_unlock(&sm_state->map_lock);
-+}
-+
-+/* Create support for private data tracking. */
-+static struct vc_sm_privdata_t *vc_sm_cma_create_priv_data(pid_t id)
-+{
-+      char alloc_name[32];
-+      struct vc_sm_privdata_t *file_data = NULL;
-+
-+      /* Allocate private structure. */
-+      file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
-+
-+      if (!file_data)
-+              return NULL;
-+
-+      snprintf(alloc_name, sizeof(alloc_name), "%d", id);
-+
-+      file_data->pid = id;
-+
-+      return file_data;
-+}
-+
-+/* Dma_buf operations for chaining through to an imported dma_buf */
-+static
-+int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
-+                              struct dma_buf_attachment *attachment)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return -EINVAL;
-+      return res->import_dma_buf->ops->attach(res->import_dma_buf,
-+                                              attachment);
-+}
-+
-+static
-+void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
-+                                struct dma_buf_attachment *attachment)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return;
-+      res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
-+}
-+
-+static
-+struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
-+                                        enum dma_data_direction direction)
-+{
-+      struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return NULL;
-+      return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
-+}
-+
-+static
-+void vc_sm_import_unmap_dma_buf(struct dma_buf_attachment *attachment,
-+                              struct sg_table *table,
-+                              enum dma_data_direction direction)
-+{
-+      struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return;
-+      res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
-+}
-+
-+static
-+int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
-+               dmabuf, res, res->import_dma_buf);
-+      if (!res->import_dma_buf) {
-+              pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
-+                     __func__, dmabuf);
-+              return -EINVAL;
-+      }
-+      return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
-+}
-+
-+static
-+void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
-+      if (!res->import_dma_buf)
-+              return;
-+
-+      res->in_use = 0;
-+
-+      vc_sm_release_resource(res, 0);
-+}
-+
-+static
-+void *vc_sm_import_dma_buf_kmap(struct dma_buf *dmabuf,
-+                              unsigned long offset)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return NULL;
-+      return res->import_dma_buf->ops->map(res->import_dma_buf,
-+                                                    offset);
-+}
-+
-+static
-+void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
-+                               unsigned long offset, void *ptr)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return;
-+      res->import_dma_buf->ops->unmap(res->import_dma_buf,
-+                                             offset, ptr);
-+}
-+
-+static
-+int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
-+                                        enum dma_data_direction direction)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return -EINVAL;
-+      return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
-+                                                          direction);
-+}
-+
-+static
-+int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
-+                                      enum dma_data_direction direction)
-+{
-+      struct vc_sm_buffer *res = dmabuf->priv;
-+
-+      if (!res->import_dma_buf)
-+              return -EINVAL;
-+      return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
-+                                                        direction);
-+}
-+
-+static const struct dma_buf_ops dma_buf_import_ops = {
-+      .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,
-+      .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,
-+      .end_cpu_access = vc_sm_import_dma_buf_end_cpu_access,
-+      .map = vc_sm_import_dma_buf_kmap,
-+      .unmap = vc_sm_import_dma_buf_kunmap,
-+};
-+
-+/* Import a dma_buf to be shared with VC. */
-+int
-+vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
-+                               struct dma_buf *dma_buf,
-+                               struct dma_buf **imported_buf)
-+{
-+      DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-+      struct vc_sm_buffer *buffer = NULL;
-+      struct vc_sm_import import = { };
-+      struct vc_sm_import_result result = { };
-+      struct dma_buf_attachment *attach = NULL;
-+      struct sg_table *sgt = NULL;
-+      int ret = 0;
-+      int status;
-+
-+      /* Setup our allocation parameters */
-+      pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
-+
-+      get_dma_buf(dma_buf);
-+      dma_buf = dma_buf;
-+
-+      attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
-+      if (IS_ERR(attach)) {
-+              ret = PTR_ERR(attach);
-+              goto error;
-+      }
-+
-+      sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
-+      if (IS_ERR(sgt)) {
-+              ret = PTR_ERR(sgt);
-+              goto error;
-+      }
-+
-+      /* Verify that the address block is contiguous */
-+      if (sgt->nents != 1) {
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      /* Allocate local buffer to track this allocation. */
-+      buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-+      if (!buffer) {
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      import.type = VC_SM_ALLOC_NON_CACHED;
-+      import.addr = (uint32_t)sg_dma_address(sgt->sgl);
-+      if ((import.addr & 0xC0000000) != 0xC0000000) {
-+              pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
-+                     __func__, import.addr);
-+              import.addr |= 0xC0000000;
-+      }
-+      import.size = sg_dma_len(sgt->sgl);
-+      import.allocator = current->tgid;
-+      import.kernel_id = (uint32_t)buffer;    //FIXME: 64 bit support needed.
-+
-+      memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
-+             sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
-+
-+      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
-+               __func__, import.name, import.type, (void *)import.addr,
-+               import.size);
-+
-+      /* Allocate the videocore buffer. */
-+      status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-+                                     &sm_state->int_trans_id);
-+      if (status == -EINTR) {
-+              pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
-+                       __func__, sm_state->int_trans_id);
-+              ret = -ERESTARTSYS;
-+              private->restart_sys = -EINTR;
-+              private->int_action = VC_SM_MSG_TYPE_IMPORT;
-+              goto error;
-+      } else if (status || !result.res_handle) {
-+              pr_debug("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
-+                       __func__, status, sm_state->int_trans_id);
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      mutex_init(&buffer->lock);
-+      INIT_LIST_HEAD(&buffer->attachments);
-+      memcpy(buffer->name, import.name,
-+             min(sizeof(buffer->name), sizeof(import.name) - 1));
-+
-+      /* Keep track of the buffer we created. */
-+      buffer->private = private;
-+      buffer->vc_handle = result.res_handle;
-+      buffer->size = import.size;
-+      buffer->vpu_state = VPU_MAPPED;
-+
-+      buffer->import_dma_buf = dma_buf;
-+
-+      buffer->attach = attach;
-+      buffer->sgt = sgt;
-+      buffer->dma_addr = sg_dma_address(sgt->sgl);
-+      buffer->in_use = 1;
-+
-+      /*
-+       * We're done - we need to export a new dmabuf chaining through most
-+       * functions, but enabling us to release our own internal references
-+       * here.
-+       */
-+      exp_info.ops = &dma_buf_import_ops;
-+      exp_info.size = import.size;
-+      exp_info.flags = O_RDWR;
-+      exp_info.priv = buffer;
-+
-+      buffer->dma_buf = dma_buf_export(&exp_info);
-+      if (IS_ERR(buffer->dma_buf)) {
-+              ret = PTR_ERR(buffer->dma_buf);
-+              goto error;
-+      }
-+
-+      vc_sm_add_resource(private, buffer);
-+
-+      *imported_buf = buffer->dma_buf;
-+
-+      return 0;
-+
-+error:
-+      if (result.res_handle) {
-+              struct vc_sm_free_t free = { result.res_handle, 0 };
-+
-+              vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
-+                                  &sm_state->int_trans_id);
-+      }
-+      kfree(buffer);
-+      if (sgt)
-+              dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
-+      if (attach)
-+              dma_buf_detach(dma_buf, attach);
-+      dma_buf_put(dma_buf);
-+      return ret;
-+}
-+
-+/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
-+void
-+vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
-+              int reply_len)
-+{
-+      switch (reply->trans_id & ~0x80000000) {
-+      case VC_SM_MSG_TYPE_CLIENT_VERSION:
-+      {
-+              /* Acknowledge that the firmware supports the version command */
-+              pr_debug("%s: firmware acked version msg. Require release cb\n",
-+                       __func__);
-+              sm_state->require_released_callback = true;
-+      }
-+      break;
-+      case VC_SM_MSG_TYPE_RELEASED:
-+      {
-+              struct vc_sm_released *release = (struct vc_sm_released *)reply;
-+              struct vc_sm_buffer *buffer =
-+                              (struct vc_sm_buffer *)release->kernel_id;
-+
-+              /*
-+               * FIXME: Need to check buffer is still valid and allocated
-+               * before continuing
-+               */
-+              pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
-+                       __func__, release->addr, release->size,
-+                       release->kernel_id, release->vc_handle);
-+              mutex_lock(&buffer->lock);
-+              buffer->vc_handle = 0;
-+              buffer->vpu_state = VPU_NOT_MAPPED;
-+              mutex_unlock(&buffer->lock);
-+
-+              vc_sm_release_resource(buffer, 0);
-+      }
-+      break;
-+      default:
-+              pr_err("%s: Unknown vpu cmd %x\n", __func__, reply->trans_id);
-+              break;
-+      }
-+}
-+
-+/* Videocore connected.  */
-+static void vc_sm_connected_init(void)
-+{
-+      int ret;
-+      VCHI_INSTANCE_T vchi_instance;
-+      struct vc_sm_version version;
-+      struct vc_sm_result_t version_result;
-+
-+      pr_info("[%s]: start\n", __func__);
-+
-+      /*
-+       * Initialize and create a VCHI connection for the shared memory service
-+       * running on videocore.
-+       */
-+      ret = vchi_initialise(&vchi_instance);
-+      if (ret) {
-+              pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
-+                     __func__, ret);
-+
-+              ret = -EIO;
-+              goto err_free_mem;
-+      }
-+
-+      ret = vchi_connect(vchi_instance);
-+      if (ret) {
-+              pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
-+                     __func__, ret);
-+
-+              ret = -EIO;
-+              goto err_free_mem;
-+      }
-+
-+      /* Initialize an instance of the shared memory service. */
-+      sm_state->sm_handle = vc_sm_cma_vchi_init(vchi_instance, 1,
-+                                                vc_sm_vpu_event);
-+      if (!sm_state->sm_handle) {
-+              pr_err("[%s]: failed to initialize shared memory service\n",
-+                     __func__);
-+
-+              ret = -EPERM;
-+              goto err_free_mem;
-+      }
-+
-+      /* Create a debug fs directory entry (root). */
-+      sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
-+      if (!sm_state->dir_root) {
-+              pr_err("[%s]: failed to create \'%s\' directory entry\n",
-+                     __func__, VC_SM_DIR_ROOT_NAME);
-+
-+              ret = -EPERM;
-+              goto err_stop_sm_service;
-+      }
-+
-+      sm_state->dir_state.show = &vc_sm_cma_global_state_show;
-+      sm_state->dir_state.dir_entry =
-+              debugfs_create_file(VC_SM_STATE, 0444, sm_state->dir_root,
-+                                  &sm_state->dir_state,
-+                                  &vc_sm_cma_debug_fs_fops);
-+
-+      INIT_LIST_HEAD(&sm_state->buffer_list);
-+
-+      sm_state->data_knl = vc_sm_cma_create_priv_data(0);
-+      if (!sm_state->data_knl) {
-+              pr_err("[%s]: failed to create kernel private data tracker\n",
-+                     __func__);
-+              goto err_remove_shared_memory;
-+      }
-+
-+      version.version = 1;
-+      ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
-+                                          &version_result,
-+                                          &sm_state->int_trans_id);
-+      if (ret) {
-+              pr_err("[%s]: Failed to send version request %d\n", __func__,
-+                     ret);
-+      }
-+
-+      /* Done! */
-+      sm_inited = 1;
-+      pr_info("[%s]: installed successfully\n", __func__);
-+      return;
-+
-+err_remove_shared_memory:
-+      debugfs_remove_recursive(sm_state->dir_root);
-+err_stop_sm_service:
-+      vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-+err_free_mem:
-+      kfree(sm_state);
-+      pr_info("[%s]: failed, ret %d\n", __func__, ret);
-+}
-+
-+/* Driver loading. */
-+static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      int err;
-+
-+      pr_info("%s: Videocore shared memory driver\n", __func__);
-+
-+      sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
-+      if (!sm_state)
-+              return -ENOMEM;
-+      sm_state->pdev = pdev;
-+      mutex_init(&sm_state->map_lock);
-+
-+      dev->coherent_dma_mask = DMA_BIT_MASK(32);
-+      dev->dma_mask = &dev->coherent_dma_mask;
-+      err = of_dma_configure(dev, NULL, true);
-+      if (err) {
-+              dev_err(dev, "Unable to setup DMA: %d\n", err);
-+              return err;
-+      }
-+
-+      vchiq_add_connected_callback(vc_sm_connected_init);
-+      return 0;
-+}
-+
-+/* Driver unloading. */
-+static int bcm2835_vc_sm_cma_remove(struct platform_device *pdev)
-+{
-+      pr_debug("[%s]: start\n", __func__);
-+      if (sm_inited) {
-+              /* Remove shared memory device. */
-+              misc_deregister(&sm_state->dev);
-+
-+              /* Remove all proc entries. */
-+              //debugfs_remove_recursive(sm_state->dir_root);
-+
-+              /* Stop the videocore shared memory service. */
-+              vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-+
-+              /* Free the memory for the state structure. */
-+              mutex_destroy(&sm_state->map_lock);
-+              kfree(sm_state);
-+      }
-+
-+      pr_debug("[%s]: end\n", __func__);
-+      return 0;
-+}
-+
-+/* Get an internal resource handle mapped from the external one. */
-+int vc_sm_cma_int_handle(int handle)
-+{
-+      struct dma_buf *dma_buf = (struct dma_buf *)handle;
-+      struct vc_sm_buffer *res;
-+
-+      /* Validate we can work with this device. */
-+      if (!sm_state || !handle) {
-+              pr_err("[%s]: invalid input\n", __func__);
-+              return 0;
-+      }
-+
-+      res = (struct vc_sm_buffer *)dma_buf->priv;
-+      return res->vc_handle;
-+}
-+EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
-+
-+/* Free a previously allocated shared memory handle and block. */
-+int vc_sm_cma_free(int handle)
-+{
-+      struct dma_buf *dma_buf = (struct dma_buf *)handle;
-+
-+      /* Validate we can work with this device. */
-+      if (!sm_state || !handle) {
-+              pr_err("[%s]: invalid input\n", __func__);
-+              return -EPERM;
-+      }
-+
-+      pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
-+
-+      dma_buf_put(dma_buf);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(vc_sm_cma_free);
-+
-+/* Import a dmabuf to be shared with VC. */
-+int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
-+{
-+      struct dma_buf *new_dma_buf;
-+      struct vc_sm_buffer *res;
-+      int ret;
-+
-+      /* Validate we can work with this device. */
-+      if (!sm_state || !src_dmabuf || !handle) {
-+              pr_err("[%s]: invalid input\n", __func__);
-+              return -EPERM;
-+      }
-+
-+      ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
-+                                             &new_dma_buf);
-+
-+      if (!ret) {
-+              pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
-+              res = (struct vc_sm_buffer *)new_dma_buf->priv;
-+
-+              /* Assign valid handle at this time.*/
-+              *handle = (int)new_dma_buf;
-+      } else {
-+              /*
-+               * succeeded in importing the dma_buf, but then
-+               * failed to look it up again. How?
-+               * Release the fd again.
-+               */
-+              pr_err("%s: imported vc_sm_cma_get_buffer failed %d\n",
-+                     __func__, ret);
-+      }
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(vc_sm_cma_import_dmabuf);
-+
-+static struct platform_driver bcm2835_vcsm_cma_driver = {
-+      .probe = bcm2835_vc_sm_cma_probe,
-+      .remove = bcm2835_vc_sm_cma_remove,
-+      .driver = {
-+                 .name = DEVICE_NAME,
-+                 .owner = THIS_MODULE,
-+                 },
-+};
-+
-+module_platform_driver(bcm2835_vcsm_cma_driver);
-+
-+MODULE_AUTHOR("Dave Stevenson");
-+MODULE_DESCRIPTION("VideoCore CMA Shared Memory Driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:vcsm-cma");
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-@@ -0,0 +1,59 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory driver using CMA.
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ */
-+
-+#ifndef VC_SM_H
-+#define VC_SM_H
-+
-+#include <linux/device.h>
-+#include <linux/dma-direction.h>
-+#include <linux/kref.h>
-+#include <linux/mm_types.h>
-+#include <linux/mutex.h>
-+#include <linux/rbtree.h>
-+#include <linux/sched.h>
-+#include <linux/shrinker.h>
-+#include <linux/types.h>
-+#include <linux/miscdevice.h>
-+
-+#define VC_SM_MAX_NAME_LEN 32
-+
-+enum vc_sm_vpu_mapping_state {
-+      VPU_NOT_MAPPED,
-+      VPU_MAPPED,
-+      VPU_UNMAPPING
-+};
-+
-+struct vc_sm_buffer {
-+      struct list_head global_buffer_list;    /* Global list of buffers. */
-+
-+      size_t size;
-+
-+      /* Lock over all the following state for this buffer */
-+      struct mutex lock;
-+      struct sg_table *sg_table;
-+      struct list_head attachments;
-+
-+      char name[VC_SM_MAX_NAME_LEN];
-+
-+      int in_use:1;   /* Kernel is still using this resource */
-+
-+      enum vc_sm_vpu_mapping_state vpu_state;
-+      u32 vc_handle;  /* VideoCore handle for this buffer */
-+
-+      /* DMABUF related fields */
-+      struct dma_buf *import_dma_buf;
-+      struct dma_buf *dma_buf;
-+      struct dma_buf_attachment *attach;
-+      struct sg_table *sgt;
-+      dma_addr_t dma_addr;
-+
-+      struct vc_sm_privdata_t *private;
-+};
-+
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -0,0 +1,498 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ * Copyright 2011-2012 Broadcom Corporation.  All rights reserved.
-+ *
-+ * Based on vmcs_sm driver from Broadcom Corporation.
-+ *
-+ */
-+
-+/* ---- Include Files ----------------------------------------------------- */
-+#include <linux/completion.h>
-+#include <linux/kernel.h>
-+#include <linux/kthread.h>
-+#include <linux/list.h>
-+#include <linux/mutex.h>
-+#include <linux/semaphore.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+
-+#include "vc_sm_cma_vchi.h"
-+
-+#define VC_SM_VER  1
-+#define VC_SM_MIN_VER 0
-+
-+/* ---- Private Constants and Types -------------------------------------- */
-+
-+/* Command blocks come from a pool */
-+#define SM_MAX_NUM_CMD_RSP_BLKS 32
-+
-+struct sm_cmd_rsp_blk {
-+      struct list_head head;  /* To create lists */
-+      /* To be signaled when the response is there */
-+      struct completion cmplt;
-+
-+      u16 id;
-+      u16 length;
-+
-+      u8 msg[VC_SM_MAX_MSG_LEN];
-+
-+      uint32_t wait:1;
-+      uint32_t sent:1;
-+      uint32_t alloc:1;
-+
-+};
-+
-+struct sm_instance {
-+      u32 num_connections;
-+      VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
-+      struct task_struct *io_thread;
-+      struct completion io_cmplt;
-+
-+      vpu_event_cb vpu_event;
-+
-+      /* Mutex over the following lists */
-+      struct mutex lock;
-+      u32 trans_id;
-+      struct list_head cmd_list;
-+      struct list_head rsp_list;
-+      struct list_head dead_list;
-+
-+      struct sm_cmd_rsp_blk free_blk[SM_MAX_NUM_CMD_RSP_BLKS];
-+
-+      /* Mutex over the free_list */
-+      struct mutex free_lock;
-+      struct list_head free_list;
-+
-+      struct semaphore free_sema;
-+
-+};
-+
-+/* ---- Private Variables ------------------------------------------------ */
-+
-+/* ---- Private Function Prototypes -------------------------------------- */
-+
-+/* ---- Private Functions ------------------------------------------------ */
-+static int
-+bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
-+                     void *data,
-+                     unsigned int size)
-+{
-+      return vchi_queue_kernel_message(handle,
-+                                       data,
-+                                       size);
-+}
-+
-+static struct
-+sm_cmd_rsp_blk *vc_vchi_cmd_create(struct sm_instance *instance,
-+                                 enum vc_sm_msg_type id, void *msg,
-+                                 u32 size, int wait)
-+{
-+      struct sm_cmd_rsp_blk *blk;
-+      struct vc_sm_msg_hdr_t *hdr;
-+
-+      if (down_interruptible(&instance->free_sema)) {
-+              blk = kmalloc(sizeof(*blk), GFP_KERNEL);
-+              if (!blk)
-+                      return NULL;
-+
-+              blk->alloc = 1;
-+              init_completion(&blk->cmplt);
-+      } else {
-+              mutex_lock(&instance->free_lock);
-+              blk =
-+                  list_first_entry(&instance->free_list,
-+                                   struct sm_cmd_rsp_blk, head);
-+              list_del(&blk->head);
-+              mutex_unlock(&instance->free_lock);
-+      }
-+
-+      blk->sent = 0;
-+      blk->wait = wait;
-+      blk->length = sizeof(*hdr) + size;
-+
-+      hdr = (struct vc_sm_msg_hdr_t *)blk->msg;
-+      hdr->type = id;
-+      mutex_lock(&instance->lock);
-+      instance->trans_id++;
-+      /*
-+       * Retain the top bit for identifying asynchronous events, or VPU cmds.
-+       */
-+      instance->trans_id &= ~0x80000000;
-+      hdr->trans_id = instance->trans_id;
-+      blk->id = instance->trans_id;
-+      mutex_unlock(&instance->lock);
-+
-+      if (size)
-+              memcpy(hdr->body, msg, size);
-+
-+      return blk;
-+}
-+
-+static void
-+vc_vchi_cmd_delete(struct sm_instance *instance, struct sm_cmd_rsp_blk *blk)
-+{
-+      if (blk->alloc) {
-+              kfree(blk);
-+              return;
-+      }
-+
-+      mutex_lock(&instance->free_lock);
-+      list_add(&blk->head, &instance->free_list);
-+      mutex_unlock(&instance->free_lock);
-+      up(&instance->free_sema);
-+}
-+
-+static void vc_sm_cma_vchi_rx_ack(struct sm_instance *instance,
-+                                struct sm_cmd_rsp_blk *cmd,
-+                                struct vc_sm_result_t *reply,
-+                                u32 reply_len)
-+{
-+      mutex_lock(&instance->lock);
-+      list_for_each_entry(cmd,
-+                          &instance->rsp_list,
-+                          head) {
-+              if (cmd->id == reply->trans_id)
-+                      break;
-+      }
-+      mutex_unlock(&instance->lock);
-+
-+      if (&cmd->head == &instance->rsp_list) {
-+              //pr_debug("%s: received response %u, throw away...",
-+              pr_err("%s: received response %u, throw away...",
-+                     __func__,
-+                     reply->trans_id);
-+      } else if (reply_len > sizeof(cmd->msg)) {
-+              pr_err("%s: reply too big (%u) %u, throw away...",
-+                     __func__, reply_len,
-+                   reply->trans_id);
-+      } else {
-+              memcpy(cmd->msg, reply,
-+                     reply_len);
-+              complete(&cmd->cmplt);
-+      }
-+}
-+
-+static int vc_sm_cma_vchi_videocore_io(void *arg)
-+{
-+      struct sm_instance *instance = arg;
-+      struct sm_cmd_rsp_blk *cmd = NULL, *cmd_tmp;
-+      struct vc_sm_result_t *reply;
-+      u32 reply_len;
-+      s32 status;
-+      int svc_use = 1;
-+
-+      while (1) {
-+              if (svc_use)
-+                      vchi_service_release(instance->vchi_handle[0]);
-+              svc_use = 0;
-+              if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
-+                      vchi_service_use(instance->vchi_handle[0]);
-+                      svc_use = 1;
-+
-+                      do {
-+                              /*
-+                               * Get new command and move it to response list
-+                               */
-+                              mutex_lock(&instance->lock);
-+                              if (list_empty(&instance->cmd_list)) {
-+                                      /* no more commands to process */
-+                                      mutex_unlock(&instance->lock);
-+                                      break;
-+                              }
-+                              cmd =
-+                                  list_first_entry(&instance->cmd_list,
-+                                                   struct sm_cmd_rsp_blk,
-+                                                   head);
-+                              list_move(&cmd->head, &instance->rsp_list);
-+                              cmd->sent = 1;
-+                              mutex_unlock(&instance->lock);
-+
-+                              /* Send the command */
-+                              status = bcm2835_vchi_msg_queue(
-+                                              instance->vchi_handle[0],
-+                                              cmd->msg, cmd->length);
-+                              if (status) {
-+                                      pr_err("%s: failed to queue message (%d)",
-+                                             __func__, status);
-+                              }
-+
-+                              /* If no reply is needed then we're done */
-+                              if (!cmd->wait) {
-+                                      mutex_lock(&instance->lock);
-+                                      list_del(&cmd->head);
-+                                      mutex_unlock(&instance->lock);
-+                                      vc_vchi_cmd_delete(instance, cmd);
-+                                      continue;
-+                              }
-+
-+                              if (status) {
-+                                      complete(&cmd->cmplt);
-+                                      continue;
-+                              }
-+
-+                      } while (1);
-+
-+                      while (!vchi_msg_peek(instance->vchi_handle[0],
-+                                            (void **)&reply, &reply_len,
-+                                            VCHI_FLAGS_NONE)) {
-+                              if (reply->trans_id & 0x80000000) {
-+                                      /* Async event or cmd from the VPU */
-+                                      if (instance->vpu_event)
-+                                              instance->vpu_event(
-+                                                      instance, reply,
-+                                                      reply_len);
-+                              } else {
-+                                      vc_sm_cma_vchi_rx_ack(instance, cmd,
-+                                                            reply, reply_len);
-+                              }
-+
-+                              vchi_msg_remove(instance->vchi_handle[0]);
-+                      }
-+
-+                      /* Go through the dead list and free them */
-+                      mutex_lock(&instance->lock);
-+                      list_for_each_entry_safe(cmd, cmd_tmp,
-+                                               &instance->dead_list, head) {
-+                              list_del(&cmd->head);
-+                              vc_vchi_cmd_delete(instance, cmd);
-+                      }
-+                      mutex_unlock(&instance->lock);
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static void vc_sm_cma_vchi_callback(void *param,
-+                                  const VCHI_CALLBACK_REASON_T reason,
-+                                  void *msg_handle)
-+{
-+      struct sm_instance *instance = param;
-+
-+      (void)msg_handle;
-+
-+      switch (reason) {
-+      case VCHI_CALLBACK_MSG_AVAILABLE:
-+              complete(&instance->io_cmplt);
-+              break;
-+
-+      case VCHI_CALLBACK_SERVICE_CLOSED:
-+              pr_info("%s: service CLOSED!!", __func__);
-+      default:
-+              break;
-+      }
-+}
-+
-+struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
-+                                      unsigned int num_connections,
-+                                      vpu_event_cb vpu_event)
-+{
-+      u32 i;
-+      struct sm_instance *instance;
-+      int status;
-+
-+      pr_debug("%s: start", __func__);
-+
-+      if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
-+              pr_err("%s: unsupported number of connections %u (max=%u)",
-+                     __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
-+
-+              goto err_null;
-+      }
-+      /* Allocate memory for this instance */
-+      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-+
-+      /* Misc initialisations */
-+      mutex_init(&instance->lock);
-+      init_completion(&instance->io_cmplt);
-+      INIT_LIST_HEAD(&instance->cmd_list);
-+      INIT_LIST_HEAD(&instance->rsp_list);
-+      INIT_LIST_HEAD(&instance->dead_list);
-+      INIT_LIST_HEAD(&instance->free_list);
-+      sema_init(&instance->free_sema, SM_MAX_NUM_CMD_RSP_BLKS);
-+      mutex_init(&instance->free_lock);
-+      for (i = 0; i < SM_MAX_NUM_CMD_RSP_BLKS; i++) {
-+              init_completion(&instance->free_blk[i].cmplt);
-+              list_add(&instance->free_blk[i].head, &instance->free_list);
-+      }
-+
-+      /* Open the VCHI service connections */
-+      instance->num_connections = num_connections;
-+      for (i = 0; i < num_connections; i++) {
-+              SERVICE_CREATION_T params = {
-+                      .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
-+                      .service_id = VC_SM_SERVER_NAME,
-+                      .callback = vc_sm_cma_vchi_callback,
-+                      .callback_param = instance,
-+              };
-+
-+              status = vchi_service_open(vchi_instance,
-+                                         &params, &instance->vchi_handle[i]);
-+              if (status) {
-+                      pr_err("%s: failed to open VCHI service (%d)",
-+                             __func__, status);
-+
-+                      goto err_close_services;
-+              }
-+      }
-+
-+      /* Create the thread which takes care of all io to/from videoocore. */
-+      instance->io_thread = kthread_create(&vc_sm_cma_vchi_videocore_io,
-+                                           (void *)instance, "SMIO");
-+      if (!instance->io_thread) {
-+              pr_err("%s: failed to create SMIO thread", __func__);
-+
-+              goto err_close_services;
-+      }
-+      instance->vpu_event = vpu_event;
-+      set_user_nice(instance->io_thread, -10);
-+      wake_up_process(instance->io_thread);
-+
-+      pr_debug("%s: success - instance 0x%x", __func__,
-+               (unsigned int)instance);
-+      return instance;
-+
-+err_close_services:
-+      for (i = 0; i < instance->num_connections; i++) {
-+              if (instance->vchi_handle[i])
-+                      vchi_service_close(instance->vchi_handle[i]);
-+      }
-+      kfree(instance);
-+err_null:
-+      pr_debug("%s: FAILED", __func__);
-+      return NULL;
-+}
-+
-+int vc_sm_cma_vchi_stop(struct sm_instance **handle)
-+{
-+      struct sm_instance *instance;
-+      u32 i;
-+
-+      if (!handle) {
-+              pr_err("%s: invalid pointer to handle %p", __func__, handle);
-+              goto lock;
-+      }
-+
-+      if (!*handle) {
-+              pr_err("%s: invalid handle %p", __func__, *handle);
-+              goto lock;
-+      }
-+
-+      instance = *handle;
-+
-+      /* Close all VCHI service connections */
-+      for (i = 0; i < instance->num_connections; i++) {
-+              s32 success;
-+
-+              vchi_service_use(instance->vchi_handle[i]);
-+
-+              success = vchi_service_close(instance->vchi_handle[i]);
-+      }
-+
-+      kfree(instance);
-+
-+      *handle = NULL;
-+      return 0;
-+
-+lock:
-+      return -EINVAL;
-+}
-+
-+static int vc_sm_cma_vchi_send_msg(struct sm_instance *handle,
-+                                 enum vc_sm_msg_type msg_id, void *msg,
-+                                 u32 msg_size, void *result, u32 result_size,
-+                                 u32 *cur_trans_id, u8 wait_reply)
-+{
-+      int status = 0;
-+      struct sm_instance *instance = handle;
-+      struct sm_cmd_rsp_blk *cmd_blk;
-+
-+      if (!handle) {
-+              pr_err("%s: invalid handle", __func__);
-+              return -EINVAL;
-+      }
-+      if (!msg) {
-+              pr_err("%s: invalid msg pointer", __func__);
-+              return -EINVAL;
-+      }
-+
-+      cmd_blk =
-+          vc_vchi_cmd_create(instance, msg_id, msg, msg_size, wait_reply);
-+      if (!cmd_blk) {
-+              pr_err("[%s]: failed to allocate global tracking resource",
-+                     __func__);
-+              return -ENOMEM;
-+      }
-+
-+      if (cur_trans_id)
-+              *cur_trans_id = cmd_blk->id;
-+
-+      mutex_lock(&instance->lock);
-+      list_add_tail(&cmd_blk->head, &instance->cmd_list);
-+      mutex_unlock(&instance->lock);
-+      complete(&instance->io_cmplt);
-+
-+      if (!wait_reply)
-+              /* We're done */
-+              return 0;
-+
-+      /* Wait for the response */
-+      if (wait_for_completion_interruptible(&cmd_blk->cmplt)) {
-+              mutex_lock(&instance->lock);
-+              if (!cmd_blk->sent) {
-+                      list_del(&cmd_blk->head);
-+                      mutex_unlock(&instance->lock);
-+                      vc_vchi_cmd_delete(instance, cmd_blk);
-+                      return -ENXIO;
-+              }
-+
-+              list_move(&cmd_blk->head, &instance->dead_list);
-+              mutex_unlock(&instance->lock);
-+              complete(&instance->io_cmplt);
-+              return -EINTR;  /* We're done */
-+      }
-+
-+      if (result && result_size) {
-+              memcpy(result, cmd_blk->msg, result_size);
-+      } else {
-+              struct vc_sm_result_t *res =
-+                      (struct vc_sm_result_t *)cmd_blk->msg;
-+              status = (res->success == 0) ? 0 : -ENXIO;
-+      }
-+
-+      mutex_lock(&instance->lock);
-+      list_del(&cmd_blk->head);
-+      mutex_unlock(&instance->lock);
-+      vc_vchi_cmd_delete(instance, cmd_blk);
-+      return status;
-+}
-+
-+int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
-+                      u32 *cur_trans_id)
-+{
-+      return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_FREE,
-+                                 msg, sizeof(*msg), 0, 0, cur_trans_id, 0);
-+}
-+
-+int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
-+                        struct vc_sm_import_result *result, u32 *cur_trans_id)
-+{
-+      return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_IMPORT,
-+                                 msg, sizeof(*msg), result, sizeof(*result),
-+                                 cur_trans_id, 1);
-+}
-+
-+int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
-+                                struct vc_sm_version *msg,
-+                                struct vc_sm_result_t *result,
-+                                u32 *cur_trans_id)
-+{
-+      return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_CLIENT_VERSION,
-+                                 //msg, sizeof(*msg), result, sizeof(*result),
-+                                 //cur_trans_id, 1);
-+                                 msg, sizeof(*msg), NULL, 0,
-+                                 cur_trans_id, 0);
-+}
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
-@@ -0,0 +1,59 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ * Copyright 2011-2012 Broadcom Corporation.  All rights reserved.
-+ *
-+ * Based on vmcs_sm driver from Broadcom Corporation.
-+ *
-+ */
-+
-+#ifndef __VC_SM_CMA_VCHI_H__INCLUDED__
-+#define __VC_SM_CMA_VCHI_H__INCLUDED__
-+
-+#include "interface/vchi/vchi.h"
-+
-+#include "vc_sm_defs.h"
-+
-+/*
-+ * Forward declare.
-+ */
-+struct sm_instance;
-+
-+typedef void (*vpu_event_cb)(struct sm_instance *instance,
-+                           struct vc_sm_result_t *reply, int reply_len);
-+
-+/*
-+ * Initialize the shared memory service, opens up vchi connection to talk to it.
-+ */
-+struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
-+                                      unsigned int num_connections,
-+                                      vpu_event_cb vpu_event);
-+
-+/*
-+ * Terminates the shared memory service.
-+ */
-+int vc_sm_cma_vchi_stop(struct sm_instance **handle);
-+
-+/*
-+ * Ask the shared memory service to free up some memory that was previously
-+ * allocated by the vc_sm_cma_vchi_alloc function call.
-+ */
-+int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
-+                      u32 *cur_trans_id);
-+
-+/*
-+ * Import a contiguous block of memory and wrap it in a GPU MEM_HANDLE_T.
-+ */
-+int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
-+                        struct vc_sm_import_result *result,
-+                        u32 *cur_trans_id);
-+
-+int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
-+                                struct vc_sm_version *msg,
-+                                struct vc_sm_result_t *result,
-+                                u32 *cur_trans_id);
-+
-+#endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
-@@ -0,0 +1,298 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
-+ * All IPC messages are copied across to this file, even if the vc-sm-cma
-+ * driver is not currently using them.
-+ *
-+ ****************************************************************************
-+ */
-+
-+#ifndef __VC_SM_DEFS_H__INCLUDED__
-+#define __VC_SM_DEFS_H__INCLUDED__
-+
-+/* FourCC code used for VCHI connection */
-+#define VC_SM_SERVER_NAME MAKE_FOURCC("SMEM")
-+
-+/* Maximum message length */
-+#define VC_SM_MAX_MSG_LEN (sizeof(union vc_sm_msg_union_t) + \
-+      sizeof(struct vc_sm_msg_hdr_t))
-+#define VC_SM_MAX_RSP_LEN (sizeof(union vc_sm_msg_union_t))
-+
-+/* Resource name maximum size */
-+#define VC_SM_RESOURCE_NAME 32
-+
-+/*
-+ * Version to be reported to the VPU
-+ * VPU assumes 0 (aka 1) which does not require the released callback, nor
-+ * expect the client to handle VC_MEM_REQUESTS.
-+ * Version 2 requires the released callback, and must support VC_MEM_REQUESTS.
-+ */
-+#define VC_SM_PROTOCOL_VERSION        2
-+
-+enum vc_sm_msg_type {
-+      /* Message types supported for HOST->VC direction */
-+
-+      /* Allocate shared memory block */
-+      VC_SM_MSG_TYPE_ALLOC,
-+      /* Lock allocated shared memory block */
-+      VC_SM_MSG_TYPE_LOCK,
-+      /* Unlock allocated shared memory block */
-+      VC_SM_MSG_TYPE_UNLOCK,
-+      /* Unlock allocated shared memory block, do not answer command */
-+      VC_SM_MSG_TYPE_UNLOCK_NOANS,
-+      /* Free shared memory block */
-+      VC_SM_MSG_TYPE_FREE,
-+      /* Resize a shared memory block */
-+      VC_SM_MSG_TYPE_RESIZE,
-+      /* Walk the allocated shared memory block(s) */
-+      VC_SM_MSG_TYPE_WALK_ALLOC,
-+
-+      /* A previously applied action will need to be reverted */
-+      VC_SM_MSG_TYPE_ACTION_CLEAN,
-+
-+      /*
-+       * Import a physical address and wrap into a MEM_HANDLE_T.
-+       * Release with VC_SM_MSG_TYPE_FREE.
-+       */
-+      VC_SM_MSG_TYPE_IMPORT,
-+      /*
-+       *Tells VC the protocol version supported by this client.
-+       * 2 supports the async/cmd messages from the VPU for final release
-+       * of memory, and for VC allocations.
-+       */
-+      VC_SM_MSG_TYPE_CLIENT_VERSION,
-+      /* Response to VC request for memory */
-+      VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
-+
-+      /*
-+       * Asynchronous/cmd messages supported for VC->HOST direction.
-+       * Signalled by setting the top bit in vc_sm_result_t trans_id.
-+       */
-+
-+      /*
-+       * VC has finished with an imported memory allocation.
-+       * Release any Linux reference counts on the underlying block.
-+       */
-+      VC_SM_MSG_TYPE_RELEASED,
-+      /* VC request for memory */
-+      VC_SM_MSG_TYPE_VC_MEM_REQUEST,
-+
-+      VC_SM_MSG_TYPE_MAX
-+};
-+
-+/* Type of memory to be allocated */
-+enum vc_sm_alloc_type_t {
-+      VC_SM_ALLOC_CACHED,
-+      VC_SM_ALLOC_NON_CACHED,
-+};
-+
-+/* Message header for all messages in HOST->VC direction */
-+struct vc_sm_msg_hdr_t {
-+      u32 type;
-+      u32 trans_id;
-+      u8 body[0];
-+
-+};
-+
-+/* Request to allocate memory (HOST->VC) */
-+struct vc_sm_alloc_t {
-+      /* type of memory to allocate */
-+      enum vc_sm_alloc_type_t type;
-+      /* byte amount of data to allocate per unit */
-+      u32 base_unit;
-+      /* number of unit to allocate */
-+      u32 num_unit;
-+      /* alignment to be applied on allocation */
-+      u32 alignment;
-+      /* identity of who allocated this block */
-+      u32 allocator;
-+      /* resource name (for easier tracking on vc side) */
-+      char name[VC_SM_RESOURCE_NAME];
-+
-+};
-+
-+/* Result of a requested memory allocation (VC->HOST) */
-+struct vc_sm_alloc_result_t {
-+      /* Transaction identifier */
-+      u32 trans_id;
-+
-+      /* Resource handle */
-+      u32 res_handle;
-+      /* Pointer to resource buffer */
-+      u32 res_mem;
-+      /* Resource base size (bytes) */
-+      u32 res_base_size;
-+      /* Resource number */
-+      u32 res_num;
-+
-+};
-+
-+/* Request to free a previously allocated memory (HOST->VC) */
-+struct vc_sm_free_t {
-+      /* Resource handle (returned from alloc) */
-+      u32 res_handle;
-+      /* Resource buffer (returned from alloc) */
-+      u32 res_mem;
-+
-+};
-+
-+/* Request to lock a previously allocated memory (HOST->VC) */
-+struct vc_sm_lock_unlock_t {
-+      /* Resource handle (returned from alloc) */
-+      u32 res_handle;
-+      /* Resource buffer (returned from alloc) */
-+      u32 res_mem;
-+
-+};
-+
-+/* Request to resize a previously allocated memory (HOST->VC) */
-+struct vc_sm_resize_t {
-+      /* Resource handle (returned from alloc) */
-+      u32 res_handle;
-+      /* Resource buffer (returned from alloc) */
-+      u32 res_mem;
-+      /* Resource *new* size requested (bytes) */
-+      u32 res_new_size;
-+
-+};
-+
-+/* Result of a requested memory lock (VC->HOST) */
-+struct vc_sm_lock_result_t {
-+      /* Transaction identifier */
-+      u32 trans_id;
-+
-+      /* Resource handle */
-+      u32 res_handle;
-+      /* Pointer to resource buffer */
-+      u32 res_mem;
-+      /*
-+       * Pointer to former resource buffer if the memory
-+       * was reallocated
-+       */
-+      u32 res_old_mem;
-+
-+};
-+
-+/* Generic result for a request (VC->HOST) */
-+struct vc_sm_result_t {
-+      /* Transaction identifier */
-+      u32 trans_id;
-+
-+      s32 success;
-+
-+};
-+
-+/* Request to revert a previously applied action (HOST->VC) */
-+struct vc_sm_action_clean_t {
-+      /* Action of interest */
-+      enum vc_sm_msg_type res_action;
-+      /* Transaction identifier for the action of interest */
-+      u32 action_trans_id;
-+
-+};
-+
-+/* Request to remove all data associated with a given allocator (HOST->VC) */
-+struct vc_sm_free_all_t {
-+      /* Allocator identifier */
-+      u32 allocator;
-+};
-+
-+/* Request to import memory (HOST->VC) */
-+struct vc_sm_import {
-+      /* type of memory to allocate */
-+      enum vc_sm_alloc_type_t type;
-+      /* pointer to the VC (ie physical) address of the allocated memory */
-+      u32 addr;
-+      /* size of buffer */
-+      u32 size;
-+      /* opaque handle returned in RELEASED messages */
-+      u32 kernel_id;
-+      /* Allocator identifier */
-+      u32 allocator;
-+      /* resource name (for easier tracking on vc side) */
-+      char     name[VC_SM_RESOURCE_NAME];
-+};
-+
-+/* Result of a requested memory import (VC->HOST) */
-+struct vc_sm_import_result {
-+      /* Transaction identifier */
-+      u32 trans_id;
-+
-+      /* Resource handle */
-+      u32 res_handle;
-+};
-+
-+/* Notification that VC has finished with an allocation (VC->HOST) */
-+struct vc_sm_released {
-+      /* cmd type / trans_id */
-+      u32 cmd;
-+
-+      /* pointer to the VC (ie physical) address of the allocated memory */
-+      u32 addr;
-+      /* size of buffer */
-+      u32 size;
-+      /* opaque handle returned in RELEASED messages */
-+      u32 kernel_id;
-+      u32 vc_handle;
-+};
-+
-+/*
-+ * Client informing VC as to the protocol version it supports.
-+ * >=2 requires the released callback, and supports VC asking for memory.
-+ * Failure means that the firmware doesn't support this call, and therefore the
-+ * client should either fail, or NOT rely on getting the released callback.
-+ */
-+struct vc_sm_version {
-+      u32 version;
-+};
-+
-+/* Request FROM VideoCore for some memory */
-+struct vc_sm_vc_mem_request {
-+      /* cmd type */
-+      u32 cmd;
-+
-+      /* trans_id (from VPU) */
-+      u32 trans_id;
-+      /* size of buffer */
-+      u32 size;
-+      /* alignment of buffer */
-+      u32 align;
-+      /* resource name (for easier tracking) */
-+      char     name[VC_SM_RESOURCE_NAME];
-+};
-+
-+/* Response from the kernel to provide the VPU with some memory */
-+struct vc_sm_vc_mem_request_result {
-+      /* Transaction identifier for the VPU */
-+      u32 trans_id;
-+      /* pointer to the physical address of the allocated memory */
-+      u32 addr;
-+      /* opaque handle returned in RELEASED messages */
-+      u32 kernel_id;
-+};
-+
-+/* Union of ALL messages */
-+union vc_sm_msg_union_t {
-+      struct vc_sm_alloc_t alloc;
-+      struct vc_sm_alloc_result_t alloc_result;
-+      struct vc_sm_free_t free;
-+      struct vc_sm_lock_unlock_t lock_unlock;
-+      struct vc_sm_action_clean_t action_clean;
-+      struct vc_sm_resize_t resize;
-+      struct vc_sm_lock_result_t lock_result;
-+      struct vc_sm_result_t result;
-+      struct vc_sm_free_all_t free_all;
-+      struct vc_sm_import import;
-+      struct vc_sm_import_result import_result;
-+      struct vc_sm_version version;
-+      struct vc_sm_released released;
-+      struct vc_sm_vc_mem_request vc_request;
-+      struct vc_sm_vc_mem_request_result vc_request_result;
-+};
-+
-+#endif /* __VC_SM_DEFS_H__INCLUDED__ */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
-+ *
-+ */
-+
-+#ifndef __VC_SM_KNL_H__INCLUDED__
-+#define __VC_SM_KNL_H__INCLUDED__
-+
-+#if !defined(__KERNEL__)
-+#error "This interface is for kernel use only..."
-+#endif
-+
-+/* Free a previously allocated or imported shared memory handle and block. */
-+int vc_sm_cma_free(int handle);
-+
-+/* Get an internal resource handle mapped from the external one. */
-+int vc_sm_cma_int_handle(int handle);
-+
-+/* Import a block of memory into the GPU space. */
-+int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
-+
-+#endif /* __VC_SM_KNL_H__INCLUDED__ */
diff --git a/target/linux/brcm2708/patches-4.19/950-0242-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch b/target/linux/brcm2708/patches-4.19/950-0242-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch
new file mode 100644 (file)
index 0000000..8c69f65
--- /dev/null
@@ -0,0 +1,163 @@
+From bcb0dccc1f02ed3dd01834ca0e35c4043df8988e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 16:07:55 +0100
+Subject: [PATCH] staging: vc04_services: Use vc-sm-cma to support zero
+ copy
+
+With the vc-sm-cma driver we can support zero copy of buffers between
+the kernel and VPU. Add this support to vchiq-mmal.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vchiq-mmal/Kconfig  |  1 +
+ .../vc04_services/vchiq-mmal/mmal-common.h    |  4 ++
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 66 ++++++++++++++++++-
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  1 +
+ 4 files changed, 70 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/Kconfig
++++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
+@@ -2,6 +2,7 @@ config BCM2835_VCHIQ_MMAL
+       tristate "BCM2835 MMAL VCHIQ service"
+       depends on (ARCH_BCM2835 || COMPILE_TEST)
+       select BCM2835_VCHIQ
++      select BCM_VC_SM_CMA
+       help
+         Enables the MMAL API over VCHIQ as used for the
+         majority of the multimedia services on VideoCore.
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -51,6 +51,10 @@ struct mmal_buffer {
+       struct mmal_msg_context *msg_context;
++      struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
++      int vcsm_handle;        /* VCSM handle having imported the dmabuf */
++      u32 vc_handle;          /* VC handle to that dmabuf */
++
+       u32 cmd;                /* MMAL command. 0=data. */
+       unsigned long length;
+       u32 mmal_flags;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -27,9 +27,12 @@
+ #include <media/videobuf2-vmalloc.h>
+ #include "mmal-common.h"
++#include "mmal-parameters.h"
+ #include "mmal-vchiq.h"
+ #include "mmal-msg.h"
++#include "vc-sm-cma/vc_sm_knl.h"
++
+ #define USE_VCHIQ_ARM
+ #include "interface/vchi/vchi.h"
+@@ -425,8 +428,13 @@ buffer_from_host(struct vchiq_mmal_insta
+       /* buffer header */
+       m.u.buffer_from_host.buffer_header.cmd = 0;
+-      m.u.buffer_from_host.buffer_header.data =
+-              (u32)(unsigned long)buf->buffer;
++      if (port->zero_copy) {
++              m.u.buffer_from_host.buffer_header.data = buf->vc_handle;
++      } else {
++              m.u.buffer_from_host.buffer_header.data =
++                      (u32)(unsigned long)buf->buffer;
++      }
++
+       m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
+       if (port->type == MMAL_PORT_TYPE_OUTPUT) {
+               m.u.buffer_from_host.buffer_header.length = 0;
+@@ -591,6 +599,22 @@ static void buffer_to_host_cb(struct vch
+               msg_context->u.bulk.status = msg->h.status;
++      } else if (msg->u.buffer_from_host.is_zero_copy) {
++              /*
++               * Zero copy buffer, so nothing to do.
++               * Copy buffer info and make callback.
++               */
++              msg_context->u.bulk.buffer_used =
++                              msg->u.buffer_from_host.buffer_header.length;
++              msg_context->u.bulk.mmal_flags =
++                              msg->u.buffer_from_host.buffer_header.flags;
++              msg_context->u.bulk.dts =
++                              msg->u.buffer_from_host.buffer_header.dts;
++              msg_context->u.bulk.pts =
++                              msg->u.buffer_from_host.buffer_header.pts;
++              msg_context->u.bulk.cmd =
++                              msg->u.buffer_from_host.buffer_header.cmd;
++
+       } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
+               /* empty buffer */
+               if (msg->u.buffer_from_host.buffer_header.flags &
+@@ -1538,6 +1562,9 @@ int vchiq_mmal_port_parameter_set(struct
+       mutex_unlock(&instance->vchiq_mutex);
++      if (parameter == MMAL_PARAMETER_ZERO_COPY && !ret)
++              port->zero_copy = !!(*(bool *)value);
++
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
+@@ -1706,6 +1733,31 @@ int vchiq_mmal_submit_buffer(struct vchi
+       unsigned long flags = 0;
+       int ret;
++      /*
++       * We really want to do this in mmal_vchi_buffer_init but can't as
++       * videobuf2 won't let us have the dmabuf there.
++       */
++      if (port->zero_copy && buffer->dma_buf && !buffer->vcsm_handle) {
++              pr_debug("%s: import dmabuf %p\n", __func__, buffer->dma_buf);
++              ret = vc_sm_cma_import_dmabuf(buffer->dma_buf,
++                                            &buffer->vcsm_handle);
++              if (ret) {
++                      pr_err("%s: vc_sm_import_dmabuf_fd failed, ret %d\n",
++                             __func__, ret);
++                      return ret;
++              }
++
++              buffer->vc_handle = vc_sm_cma_int_handle(buffer->vcsm_handle);
++              if (!buffer->vc_handle) {
++                      pr_err("%s: vc_sm_int_handle failed %d\n",
++                             __func__, ret);
++                      vc_sm_cma_free(buffer->vcsm_handle);
++                      return ret;
++              }
++              pr_debug("%s: import dmabuf %p - got vc handle %08X\n",
++                       __func__, buffer->dma_buf, buffer->vc_handle);
++      }
++
+       ret = buffer_from_host(instance, port, buffer);
+       if (ret == -EINVAL) {
+               /* Port is disabled. Queue for when it is enabled. */
+@@ -1739,6 +1791,16 @@ int mmal_vchi_buffer_cleanup(struct mmal
+               release_msg_context(msg_context);
+       buf->msg_context = NULL;
++      if (buf->vcsm_handle) {
++              int ret;
++
++              pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
++                       buf->vcsm_handle);
++              ret = vc_sm_cma_free(buf->vcsm_handle);
++              if (ret)
++                      pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
++              buf->vcsm_handle = 0;
++      }
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -49,6 +49,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
+ struct vchiq_mmal_port {
+       u32 enabled:1;
++      u32 zero_copy:1;
+       u32 handle;
+       u32 type; /* port type, cached to use on port info set */
+       u32 index; /* port index, cached to use on port info set */
diff --git a/target/linux/brcm2708/patches-4.19/950-0243-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch b/target/linux/brcm2708/patches-4.19/950-0243-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch
new file mode 100644 (file)
index 0000000..fbaa3c2
--- /dev/null
@@ -0,0 +1,83 @@
+From 0b2a62596d0e6efe17bb87a3a5ebd91cee60c64b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 17:57:45 +0000
+Subject: [PATCH] media: videobuf2: Allow exporting of a struct dmabuf
+
+videobuf2 only allowed exporting a dmabuf as a file descriptor,
+but there are instances where having the struct dma_buf is
+useful within the kernel.
+
+Split the current implementation into two, one step which
+exports a struct dma_buf, and the second which converts that
+into an fd.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/common/videobuf2/videobuf2-core.c   | 21 ++++++++++++++++---
+ include/media/videobuf2-core.h                | 15 +++++++++++++
+ 2 files changed, 33 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/common/videobuf2/videobuf2-core.c
++++ b/drivers/media/common/videobuf2/videobuf2-core.c
+@@ -1851,12 +1851,12 @@ static int __find_plane_by_offset(struct
+       return -EINVAL;
+ }
+-int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
+-              unsigned int index, unsigned int plane, unsigned int flags)
++int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
++                         unsigned int index, unsigned int plane,
++                         unsigned int flags, struct dma_buf **dmabuf)
+ {
+       struct vb2_buffer *vb = NULL;
+       struct vb2_plane *vb_plane;
+-      int ret;
+       struct dma_buf *dbuf;
+       if (q->memory != VB2_MEMORY_MMAP) {
+@@ -1906,6 +1906,21 @@ int vb2_core_expbuf(struct vb2_queue *q,
+               return -EINVAL;
+       }
++      *dmabuf = dbuf;
++      return 0;
++}
++EXPORT_SYMBOL_GPL(vb2_core_expbuf_dmabuf);
++
++int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
++                  unsigned int index, unsigned int plane, unsigned int flags)
++{
++      struct dma_buf *dbuf;
++      int ret;
++
++      ret = vb2_core_expbuf_dmabuf(q, type, index, plane, flags, &dbuf);
++      if (ret)
++              return ret;
++
+       ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
+       if (ret < 0) {
+               dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
+--- a/include/media/videobuf2-core.h
++++ b/include/media/videobuf2-core.h
+@@ -825,6 +825,21 @@ int vb2_core_streamon(struct vb2_queue *
+ int vb2_core_streamoff(struct vb2_queue *q, unsigned int type);
+ /**
++ * vb2_core_expbuf_dmabuf() - Export a buffer as a dma_buf structure
++ * @q:         videobuf2 queue
++ * @type:      buffer type
++ * @index:     id number of the buffer
++ * @plane:     index of the plane to be exported, 0 for single plane queues
++ * @flags:     flags for newly created file, currently only O_CLOEXEC is
++ *             supported, refer to manual of open syscall for more details
++ * @dmabuf:    Returns the dmabuf pointer
++ *
++ */
++int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
++                         unsigned int index, unsigned int plane,
++                         unsigned int flags, struct dma_buf **dmabuf);
++
++/**
+  * vb2_core_expbuf() - Export a buffer as a file descriptor.
+  * @q:                pointer to &struct vb2_queue with videobuf2 queue.
+  * @fd:               pointer to the file descriptor associated with DMABUF
diff --git a/target/linux/brcm2708/patches-4.19/950-0243-staging-vc-sm-cma-Fixup-driver-for-older-VCHI-APIs.patch b/target/linux/brcm2708/patches-4.19/950-0243-staging-vc-sm-cma-Fixup-driver-for-older-VCHI-APIs.patch
deleted file mode 100644 (file)
index 4f16e0b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 9eb40722f3ef0d338ed97667a7391f3d74812332 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 30 Oct 2018 11:42:48 +0000
-Subject: [PATCH] staging: vc-sm-cma: Fixup driver for older VCHI APIs
-
-Original patch was based off staging which included some cleanups
-of the VCHI APIs. Those aren't present here, so switch back to
-the older API.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c          | 2 +-
- drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 5 +++++
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -632,7 +632,7 @@ static void vc_sm_connected_init(void)
-               goto err_free_mem;
-       }
--      ret = vchi_connect(vchi_instance);
-+      ret = vchi_connect(NULL, 0, vchi_instance);
-       if (ret) {
-               pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
-                      __func__, ret);
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -325,8 +325,13 @@ struct sm_instance *vc_sm_cma_vchi_init(
-               SERVICE_CREATION_T params = {
-                       .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
-                       .service_id = VC_SM_SERVER_NAME,
-+                      .rx_fifo_size = 0,
-+                      .tx_fifo_size = 0,
-                       .callback = vc_sm_cma_vchi_callback,
-                       .callback_param = instance,
-+                      .want_unaligned_bulk_rx = 0,
-+                      .want_unaligned_bulk_tx = 0,
-+                      .want_crc = 0
-               };
-               status = vchi_service_open(vchi_instance,
diff --git a/target/linux/brcm2708/patches-4.19/950-0244-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch b/target/linux/brcm2708/patches-4.19/950-0244-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch
new file mode 100644 (file)
index 0000000..0a6552b
--- /dev/null
@@ -0,0 +1,2467 @@
+From 2758fab4321519446fe5444769b6257dd18e794b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 14:53:49 +0100
+Subject: [PATCH] staging: vc04_services: Add a V4L2 M2M codec driver
+
+This adds a V4L2 memory to memory device that wraps the MMAL
+video decode and video_encode components for H264 and MJPEG encode
+and decode, MPEG4, H263, and VP8 decode (and MPEG2 decode
+if the appropriate licence has been purchased).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/Kconfig         |    1 +
+ drivers/staging/vc04_services/Makefile        |    9 +-
+ .../vc04_services/bcm2835-codec/Kconfig       |   11 +
+ .../vc04_services/bcm2835-codec/Makefile      |    8 +
+ .../staging/vc04_services/bcm2835-codec/TODO  |   24 +
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 2359 +++++++++++++++++
+ 6 files changed, 2408 insertions(+), 4 deletions(-)
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Kconfig
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Makefile
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/TODO
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+
+--- a/drivers/staging/vc04_services/Kconfig
++++ b/drivers/staging/vc04_services/Kconfig
+@@ -23,6 +23,7 @@ source "drivers/staging/vc04_services/bc
+ source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
+ source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
+ source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
++source "drivers/staging/vc04_services/bcm2835-codec/Kconfig"
+ endif
+--- a/drivers/staging/vc04_services/Makefile
++++ b/drivers/staging/vc04_services/Makefile
+@@ -10,10 +10,11 @@ vchiq-objs := \
+    interface/vchiq_arm/vchiq_util.o \
+    interface/vchiq_arm/vchiq_connected.o \
+-obj-$(CONFIG_SND_BCM2835)     += bcm2835-audio/
+-obj-$(CONFIG_VIDEO_BCM2835)   += bcm2835-camera/
+-obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
+-obj-$(CONFIG_BCM_VC_SM_CMA)   += vc-sm-cma/
++obj-$(CONFIG_SND_BCM2835)             += bcm2835-audio/
++obj-$(CONFIG_VIDEO_BCM2835)           += bcm2835-camera/
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL)      += vchiq-mmal/
++obj-$(CONFIG_BCM_VC_SM_CMA)           += vc-sm-cma/
++obj-$(CONFIG_VIDEO_CODEC_BCM2835)     += bcm2835-codec/
+ ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
+@@ -0,0 +1,11 @@
++config VIDEO_CODEC_BCM2835
++      tristate "BCM2835 Video codec support"
++      depends on MEDIA_SUPPORT
++      depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
++      select BCM2835_VCHIQ_MMAL
++      select VIDEOBUF2_DMA_CONTIG
++      select V4L2_MEM2MEM_DEV
++      help
++        Say Y here to enable the V4L2 video codecs for
++        Broadcom BCM2835 SoC. This operates over the VCHIQ interface
++        to a service running on VideoCore.
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/Makefile
+@@ -0,0 +1,8 @@
++# SPDX-License-Identifier: GPL-2.0
++bcm2835-codec-objs := bcm2835-v4l2-codec.o
++
++obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec.o
++
++ccflags-y += \
++      -Idrivers/staging/vc04_services \
++      -D__VCCOREVER__=0x04000000
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/TODO
+@@ -0,0 +1,24 @@
++1) Convert to be a platform driver.
++
++Right now when the module probes, it tries to initialize VCHI and
++errors out if it wasn't ready yet.  If bcm2835-v4l2 was built in, then
++VCHI generally isn't ready because it depends on both the firmware and
++mailbox drivers having already loaded.
++
++We should have VCHI create a platform device once it's initialized,
++and have this driver bind to it, so that we automatically load the
++v4l2 module after VCHI loads.
++
++2) Support SELECTION API to define crop region on the image for encode.
++
++Particularly for resolutions that aren't a multiple of the macroblock
++size, the codec will report a resolution that is a multiple of the macroblock
++size (it has to have the memory to decode into), and then a different crop
++region within that buffer.
++The most common example is 1080P, where the buffer will be 1920x1088 with a
++crop region of 1920x1080.
++
++3) Refactor so that the component creation is only on queue_setup, not open.
++
++Fixes v4l2-compliance failure on trying to open 100 instances of the
++device.
+\ No newline at end of file
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -0,0 +1,2359 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/*
++ * A v4l2-mem2mem device that wraps the video codec MMAL component.
++ *
++ * Copyright 2018 Raspberry Pi (Trading) Ltd.
++ * Author: Dave Stevenson (dave.stevenson@raspberrypi.org)
++ *
++ * Loosely based on the vim2m virtual driver by Pawel Osciak
++ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
++ * Pawel Osciak, <pawel@osciak.com>
++ * Marek Szyprowski, <m.szyprowski@samsung.com>
++ *
++ * Whilst this driver uses the v4l2_mem2mem framework, it does not need the
++ * scheduling aspects, so will always take the buffers, pass them to the VPU,
++ * and then signal the job as complete.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version
++ */
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/fs.h>
++#include <linux/timer.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/platform_device.h>
++#include <linux/syscalls.h>
++
++#include <media/v4l2-mem2mem.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-ioctl.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-event.h>
++#include <media/videobuf2-dma-contig.h>
++
++#include "vchiq-mmal/mmal-encodings.h"
++#include "vchiq-mmal/mmal-msg.h"
++#include "vchiq-mmal/mmal-parameters.h"
++#include "vchiq-mmal/mmal-vchiq.h"
++
++/*
++ * Default /dev/videoN node numbers for decode and encode.
++ * Deliberately avoid the very low numbers as these are often taken by webcams
++ * etc, and simple apps tend to only go for /dev/video0.
++ */
++static int decode_video_nr = 10;
++module_param(decode_video_nr, int, 0644);
++MODULE_PARM_DESC(decode_video_nr, "decoder video device number");
++
++static int encode_video_nr = 11;
++module_param(encode_video_nr, int, 0644);
++MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
++
++static unsigned int debug;
++module_param(debug, uint, 0644);
++MODULE_PARM_DESC(debug, "activates debug info (0-3)");
++
++#define MIN_W         32
++#define MIN_H         32
++#define MAX_W         1920
++#define MAX_H         1088
++#define BPL_ALIGN     32
++#define DEFAULT_WIDTH 640
++#define DEFAULT_HEIGHT        480
++/*
++ * The unanswered question - what is the maximum size of a compressed frame?
++ * V4L2 mandates that the encoded frame must fit in a single buffer. Sizing
++ * that buffer is a compromise between wasting memory and risking not fitting.
++ * The 1080P version of Big Buck Bunny has some frames that exceed 512kB.
++ * Adopt a moderately arbitrary split at 720P for switching between 512 and
++ * 768kB buffers.
++ */
++#define DEF_COMP_BUF_SIZE_GREATER_720P        (768 << 10)
++#define DEF_COMP_BUF_SIZE_720P_OR_LESS        (512 << 10)
++
++/* Flags that indicate a format can be used for capture/output */
++#define MEM2MEM_CAPTURE               BIT(0)
++#define MEM2MEM_OUTPUT                BIT(1)
++
++#define MEM2MEM_NAME          "bcm2835-codec"
++
++struct bcm2835_codec_fmt {
++      u32     fourcc;
++      int     depth;
++      int     bytesperline_align;
++      u32     flags;
++      u32     mmal_fmt;
++      bool    decode_only;
++      bool    encode_only;
++      int     size_multiplier_x2;
++};
++
++/* Supported raw pixel formats. Those supported for both encode and decode
++ * must come first, with those only supported for decode coming after (there
++ * are no formats supported for encode only).
++ */
++static struct bcm2835_codec_fmt raw_formats[] = {
++      {
++              .fourcc                 = V4L2_PIX_FMT_YUV420,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_I420,
++              .size_multiplier_x2     = 3,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_YVU420,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_YV12,
++              .size_multiplier_x2     = 3,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_NV12,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_NV12,
++              .size_multiplier_x2     = 3,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_NV21,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_NV21,
++              .size_multiplier_x2     = 3,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_RGB565,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_RGB16,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_YUYV,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_YUYV,
++              .encode_only            = true,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_UYVY,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_UYVY,
++              .encode_only            = true,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_YVYU,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_YVYU,
++              .encode_only            = true,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_VYUY,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_VYUY,
++              .encode_only            = true,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_RGB24,
++              .depth                  = 24,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_RGB24,
++              .encode_only            = true,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_BGR24,
++              .depth                  = 24,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BGR24,
++              .encode_only            = true,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_BGR32,
++              .depth                  = 32,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BGRA,
++              .encode_only            = true,
++              .size_multiplier_x2     = 2,
++      },
++};
++
++/* Supported encoded formats. Those supported for both encode and decode
++ * must come first, with those only supported for decode coming after (there
++ * are no formats supported for encode only).
++ */
++static struct bcm2835_codec_fmt encoded_formats[] = {
++      {
++              .fourcc                 = V4L2_PIX_FMT_H264,
++              .depth                  = 0,
++              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
++              .mmal_fmt               = MMAL_ENCODING_H264,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_MJPEG,
++              .depth                  = 0,
++              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
++              .mmal_fmt               = MMAL_ENCODING_MJPEG,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_MPEG4,
++              .depth                  = 0,
++              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
++              .mmal_fmt               = MMAL_ENCODING_MP4V,
++              .decode_only            = true,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_H263,
++              .depth                  = 0,
++              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
++              .mmal_fmt               = MMAL_ENCODING_H263,
++              .decode_only            = true,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_MPEG2,
++              .depth                  = 0,
++              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
++              .mmal_fmt               = MMAL_ENCODING_MP2V,
++              .decode_only            = true,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_VP8,
++              .depth                  = 0,
++              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
++              .mmal_fmt               = MMAL_ENCODING_VP8,
++              .decode_only            = true,
++      },
++      /*
++       * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
++       * support them.
++       */
++};
++
++struct bcm2835_codec_fmt_list {
++      struct bcm2835_codec_fmt *list;
++      unsigned int num_entries;
++};
++
++#define RAW_LIST      0
++#define ENCODED_LIST  1
++
++struct bcm2835_codec_fmt_list formats[] = {
++      {
++              .list = raw_formats,
++              .num_entries = ARRAY_SIZE(raw_formats),
++      }, {
++              .list = encoded_formats,
++              .num_entries = ARRAY_SIZE(encoded_formats),
++      },
++};
++
++struct m2m_mmal_buffer {
++      struct v4l2_m2m_buffer  m2m;
++      struct mmal_buffer      mmal;
++};
++
++/* Per-queue, driver-specific private data */
++struct bcm2835_codec_q_data {
++      /*
++       * These parameters should be treated as gospel, with everything else
++       * being determined from them.
++       */
++      /* Buffer width/height */
++      unsigned int            bytesperline;
++      unsigned int            height;
++      /* Crop size used for selection handling */
++      unsigned int            crop_width;
++      unsigned int            crop_height;
++      bool                    selection_set;
++
++      unsigned int            sizeimage;
++      unsigned int            sequence;
++      struct bcm2835_codec_fmt        *fmt;
++
++      /* One extra buffer header so we can send an EOS. */
++      struct m2m_mmal_buffer  eos_buffer;
++      bool                    eos_buffer_in_use;      /* debug only */
++};
++
++enum {
++      V4L2_M2M_SRC = 0,
++      V4L2_M2M_DST = 1,
++};
++
++static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
++                                                           bool capture)
++{
++      return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
++}
++
++static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
++{
++      return &get_format_list(decode, capture)->list[0];
++}
++
++static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
++                                           bool capture)
++{
++      struct bcm2835_codec_fmt *fmt;
++      unsigned int k;
++      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
++
++      for (k = 0; k < fmts->num_entries; k++) {
++              fmt = &fmts->list[k];
++              if (fmt->fourcc == f->fmt.pix.pixelformat)
++                      break;
++      }
++
++      /*
++       * Some compressed formats are only supported for decoding, not
++       * encoding.
++       */
++      if (!decode && fmts->list[k].decode_only)
++              return NULL;
++
++      /* Some pixel formats are only supported for encoding, not decoding. */
++      if (decode && fmts->list[k].encode_only)
++              return NULL;
++
++      if (k == fmts->num_entries)
++              return NULL;
++
++      return &fmts->list[k];
++}
++
++struct bcm2835_codec_dev {
++      struct platform_device *pdev;
++
++      /* v4l2 devices */
++      struct v4l2_device      v4l2_dev;
++      struct video_device     vfd;
++      /* mutex for the v4l2 device */
++      struct mutex            dev_mutex;
++      atomic_t                num_inst;
++
++      /* allocated mmal instance and components */
++      bool                    decode;  /* Is this instance a decoder? */
++      struct vchiq_mmal_instance      *instance;
++
++      struct v4l2_m2m_dev     *m2m_dev;
++};
++
++struct bcm2835_codec_ctx {
++      struct v4l2_fh          fh;
++      struct bcm2835_codec_dev        *dev;
++
++      struct v4l2_ctrl_handler hdl;
++
++      struct vchiq_mmal_component  *component;
++      bool component_enabled;
++
++      enum v4l2_colorspace    colorspace;
++      enum v4l2_ycbcr_encoding ycbcr_enc;
++      enum v4l2_xfer_func     xfer_func;
++      enum v4l2_quantization  quant;
++
++      /* Source and destination queue data */
++      struct bcm2835_codec_q_data   q_data[2];
++      s32  bitrate;
++
++      bool aborting;
++      int num_ip_buffers;
++      int num_op_buffers;
++      struct completion frame_cmplt;
++};
++
++struct bcm2835_codec_driver {
++      struct bcm2835_codec_dev *encode;
++      struct bcm2835_codec_dev *decode;
++};
++
++static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
++{
++      return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
++}
++
++static struct bcm2835_codec_q_data *get_q_data(struct bcm2835_codec_ctx *ctx,
++                                             enum v4l2_buf_type type)
++{
++      switch (type) {
++      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++              return &ctx->q_data[V4L2_M2M_SRC];
++      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++              return &ctx->q_data[V4L2_M2M_DST];
++      default:
++              v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
++                       __func__, type);
++              break;
++      }
++      return NULL;
++}
++
++static struct vchiq_mmal_port *get_port_data(struct bcm2835_codec_ctx *ctx,
++                                           enum v4l2_buf_type type)
++{
++      if (!ctx->component)
++              return NULL;
++
++      switch (type) {
++      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++              return &ctx->component->input[0];
++      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++              return &ctx->component->output[0];
++      default:
++              v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
++                       __func__, type);
++              break;
++      }
++      return NULL;
++}
++
++/*
++ * mem2mem callbacks
++ */
++
++/**
++ * job_ready() - check whether an instance is ready to be scheduled to run
++ */
++static int job_ready(void *priv)
++{
++      struct bcm2835_codec_ctx *ctx = priv;
++
++      if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
++          !v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx))
++              return 0;
++
++      return 1;
++}
++
++static void job_abort(void *priv)
++{
++      struct bcm2835_codec_ctx *ctx = priv;
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s\n", __func__);
++      /* Will cancel the transaction in the next interrupt handler */
++      ctx->aborting = 1;
++}
++
++static inline unsigned int get_sizeimage(int bpl, int height,
++                                       struct bcm2835_codec_fmt *fmt)
++{
++      return (bpl * height * fmt->size_multiplier_x2) >> 1;
++}
++
++static inline unsigned int get_bytesperline(int width,
++                                          struct bcm2835_codec_fmt *fmt)
++{
++      return ALIGN((width * fmt->depth) >> 3, fmt->bytesperline_align);
++}
++
++static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
++                                 bool decode,
++                                 struct bcm2835_codec_q_data *q_data,
++                                 struct vchiq_mmal_port *port)
++{
++      port->format.encoding = q_data->fmt->mmal_fmt;
++
++      if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
++              /* Raw image format - set width/height */
++              port->es.video.width = q_data->bytesperline /
++                                              (q_data->fmt->depth >> 3);
++              port->es.video.height = q_data->height;
++              port->es.video.crop.width = q_data->crop_width;
++              port->es.video.crop.height = q_data->crop_height;
++              port->es.video.frame_rate.num = 0;
++              port->es.video.frame_rate.den = 1;
++      } else {
++              /* Compressed format - leave resolution as 0 for decode */
++              if (decode) {
++                      port->es.video.width = 0;
++                      port->es.video.height = 0;
++                      port->es.video.crop.width = 0;
++                      port->es.video.crop.height = 0;
++              } else {
++                      port->es.video.width = q_data->crop_width;
++                      port->es.video.height = q_data->height;
++                      port->es.video.crop.width = q_data->crop_width;
++                      port->es.video.crop.height = q_data->crop_height;
++                      port->format.bitrate = ctx->bitrate;
++              }
++              port->es.video.frame_rate.num = 0;
++              port->es.video.frame_rate.den = 1;
++      }
++      port->es.video.crop.x = 0;
++      port->es.video.crop.y = 0;
++
++      port->current_buffer.size = q_data->sizeimage;
++};
++
++static void ip_buffer_cb(struct vchiq_mmal_instance *instance,
++                       struct vchiq_mmal_port *port, int status,
++                       struct mmal_buffer *mmal_buf)
++{
++      struct bcm2835_codec_ctx *ctx = port->cb_ctx/*, *curr_ctx*/;
++      struct m2m_mmal_buffer *buf =
++                      container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
++
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: port %p buf %p length %lu, flags %x\n",
++               __func__, port, mmal_buf, mmal_buf->length,
++               mmal_buf->mmal_flags);
++
++      if (buf == &ctx->q_data[V4L2_M2M_SRC].eos_buffer) {
++              /* Do we need to add lcoking to prevent multiple submission of
++               * the EOS, and therefore handle mutliple return here?
++               */
++              v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: eos buffer returned.\n",
++                       __func__);
++              ctx->q_data[V4L2_M2M_SRC].eos_buffer_in_use = false;
++              return;
++      }
++
++      if (status) {
++              /* error in transfer */
++              if (buf)
++                      /* there was a buffer with the error so return it */
++                      vb2_buffer_done(&buf->m2m.vb.vb2_buf,
++                                      VB2_BUF_STATE_ERROR);
++              return;
++      }
++      if (mmal_buf->cmd) {
++              v4l2_err(&ctx->dev->v4l2_dev, "%s: Not expecting cmd msgs on ip callback - %08x\n",
++                       __func__, mmal_buf->cmd);
++              /*
++               * CHECKME: Should we return here. The buffer shouldn't have a
++               * message context or vb2 buf associated.
++               */
++      }
++
++      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: no error. Return buffer %p\n",
++               __func__, &buf->m2m.vb.vb2_buf);
++      vb2_buffer_done(&buf->m2m.vb.vb2_buf, VB2_BUF_STATE_DONE);
++
++      ctx->num_ip_buffers++;
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d input buffers\n",
++               __func__, ctx->num_ip_buffers);
++
++      if (!port->enabled)
++              complete(&ctx->frame_cmplt);
++}
++
++static void queue_res_chg_event(struct bcm2835_codec_ctx *ctx)
++{
++      static const struct v4l2_event ev_src_ch = {
++              .type = V4L2_EVENT_SOURCE_CHANGE,
++              .u.src_change.changes =
++              V4L2_EVENT_SRC_CH_RESOLUTION,
++      };
++
++      v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
++}
++
++static void send_eos_event(struct bcm2835_codec_ctx *ctx)
++{
++      static const struct v4l2_event ev = {
++              .type = V4L2_EVENT_EOS,
++      };
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Sending EOS event\n");
++
++      v4l2_event_queue_fh(&ctx->fh, &ev);
++}
++
++static void color_mmal2v4l(struct bcm2835_codec_ctx *ctx, u32 mmal_color_space)
++{
++      switch (mmal_color_space) {
++      case MMAL_COLOR_SPACE_ITUR_BT601:
++              ctx->colorspace = V4L2_COLORSPACE_REC709;
++              ctx->xfer_func = V4L2_XFER_FUNC_709;
++              ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
++              ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
++              break;
++
++      case MMAL_COLOR_SPACE_ITUR_BT709:
++              ctx->colorspace = V4L2_COLORSPACE_REC709;
++              ctx->xfer_func = V4L2_XFER_FUNC_709;
++              ctx->ycbcr_enc = V4L2_YCBCR_ENC_709;
++              ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
++              break;
++      }
++}
++
++static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
++                             struct mmal_buffer *mmal_buf)
++{
++      struct bcm2835_codec_q_data *q_data;
++      struct mmal_msg_event_format_changed *format =
++              (struct mmal_msg_event_format_changed *)mmal_buf->buffer;
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
++               __func__,
++               format->buffer_size_min,
++               format->buffer_size_recommended,
++               format->buffer_num_min,
++               format->buffer_num_recommended
++              );
++      if (format->format.type != MMAL_ES_TYPE_VIDEO) {
++              v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed but not video %u\n",
++                       __func__, format->format.type);
++              return;
++      }
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed to %ux%u, crop %ux%u, colourspace %08X\n",
++               __func__, format->es.video.width, format->es.video.height,
++               format->es.video.crop.width, format->es.video.crop.height,
++               format->es.video.color_space);
++
++      q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
++      q_data->crop_width = format->es.video.crop.width;
++      q_data->crop_height = format->es.video.crop.height;
++      q_data->bytesperline = format->es.video.crop.width;
++      q_data->height = format->es.video.height;
++      q_data->sizeimage = format->buffer_size_min;
++      if (format->es.video.color_space)
++              color_mmal2v4l(ctx, format->es.video.color_space);
++
++      queue_res_chg_event(ctx);
++}
++
++static void op_buffer_cb(struct vchiq_mmal_instance *instance,
++                       struct vchiq_mmal_port *port, int status,
++                       struct mmal_buffer *mmal_buf)
++{
++      struct bcm2835_codec_ctx *ctx = port->cb_ctx;
++      struct m2m_mmal_buffer *buf;
++      struct vb2_v4l2_buffer *vb2;
++
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev,
++               "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
++               __func__, status, mmal_buf, mmal_buf->length,
++               mmal_buf->mmal_flags, mmal_buf->pts);
++
++      if (status) {
++              /* error in transfer */
++              if (vb2) {
++                      /* there was a buffer with the error so return it */
++                      vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
++              }
++              return;
++      }
++
++      if (mmal_buf->cmd) {
++              switch (mmal_buf->cmd) {
++              case MMAL_EVENT_FORMAT_CHANGED:
++              {
++                      handle_fmt_changed(ctx, mmal_buf);
++                      break;
++              }
++              default:
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Unexpected event on output callback - %08x\n",
++                               __func__, mmal_buf->cmd);
++                      break;
++              }
++              return;
++      }
++
++      buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
++      vb2 = &buf->m2m.vb;
++
++      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
++               __func__, mmal_buf->length, mmal_buf->mmal_flags,
++               vb2->vb2_buf.index);
++
++      if (mmal_buf->length == 0) {
++              /* stream ended, or buffer being returned during disable. */
++              v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: Empty buffer - flags %04x",
++                       __func__, mmal_buf->mmal_flags);
++              if (!mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
++                      vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
++                      if (!port->enabled)
++                              complete(&ctx->frame_cmplt);
++                      return;
++              }
++      }
++      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
++              /* EOS packet from the VPU */
++              send_eos_event(ctx);
++              vb2->flags |= V4L2_BUF_FLAG_LAST;
++      }
++
++      vb2->vb2_buf.timestamp = mmal_buf->pts;
++
++      vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
++      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
++              vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
++
++      vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_DONE);
++      ctx->num_op_buffers++;
++
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d output buffers\n",
++               __func__, ctx->num_op_buffers);
++
++      if (!port->enabled)
++              complete(&ctx->frame_cmplt);
++}
++
++/* vb2_to_mmal_buffer() - converts vb2 buffer header to MMAL
++ *
++ * Copies all the required fields from a VB2 buffer to the MMAL buffer header,
++ * ready for sending to the VPU.
++ */
++static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
++                             struct vb2_v4l2_buffer *vb2)
++{
++      buf->mmal.mmal_flags = 0;
++      if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
++              buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
++
++      /*
++       * Adding this means that the data must be framed correctly as one frame
++       * per buffer. The underlying decoder has no such requirement, but it
++       * will reduce latency as the bistream parser will be kicked immediately
++       * to parse the frame, rather than relying on its own heuristics for
++       * when to wake up.
++       */
++      buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
++
++      buf->mmal.length = vb2->vb2_buf.planes[0].bytesused;
++      /*
++       * Minor ambiguity in the V4L2 spec as to whether passing in a 0 length
++       * buffer, or one with V4L2_BUF_FLAG_LAST set denotes end of stream.
++       * Handle either.
++       */
++      if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
++              buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
++
++      buf->mmal.pts = vb2->vb2_buf.timestamp;
++      buf->mmal.dts = MMAL_TIME_UNKNOWN;
++}
++
++/* device_run() - prepares and starts the device
++ *
++ * This simulates all the immediate preparations required before starting
++ * a device. This will be called by the framework when it decides to schedule
++ * a particular instance.
++ */
++static void device_run(void *priv)
++{
++      struct bcm2835_codec_ctx *ctx = priv;
++      struct bcm2835_codec_dev *dev = ctx->dev;
++      struct vb2_v4l2_buffer *src_buf, *dst_buf;
++      struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
++      struct v4l2_m2m_buffer *m2m;
++      int ret;
++
++      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: off we go\n", __func__);
++
++      src_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->out_q_ctx);
++      if (src_buf) {
++              m2m = container_of(src_buf, struct v4l2_m2m_buffer, vb);
++              src_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
++              vb2_to_mmal_buffer(src_m2m_buf, src_buf);
++
++              ret = vchiq_mmal_submit_buffer(dev->instance,
++                                             &ctx->component->input[0],
++                                             &src_m2m_buf->mmal);
++              v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted ip buffer len %lu, pts %llu, flags %04x\n",
++                       __func__, src_m2m_buf->mmal.length,
++                       src_m2m_buf->mmal.pts, src_m2m_buf->mmal.mmal_flags);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting ip buffer\n",
++                               __func__);
++      }
++
++      dst_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->cap_q_ctx);
++      if (dst_buf) {
++              m2m = container_of(dst_buf, struct v4l2_m2m_buffer, vb);
++              dst_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
++              vb2_to_mmal_buffer(dst_m2m_buf, dst_buf);
++
++              ret = vchiq_mmal_submit_buffer(dev->instance,
++                                             &ctx->component->output[0],
++                                             &dst_m2m_buf->mmal);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting op buffer\n",
++                               __func__);
++      }
++
++      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted src %p, dst %p\n",
++               __func__, src_m2m_buf, dst_m2m_buf);
++
++      /* Complete the job here. */
++      v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
++}
++
++/*
++ * video ioctls
++ */
++static int vidioc_querycap(struct file *file, void *priv,
++                         struct v4l2_capability *cap)
++{
++      strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
++      strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
++      snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
++               MEM2MEM_NAME);
++      cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
++      cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
++      return 0;
++}
++
++static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
++{
++      struct bcm2835_codec_fmt *fmt;
++      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
++
++      if (f->index < fmts->num_entries) {
++              /* Format found */
++              /* Check format isn't a decode only format when encoding */
++              if (!decode &&
++                  fmts->list[f->index].decode_only)
++                      return -EINVAL;
++              /* Check format isn't a decode only format when encoding */
++              if (decode &&
++                  fmts->list[f->index].encode_only)
++                      return -EINVAL;
++
++              fmt = &fmts->list[f->index];
++              f->pixelformat = fmt->fourcc;
++              f->flags = fmt->flags;
++              return 0;
++      }
++
++      /* Format not found */
++      return -EINVAL;
++}
++
++static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
++                                 struct v4l2_fmtdesc *f)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      return enum_fmt(f, ctx->dev->decode, true);
++}
++
++static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
++                                 struct v4l2_fmtdesc *f)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      return enum_fmt(f, ctx->dev->decode, false);
++}
++
++static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
++{
++      struct vb2_queue *vq;
++      struct bcm2835_codec_q_data *q_data;
++
++      vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
++      if (!vq)
++              return -EINVAL;
++
++      q_data = get_q_data(ctx, f->type);
++
++      f->fmt.pix.width        = q_data->crop_width;
++      f->fmt.pix.height       = q_data->height;
++      f->fmt.pix.field        = V4L2_FIELD_NONE;
++      f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
++      f->fmt.pix.bytesperline = q_data->bytesperline;
++      f->fmt.pix.sizeimage    = q_data->sizeimage;
++      f->fmt.pix.colorspace   = ctx->colorspace;
++      f->fmt.pix.xfer_func    = ctx->xfer_func;
++      f->fmt.pix.ycbcr_enc    = ctx->ycbcr_enc;
++      f->fmt.pix.quantization = ctx->quant;
++
++      return 0;
++}
++
++static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
++                              struct v4l2_format *f)
++{
++      return vidioc_g_fmt(file2ctx(file), f);
++}
++
++static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
++                              struct v4l2_format *f)
++{
++      return vidioc_g_fmt(file2ctx(file), f);
++}
++
++static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
++{
++      /*
++       * The V4L2 specification requires the driver to correct the format
++       * struct if any of the dimensions is unsupported
++       */
++      if (f->fmt.pix.width > MAX_W)
++              f->fmt.pix.width = MAX_W;
++      if (f->fmt.pix.height > MAX_H)
++              f->fmt.pix.height = MAX_H;
++
++      if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
++              /* Only clip min w/h on capture. Treat 0x0 as unknown. */
++              if (f->fmt.pix.width < MIN_W)
++                      f->fmt.pix.width = MIN_W;
++              if (f->fmt.pix.height < MIN_H)
++                      f->fmt.pix.height = MIN_H;
++
++              /*
++               * Buffer must have a vertical alignment of 16 lines.
++               * The selection will reflect any cropping rectangle when only
++               * some of the pixels are active.
++               */
++              f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
++
++              f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
++                                                         fmt);
++              f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
++                                                   f->fmt.pix.height,
++                                                   fmt);
++      } else {
++              u32 min_size = f->fmt.pix.width > 1280 ||
++                             f->fmt.pix.height > 720 ?
++                             DEF_COMP_BUF_SIZE_GREATER_720P :
++                             DEF_COMP_BUF_SIZE_720P_OR_LESS;
++
++              f->fmt.pix.bytesperline = 0;
++              if (f->fmt.pix.sizeimage < min_size)
++                      f->fmt.pix.sizeimage = min_size;
++      }
++
++      f->fmt.pix.field = V4L2_FIELD_NONE;
++
++      return 0;
++}
++
++static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
++                                struct v4l2_format *f)
++{
++      struct bcm2835_codec_fmt *fmt;
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      fmt = find_format(f, ctx->dev->decode, true);
++      if (!fmt) {
++              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++                                                          true)->fourcc;
++              fmt = find_format(f, ctx->dev->decode, true);
++      }
++
++      return vidioc_try_fmt(f, fmt);
++}
++
++static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
++                                struct v4l2_format *f)
++{
++      struct bcm2835_codec_fmt *fmt;
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      fmt = find_format(f, ctx->dev->decode, false);
++      if (!fmt) {
++              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++                                                          false)->fourcc;
++              fmt = find_format(f, ctx->dev->decode, false);
++      }
++
++      if (!f->fmt.pix.colorspace)
++              f->fmt.pix.colorspace = ctx->colorspace;
++
++      return vidioc_try_fmt(f, fmt);
++}
++
++static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
++                      unsigned int requested_height)
++{
++      struct bcm2835_codec_q_data *q_data;
++      struct vb2_queue *vq;
++      struct vchiq_mmal_port *port;
++      bool update_capture_port = false;
++      int ret;
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
++               f->type, f->fmt.pix.width, f->fmt.pix.height,
++               f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
++
++      vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
++      if (!vq)
++              return -EINVAL;
++
++      q_data = get_q_data(ctx, f->type);
++      if (!q_data)
++              return -EINVAL;
++
++      if (vb2_is_busy(vq)) {
++              v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
++              return -EBUSY;
++      }
++
++      q_data->fmt = find_format(f, ctx->dev->decode,
++                                f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
++      q_data->crop_width = f->fmt.pix.width;
++      q_data->height = f->fmt.pix.height;
++      if (!q_data->selection_set)
++              q_data->crop_height = requested_height;
++
++      /*
++       * Copying the behaviour of vicodec which retains a single set of
++       * colorspace parameters for both input and output.
++       */
++      ctx->colorspace = f->fmt.pix.colorspace;
++      ctx->xfer_func = f->fmt.pix.xfer_func;
++      ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
++      ctx->quant = f->fmt.pix.quantization;
++
++      /* All parameters should have been set correctly by try_fmt */
++      q_data->bytesperline = f->fmt.pix.bytesperline;
++      q_data->sizeimage = f->fmt.pix.sizeimage;
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
++               q_data->bytesperline, q_data->sizeimage);
++
++      if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
++          f->fmt.pix.width && f->fmt.pix.height) {
++              /*
++               * On the decoder, if provided with a resolution on the input
++               * side, then replicate that to the output side.
++               * GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
++               * nor set up a resolution on the output side, therefore
++               * we can't decode anything at a resolution other than the
++               * default one.
++               */
++              struct bcm2835_codec_q_data *q_data_dst =
++                                              &ctx->q_data[V4L2_M2M_DST];
++
++              q_data_dst->crop_width = q_data->crop_width;
++              q_data_dst->crop_height = q_data->crop_height;
++              q_data_dst->height = ALIGN(q_data->crop_height, 16);
++
++              q_data_dst->bytesperline =
++                      get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
++              q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
++                                                    q_data_dst->height,
++                                                    q_data_dst->fmt);
++              update_capture_port = true;
++      }
++
++      /* If we have a component then setup the port as well */
++      port = get_port_data(ctx, vq->type);
++      if (!port)
++              return 0;
++
++      setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
++      ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
++      if (ret) {
++              v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
++                       __func__, ret);
++              ret = -EINVAL;
++      }
++
++      if (q_data->sizeimage < port->minimum_buffer.size) {
++              v4l2_err(&ctx->dev->v4l2_dev, "%s: Current buffer size of %u < min buf size %u - driver mismatch to MMAL\n",
++                       __func__, q_data->sizeimage,
++                       port->minimum_buffer.size);
++      }
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
++               f->type, q_data->crop_width, q_data->height,
++               q_data->fmt->fourcc, q_data->sizeimage);
++
++      if (update_capture_port) {
++              struct vchiq_mmal_port *port_dst = &ctx->component->output[0];
++              struct bcm2835_codec_q_data *q_data_dst =
++                                              &ctx->q_data[V4L2_M2M_DST];
++
++              setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
++                                     port_dst);
++              ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
++              if (ret) {
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
++                               __func__, ret);
++                      ret = -EINVAL;
++              }
++      }
++      return ret;
++}
++
++static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
++                              struct v4l2_format *f)
++{
++      unsigned int height = f->fmt.pix.height;
++      int ret;
++
++      ret = vidioc_try_fmt_vid_cap(file, priv, f);
++      if (ret)
++              return ret;
++
++      return vidioc_s_fmt(file2ctx(file), f, height);
++}
++
++static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
++                              struct v4l2_format *f)
++{
++      unsigned int height = f->fmt.pix.height;
++      int ret;
++
++      ret = vidioc_try_fmt_vid_out(file, priv, f);
++      if (ret)
++              return ret;
++
++      ret = vidioc_s_fmt(file2ctx(file), f, height);
++      return ret;
++}
++
++static int vidioc_g_selection(struct file *file, void *priv,
++                            struct v4l2_selection *s)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++      struct bcm2835_codec_q_data *q_data;
++      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
++                                                              true : false;
++
++      if (capture_queue ^ ctx->dev->decode)
++              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
++              return -EINVAL;
++
++      q_data = get_q_data(ctx, s->type);
++      if (!q_data)
++              return -EINVAL;
++
++      if (ctx->dev->decode) {
++              switch (s->target) {
++              case V4L2_SEL_TGT_COMPOSE_DEFAULT:
++              case V4L2_SEL_TGT_COMPOSE:
++                      s->r.left = 0;
++                      s->r.top = 0;
++                      s->r.width = q_data->crop_width;
++                      s->r.height = q_data->crop_height;
++                      break;
++              case V4L2_SEL_TGT_COMPOSE_BOUNDS:
++                      s->r.left = 0;
++                      s->r.top = 0;
++                      s->r.width = q_data->crop_width;
++                      s->r.height = q_data->crop_height;
++                      break;
++              default:
++                      return -EINVAL;
++              }
++      } else {
++              switch (s->target) {
++              case V4L2_SEL_TGT_CROP_DEFAULT:
++              case V4L2_SEL_TGT_CROP_BOUNDS:
++                      s->r.top = 0;
++                      s->r.left = 0;
++                      s->r.width = q_data->bytesperline;
++                      s->r.height = q_data->height;
++                      break;
++              case V4L2_SEL_TGT_CROP:
++                      s->r.top = 0;
++                      s->r.left = 0;
++                      s->r.width = q_data->crop_width;
++                      s->r.height = q_data->crop_height;
++                      break;
++              default:
++                      return -EINVAL;
++              }
++      }
++
++      return 0;
++}
++
++static int vidioc_s_selection(struct file *file, void *priv,
++                            struct v4l2_selection *s)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++      struct bcm2835_codec_q_data *q_data = NULL;
++      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
++                                                              true : false;
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
++               __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
++               s->r.width, s->r.height);
++
++      if (capture_queue ^ ctx->dev->decode)
++              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
++              return -EINVAL;
++
++      q_data = get_q_data(ctx, s->type);
++      if (!q_data)
++              return -EINVAL;
++
++      if (ctx->dev->decode) {
++              switch (s->target) {
++              case V4L2_SEL_TGT_COMPOSE:
++                      /* Accept cropped image */
++                      s->r.left = 0;
++                      s->r.top = 0;
++                      s->r.width = min(s->r.width, q_data->crop_width);
++                      s->r.height = min(s->r.height, q_data->height);
++                      q_data->crop_width = s->r.width;
++                      q_data->crop_height = s->r.height;
++                      q_data->selection_set = true;
++                      break;
++              default:
++                      return -EINVAL;
++              }
++      } else {
++              switch (s->target) {
++              case V4L2_SEL_TGT_CROP:
++                      /* Only support crop from (0,0) */
++                      s->r.top = 0;
++                      s->r.left = 0;
++                      s->r.width = min(s->r.width, q_data->crop_width);
++                      s->r.height = min(s->r.height, q_data->crop_height);
++                      q_data->crop_width = s->r.width;
++                      q_data->crop_height = s->r.height;
++                      q_data->selection_set = true;
++                      break;
++              default:
++                      return -EINVAL;
++              }
++      }
++
++      return 0;
++}
++
++static int vidioc_subscribe_evt(struct v4l2_fh *fh,
++                              const struct v4l2_event_subscription *sub)
++{
++      switch (sub->type) {
++      case V4L2_EVENT_EOS:
++              return v4l2_event_subscribe(fh, sub, 2, NULL);
++      case V4L2_EVENT_SOURCE_CHANGE:
++              return v4l2_src_change_event_subscribe(fh, sub);
++      default:
++              return v4l2_ctrl_subscribe_event(fh, sub);
++      }
++}
++
++static int bcm2835_codec_set_level_profile(struct bcm2835_codec_ctx *ctx,
++                                         struct v4l2_ctrl *ctrl)
++{
++      struct mmal_parameter_video_profile param;
++      int param_size = sizeof(param);
++      int ret;
++
++      /*
++       * Level and Profile are set via the same MMAL parameter.
++       * Retrieve the current settings and amend the one that has changed.
++       */
++      ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
++                                          &ctx->component->output[0],
++                                          MMAL_PARAMETER_PROFILE,
++                                          &param,
++                                          &param_size);
++      if (ret)
++              return ret;
++
++      switch (ctrl->id) {
++      case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
++              switch (ctrl->val) {
++              case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
++                      param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
++                      param.profile =
++                              MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
++                      param.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
++                      param.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
++                      break;
++              default:
++                      /* Should never get here */
++                      break;
++              }
++              break;
++
++      case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
++              switch (ctrl->val) {
++              case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
++                      param.level = MMAL_VIDEO_LEVEL_H264_1;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
++                      param.level = MMAL_VIDEO_LEVEL_H264_1b;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
++                      param.level = MMAL_VIDEO_LEVEL_H264_11;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
++                      param.level = MMAL_VIDEO_LEVEL_H264_12;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
++                      param.level = MMAL_VIDEO_LEVEL_H264_13;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
++                      param.level = MMAL_VIDEO_LEVEL_H264_2;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
++                      param.level = MMAL_VIDEO_LEVEL_H264_21;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
++                      param.level = MMAL_VIDEO_LEVEL_H264_22;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
++                      param.level = MMAL_VIDEO_LEVEL_H264_3;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
++                      param.level = MMAL_VIDEO_LEVEL_H264_31;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
++                      param.level = MMAL_VIDEO_LEVEL_H264_32;
++                      break;
++              case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
++                      param.level = MMAL_VIDEO_LEVEL_H264_4;
++                      break;
++              default:
++                      /* Should never get here */
++                      break;
++              }
++      }
++      ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++                                          &ctx->component->output[0],
++                                          MMAL_PARAMETER_PROFILE,
++                                          &param,
++                                          param_size);
++
++      return ret;
++}
++
++static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++      struct bcm2835_codec_ctx *ctx =
++              container_of(ctrl->handler, struct bcm2835_codec_ctx, hdl);
++      int ret = 0;
++
++      switch (ctrl->id) {
++      case V4L2_CID_MPEG_VIDEO_BITRATE:
++              ctx->bitrate = ctrl->val;
++              if (!ctx->component)
++                      break;
++
++              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++                                                  &ctx->component->output[0],
++                                                  MMAL_PARAMETER_VIDEO_BIT_RATE,
++                                                  &ctrl->val,
++                                                  sizeof(ctrl->val));
++              break;
++
++      case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
++              u32 bitrate_mode;
++
++              if (!ctx->component)
++                      break;
++
++              switch (ctrl->val) {
++              default:
++              case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
++                      bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
++                      break;
++              case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
++                      bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
++                      break;
++              }
++
++              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++                                                  &ctx->component->output[0],
++                                                  MMAL_PARAMETER_RATECONTROL,
++                                                  &bitrate_mode,
++                                                  sizeof(bitrate_mode));
++              break;
++      }
++      case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
++              if (!ctx->component)
++                      break;
++
++              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++                                                  &ctx->component->output[0],
++                                                  MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
++                                                  &ctrl->val,
++                                                  sizeof(ctrl->val));
++              break;
++
++      case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
++              if (!ctx->component)
++                      break;
++
++              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++                                                  &ctx->component->output[0],
++                                                  MMAL_PARAMETER_INTRAPERIOD,
++                                                  &ctrl->val,
++                                                  sizeof(ctrl->val));
++              break;
++
++      case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
++      case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
++              if (!ctx->component)
++                      break;
++
++              ret = bcm2835_codec_set_level_profile(ctx, ctrl);
++              break;
++
++      default:
++              v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
++              return -EINVAL;
++      }
++
++      if (ret)
++              v4l2_err(&ctx->dev->v4l2_dev, "Failed setting ctrl %08x, ret %d\n",
++                       ctrl->id, ret);
++      return ret ? -EINVAL : 0;
++}
++
++static const struct v4l2_ctrl_ops bcm2835_codec_ctrl_ops = {
++      .s_ctrl = bcm2835_codec_s_ctrl,
++};
++
++static int vidioc_try_decoder_cmd(struct file *file, void *priv,
++                                struct v4l2_decoder_cmd *cmd)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      if (!ctx->dev->decode)
++              return -EINVAL;
++
++      switch (cmd->cmd) {
++      case V4L2_DEC_CMD_STOP:
++              if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) {
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: DEC cmd->flags=%u stop to black not supported",
++                               __func__, cmd->flags);
++                      return -EINVAL;
++              }
++              break;
++      case V4L2_DEC_CMD_START:
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static int vidioc_decoder_cmd(struct file *file, void *priv,
++                            struct v4l2_decoder_cmd *cmd)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++      struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
++      int ret;
++
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
++               cmd->cmd);
++      ret = vidioc_try_decoder_cmd(file, priv, cmd);
++      if (ret)
++              return ret;
++
++      switch (cmd->cmd) {
++      case V4L2_DEC_CMD_STOP:
++              if (q_data->eos_buffer_in_use)
++                      v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
++              q_data->eos_buffer_in_use = true;
++
++              q_data->eos_buffer.mmal.buffer_size = 0;
++              q_data->eos_buffer.mmal.length = 0;
++              q_data->eos_buffer.mmal.mmal_flags =
++                                              MMAL_BUFFER_HEADER_FLAG_EOS;
++              q_data->eos_buffer.mmal.pts = 0;
++              q_data->eos_buffer.mmal.dts = 0;
++
++              if (!ctx->component)
++                      break;
++
++              ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
++                                             &ctx->component->input[0],
++                                             &q_data->eos_buffer.mmal);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev,
++                               "%s: EOS buffer submit failed %d\n",
++                               __func__, ret);
++
++              break;
++
++      case V4L2_DEC_CMD_START:
++              /* Do we need to do anything here? */
++              break;
++
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int vidioc_try_encoder_cmd(struct file *file, void *priv,
++                                struct v4l2_encoder_cmd *cmd)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      if (ctx->dev->decode)
++              return -EINVAL;
++
++      switch (cmd->cmd) {
++      case V4L2_ENC_CMD_STOP:
++              break;
++
++      case V4L2_ENC_CMD_START:
++              /* Do we need to do anything here? */
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static int vidioc_encoder_cmd(struct file *file, void *priv,
++                            struct v4l2_encoder_cmd *cmd)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++      struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
++      int ret;
++
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
++               cmd->cmd);
++      ret = vidioc_try_encoder_cmd(file, priv, cmd);
++      if (ret)
++              return ret;
++
++      switch (cmd->cmd) {
++      case V4L2_ENC_CMD_STOP:
++              if (q_data->eos_buffer_in_use)
++                      v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
++              q_data->eos_buffer_in_use = true;
++
++              q_data->eos_buffer.mmal.buffer_size = 0;
++              q_data->eos_buffer.mmal.length = 0;
++              q_data->eos_buffer.mmal.mmal_flags =
++                                              MMAL_BUFFER_HEADER_FLAG_EOS;
++              q_data->eos_buffer.mmal.pts = 0;
++              q_data->eos_buffer.mmal.dts = 0;
++
++              if (!ctx->component)
++                      break;
++
++              ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
++                                             &ctx->component->input[0],
++                                             &q_data->eos_buffer.mmal);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev,
++                               "%s: EOS buffer submit failed %d\n",
++                               __func__, ret);
++
++              break;
++      case V4L2_ENC_CMD_START:
++              /* Do we need to do anything here? */
++              break;
++
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
++      .vidioc_querycap        = vidioc_querycap,
++
++      .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
++      .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
++      .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
++      .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
++
++      .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
++      .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
++      .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
++      .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
++
++      .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
++      .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
++      .vidioc_qbuf            = v4l2_m2m_ioctl_qbuf,
++      .vidioc_dqbuf           = v4l2_m2m_ioctl_dqbuf,
++      .vidioc_prepare_buf     = v4l2_m2m_ioctl_prepare_buf,
++      .vidioc_create_bufs     = v4l2_m2m_ioctl_create_bufs,
++      .vidioc_expbuf          = v4l2_m2m_ioctl_expbuf,
++
++      .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
++      .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
++
++      .vidioc_g_selection     = vidioc_g_selection,
++      .vidioc_s_selection     = vidioc_s_selection,
++
++      .vidioc_subscribe_event = vidioc_subscribe_evt,
++      .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
++
++      .vidioc_decoder_cmd = vidioc_decoder_cmd,
++      .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
++      .vidioc_encoder_cmd = vidioc_encoder_cmd,
++      .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
++};
++
++static int bcm2835_codec_set_ctrls(struct bcm2835_codec_ctx *ctx)
++{
++      /*
++       * Query the control handler for the value of the various controls and
++       * set them.
++       */
++      const u32 control_ids[] = {
++              V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
++              V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
++              V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
++              V4L2_CID_MPEG_VIDEO_H264_LEVEL,
++              V4L2_CID_MPEG_VIDEO_H264_PROFILE,
++      };
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(control_ids); i++) {
++              struct v4l2_ctrl *ctrl;
++
++              ctrl = v4l2_ctrl_find(&ctx->hdl, control_ids[i]);
++              if (ctrl)
++                      bcm2835_codec_s_ctrl(ctrl);
++      }
++
++      return 0;
++}
++
++static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
++{
++      struct bcm2835_codec_dev *dev = ctx->dev;
++      unsigned int enable = 1;
++      int ret;
++
++      ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
++                                      "ril.video_decode" : "ril.video_encode",
++                                      &ctx->component);
++      if (ret < 0) {
++              v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
++                       __func__, dev->decode ? "decode" : "encode");
++              return -ENOMEM;
++      }
++
++      vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->input[0],
++                                    MMAL_PARAMETER_ZERO_COPY, &enable,
++                                    sizeof(enable));
++      vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->output[0],
++                                    MMAL_PARAMETER_ZERO_COPY, &enable,
++                                    sizeof(enable));
++
++      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
++                             &ctx->component->input[0]);
++
++      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
++                             &ctx->component->output[0]);
++
++      ret = vchiq_mmal_port_set_format(dev->instance,
++                                       &ctx->component->input[0]);
++      if (ret < 0)
++              goto destroy_component;
++
++      ret = vchiq_mmal_port_set_format(dev->instance,
++                                       &ctx->component->output[0]);
++      if (ret < 0)
++              goto destroy_component;
++
++      if (dev->decode) {
++              if (ctx->q_data[V4L2_M2M_DST].sizeimage <
++                      ctx->component->output[0].minimum_buffer.size)
++                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
++                               ctx->q_data[V4L2_M2M_DST].sizeimage,
++                               ctx->component->output[0].minimum_buffer.size);
++      } else {
++              if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
++                      ctx->component->output[0].minimum_buffer.size)
++                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
++                               ctx->q_data[V4L2_M2M_SRC].sizeimage,
++                               ctx->component->output[0].minimum_buffer.size);
++
++              /* Now we have a component we can set all the ctrls */
++              bcm2835_codec_set_ctrls(ctx);
++      }
++
++      return 0;
++
++destroy_component:
++      vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
++
++      return ret;
++}
++
++/*
++ * Queue operations
++ */
++
++static int bcm2835_codec_queue_setup(struct vb2_queue *vq,
++                                   unsigned int *nbuffers,
++                                   unsigned int *nplanes,
++                                   unsigned int sizes[],
++                                   struct device *alloc_devs[])
++{
++      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vq);
++      struct bcm2835_codec_q_data *q_data;
++      struct vchiq_mmal_port *port;
++      unsigned int size;
++
++      q_data = get_q_data(ctx, vq->type);
++      if (!q_data)
++              return -EINVAL;
++
++      if (!ctx->component)
++              if (bcm2835_codec_create_component(ctx))
++                      return -EINVAL;
++
++      port = get_port_data(ctx, vq->type);
++
++      size = q_data->sizeimage;
++
++      if (*nplanes)
++              return sizes[0] < size ? -EINVAL : 0;
++
++      *nplanes = 1;
++
++      sizes[0] = size;
++      port->current_buffer.size = size;
++
++      if (*nbuffers < port->minimum_buffer.num)
++              *nbuffers = port->minimum_buffer.num;
++      /* Add one buffer to take an EOS */
++      port->current_buffer.num = *nbuffers + 1;
++
++      return 0;
++}
++
++static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
++{
++      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++      struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
++      struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
++                                                 vb);
++      struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
++                                                 m2m);
++
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
++               __func__, ctx, vb);
++      buf->mmal.buffer = vb2_plane_vaddr(&buf->m2m.vb.vb2_buf, 0);
++      buf->mmal.buffer_size = vb2_plane_size(&buf->m2m.vb.vb2_buf, 0);
++
++      mmal_vchi_buffer_init(ctx->dev->instance, &buf->mmal);
++
++      return 0;
++}
++
++static int bcm2835_codec_buf_prepare(struct vb2_buffer *vb)
++{
++      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++      struct bcm2835_codec_q_data *q_data;
++      struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++      struct v4l2_m2m_buffer *m2m = container_of(vbuf, struct v4l2_m2m_buffer,
++                                                 vb);
++      struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
++                                                 m2m);
++      int ret;
++
++      v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
++               __func__, vb->vb2_queue->type, vb);
++
++      q_data = get_q_data(ctx, vb->vb2_queue->type);
++      if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
++              if (vbuf->field == V4L2_FIELD_ANY)
++                      vbuf->field = V4L2_FIELD_NONE;
++              if (vbuf->field != V4L2_FIELD_NONE) {
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s field isn't supported\n",
++                               __func__);
++                      return -EINVAL;
++              }
++      }
++
++      if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
++              v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
++                       __func__, vb2_plane_size(vb, 0),
++                       (long)q_data->sizeimage);
++              return -EINVAL;
++      }
++
++      if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
++              vb2_set_plane_payload(vb, 0, q_data->sizeimage);
++
++      /*
++       * We want to do this at init, but vb2_core_expbuf checks that the
++       * index < q->num_buffers, and q->num_buffers only gets updated once
++       * all the buffers are allocated.
++       */
++      if (!buf->mmal.dma_buf) {
++              ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
++                                           vb->vb2_queue->type, vb->index, 0,
++                                           O_CLOEXEC, &buf->mmal.dma_buf);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
++                               __func__, vb->index, ret);
++      } else {
++              ret = 0;
++      }
++
++      return ret;
++}
++
++static void bcm2835_codec_buf_queue(struct vb2_buffer *vb)
++{
++      struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++
++      v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p vbuf->flags %u, seq %u, bytesused %u\n",
++               __func__, vb->vb2_queue->type, vb, vbuf->flags, vbuf->sequence,
++               vb->planes[0].bytesused);
++      v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
++}
++
++static void bcm2835_codec_buffer_cleanup(struct vb2_buffer *vb)
++{
++      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++      struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
++      struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
++                                                 vb);
++      struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
++                                                 m2m);
++
++      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
++               __func__, ctx, vb);
++
++      mmal_vchi_buffer_cleanup(&buf->mmal);
++
++      if (buf->mmal.dma_buf) {
++              dma_buf_put(buf->mmal.dma_buf);
++              buf->mmal.dma_buf = NULL;
++      }
++}
++
++static int bcm2835_codec_start_streaming(struct vb2_queue *q,
++                                       unsigned int count)
++{
++      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);
++      int ret;
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
++               __func__, q->type, count);
++      q_data->sequence = 0;
++
++      if (!ctx->component_enabled) {
++              ret = vchiq_mmal_component_enable(dev->instance,
++                                                ctx->component);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
++                               __func__, ret);
++              ctx->component_enabled = true;
++      }
++
++      if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
++              /*
++               * Create the EOS buffer.
++               * We only need the MMAL part, and want to NOT attach a memory
++               * buffer to it as it should only take flags.
++               */
++              memset(&q_data->eos_buffer, 0, sizeof(q_data->eos_buffer));
++              mmal_vchi_buffer_init(dev->instance,
++                                    &q_data->eos_buffer.mmal);
++              q_data->eos_buffer_in_use = false;
++
++              ctx->component->input[0].cb_ctx = ctx;
++              ret = vchiq_mmal_port_enable(dev->instance,
++                                           &ctx->component->input[0],
++                                           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;
++              ret = vchiq_mmal_port_enable(dev->instance,
++                                           &ctx->component->output[0],
++                                           op_buffer_cb);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
++                               __func__, ret);
++      }
++      return ret;
++}
++
++static void bcm2835_codec_stop_streaming(struct vb2_queue *q)
++{
++      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);
++      struct vb2_v4l2_buffer *vbuf;
++      struct vb2_v4l2_buffer *vb2;
++      struct v4l2_m2m_buffer *m2m;
++      struct m2m_mmal_buffer *buf;
++      int ret, i;
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n",
++               __func__, q->type);
++
++      init_completion(&ctx->frame_cmplt);
++
++      /* Clear out all buffers held by m2m framework */
++      for (;;) {
++              if (V4L2_TYPE_IS_OUTPUT(q->type))
++                      vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
++              else
++                      vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
++              if (!vbuf)
++                      break;
++              v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: return buffer %p\n",
++                       __func__, vbuf);
++
++              v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
++      }
++
++      /* Disable MMAL port - this will flush buffers back */
++      ret = vchiq_mmal_port_disable(dev->instance, port);
++      if (ret)
++              v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed disabling %s port, ret %d\n",
++                       __func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
++                       ret);
++
++      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);
++              if (ret <= 0) {
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
++                               __func__,
++                               atomic_read(&port->buffers_with_vpu));
++                      break;
++              }
++      }
++
++      /*
++       * 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);
++
++              mmal_vchi_buffer_cleanup(&buf->mmal);
++              if (buf->mmal.dma_buf) {
++                      dma_buf_put(buf->mmal.dma_buf);
++                      buf->mmal.dma_buf = NULL;
++              }
++      }
++
++      /* If both ports disabled, then disable the component */
++      if (!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);
++      }
++
++      if (V4L2_TYPE_IS_OUTPUT(q->type))
++              mmal_vchi_buffer_cleanup(&q_data->eos_buffer.mmal);
++
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: done\n", __func__);
++}
++
++static const struct vb2_ops bcm2835_codec_qops = {
++      .queue_setup     = bcm2835_codec_queue_setup,
++      .buf_init        = bcm2835_codec_buf_init,
++      .buf_prepare     = bcm2835_codec_buf_prepare,
++      .buf_queue       = bcm2835_codec_buf_queue,
++      .buf_cleanup     = bcm2835_codec_buffer_cleanup,
++      .start_streaming = bcm2835_codec_start_streaming,
++      .stop_streaming  = bcm2835_codec_stop_streaming,
++      .wait_prepare    = vb2_ops_wait_prepare,
++      .wait_finish     = vb2_ops_wait_finish,
++};
++
++static int queue_init(void *priv, struct vb2_queue *src_vq,
++                    struct vb2_queue *dst_vq)
++{
++      struct bcm2835_codec_ctx *ctx = priv;
++      int ret;
++
++      src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++      src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
++      src_vq->drv_priv = ctx;
++      src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
++      src_vq->ops = &bcm2835_codec_qops;
++      src_vq->mem_ops = &vb2_dma_contig_memops;
++      src_vq->dev = &ctx->dev->pdev->dev;
++      src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
++      src_vq->lock = &ctx->dev->dev_mutex;
++
++      ret = vb2_queue_init(src_vq);
++      if (ret)
++              return ret;
++
++      dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++      dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
++      dst_vq->drv_priv = ctx;
++      dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
++      dst_vq->ops = &bcm2835_codec_qops;
++      dst_vq->mem_ops = &vb2_dma_contig_memops;
++      dst_vq->dev = &ctx->dev->pdev->dev;
++      dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
++      dst_vq->lock = &ctx->dev->dev_mutex;
++
++      return vb2_queue_init(dst_vq);
++}
++
++/*
++ * File operations
++ */
++static int bcm2835_codec_open(struct file *file)
++{
++      struct bcm2835_codec_dev *dev = video_drvdata(file);
++      struct bcm2835_codec_ctx *ctx = NULL;
++      struct v4l2_ctrl_handler *hdl;
++      int rc = 0;
++
++      v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
++               dev->decode ? "decode" : "encode");
++      if (mutex_lock_interruptible(&dev->dev_mutex)) {
++              v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
++              return -ERESTARTSYS;
++      }
++      ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
++      if (!ctx) {
++              rc = -ENOMEM;
++              goto open_unlock;
++      }
++
++      ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
++      ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
++      if (dev->decode) {
++              /*
++               * Input width and height are irrelevant as they will be defined
++               * by the bitstream not the format. Required by V4L2 though.
++               */
++              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
++              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
++              ctx->q_data[V4L2_M2M_SRC].sizeimage =
++                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
++
++              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
++              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_DST].bytesperline =
++                              get_bytesperline(DEFAULT_WIDTH,
++                                               ctx->q_data[V4L2_M2M_DST].fmt);
++              ctx->q_data[V4L2_M2M_DST].sizeimage =
++                      get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
++                                    ctx->q_data[V4L2_M2M_DST].height,
++                                    ctx->q_data[V4L2_M2M_DST].fmt);
++      } else {
++              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
++              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_SRC].bytesperline =
++                              get_bytesperline(DEFAULT_WIDTH,
++                                               ctx->q_data[V4L2_M2M_SRC].fmt);
++              ctx->q_data[V4L2_M2M_SRC].sizeimage =
++                      get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
++                                    ctx->q_data[V4L2_M2M_SRC].height,
++                                    ctx->q_data[V4L2_M2M_SRC].fmt);
++
++              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
++              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
++              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
++              ctx->q_data[V4L2_M2M_DST].sizeimage =
++                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
++      }
++
++      ctx->colorspace = V4L2_COLORSPACE_REC709;
++      ctx->bitrate = 10 * 1000 * 1000;
++
++      /* Initialise V4L2 contexts */
++      v4l2_fh_init(&ctx->fh, video_devdata(file));
++      file->private_data = &ctx->fh;
++      ctx->dev = dev;
++      hdl = &ctx->hdl;
++      if (!dev->decode) {
++              /* Encode controls */
++              v4l2_ctrl_handler_init(hdl, 6);
++
++              v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
++                                     V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
++                                     V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
++                                     V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
++              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++                                V4L2_CID_MPEG_VIDEO_BITRATE,
++                                25 * 1000, 25 * 1000 * 1000,
++                                25 * 1000, 10 * 1000 * 1000);
++              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++                                V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
++                                0, 1,
++                                1, 0);
++              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++                                V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
++                                0, 0x7FFFFFFF,
++                                1, 60);
++              v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
++                                     V4L2_CID_MPEG_VIDEO_H264_LEVEL,
++                                     V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
++                                     ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
++                                     V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
++              v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
++                                     V4L2_CID_MPEG_VIDEO_H264_PROFILE,
++                                     V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
++                                     ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
++                                       BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
++                                      V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
++              if (hdl->error) {
++                      rc = hdl->error;
++                      goto free_ctrl_handler;
++              }
++              ctx->fh.ctrl_handler = hdl;
++              v4l2_ctrl_handler_setup(hdl);
++      }
++
++      ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
++
++      if (IS_ERR(ctx->fh.m2m_ctx)) {
++              rc = PTR_ERR(ctx->fh.m2m_ctx);
++
++              goto free_ctrl_handler;
++      }
++
++      /* Set both queues as buffered as we have buffering in the VPU. That
++       * means that we will be scheduled whenever either an input or output
++       * buffer is available (otherwise one of each are required).
++       */
++      v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
++      v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
++
++      v4l2_fh_add(&ctx->fh);
++      atomic_inc(&dev->num_inst);
++
++      mutex_unlock(&dev->dev_mutex);
++      return 0;
++
++free_ctrl_handler:
++      v4l2_ctrl_handler_free(hdl);
++      kfree(ctx);
++open_unlock:
++      mutex_unlock(&dev->dev_mutex);
++      return rc;
++}
++
++static int bcm2835_codec_release(struct file *file)
++{
++      struct bcm2835_codec_dev *dev = video_drvdata(file);
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: Releasing instance %p\n",
++               __func__, ctx);
++
++      v4l2_fh_del(&ctx->fh);
++      v4l2_fh_exit(&ctx->fh);
++      v4l2_ctrl_handler_free(&ctx->hdl);
++      mutex_lock(&dev->dev_mutex);
++      v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
++
++      if (ctx->component)
++              vchiq_mmal_component_finalise(dev->instance, ctx->component);
++
++      mutex_unlock(&dev->dev_mutex);
++      kfree(ctx);
++
++      atomic_dec(&dev->num_inst);
++
++      return 0;
++}
++
++static const struct v4l2_file_operations bcm2835_codec_fops = {
++      .owner          = THIS_MODULE,
++      .open           = bcm2835_codec_open,
++      .release        = bcm2835_codec_release,
++      .poll           = v4l2_m2m_fop_poll,
++      .unlocked_ioctl = video_ioctl2,
++      .mmap           = v4l2_m2m_fop_mmap,
++};
++
++static const struct video_device bcm2835_codec_videodev = {
++      .name           = MEM2MEM_NAME,
++      .vfl_dir        = VFL_DIR_M2M,
++      .fops           = &bcm2835_codec_fops,
++      .ioctl_ops      = &bcm2835_codec_ioctl_ops,
++      .minor          = -1,
++      .release        = video_device_release_empty,
++};
++
++static const struct v4l2_m2m_ops m2m_ops = {
++      .device_run     = device_run,
++      .job_ready      = job_ready,
++      .job_abort      = job_abort,
++};
++
++static int bcm2835_codec_create(struct platform_device *pdev,
++                              struct bcm2835_codec_dev **new_dev,
++                              bool decode)
++{
++      struct bcm2835_codec_dev *dev;
++      struct video_device *vfd;
++      struct vchiq_mmal_instance *instance = NULL;
++      int video_nr;
++      int ret;
++
++      dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
++      if (!dev)
++              return -ENOMEM;
++
++      dev->pdev = pdev;
++
++      dev->decode = decode;
++
++      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++      if (ret)
++              return ret;
++
++      atomic_set(&dev->num_inst, 0);
++      mutex_init(&dev->dev_mutex);
++
++      dev->vfd = bcm2835_codec_videodev;
++      vfd = &dev->vfd;
++      vfd->lock = &dev->dev_mutex;
++      vfd->v4l2_dev = &dev->v4l2_dev;
++
++      if (dev->decode) {
++              v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
++              v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
++              video_nr = decode_video_nr;
++      } else {
++              v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
++              v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
++              video_nr = encode_video_nr;
++      }
++
++      ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
++      if (ret) {
++              v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
++              goto unreg_dev;
++      }
++
++      video_set_drvdata(vfd, dev);
++      snprintf(vfd->name, sizeof(vfd->name), "%s",
++               bcm2835_codec_videodev.name);
++      v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
++                vfd->num);
++
++      *new_dev = dev;
++
++      dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
++      if (IS_ERR(dev->m2m_dev)) {
++              v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
++              ret = PTR_ERR(dev->m2m_dev);
++              goto err_m2m;
++      }
++
++      ret = vchiq_mmal_init(&instance);
++      if (ret < 0)
++              goto err_m2m;
++      dev->instance = instance;
++
++      v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
++                dev->decode ? "decode" : "encode");
++      return 0;
++
++err_m2m:
++      v4l2_m2m_release(dev->m2m_dev);
++      video_unregister_device(&dev->vfd);
++unreg_dev:
++      v4l2_device_unregister(&dev->v4l2_dev);
++
++      return ret;
++}
++
++static int bcm2835_codec_destroy(struct bcm2835_codec_dev *dev)
++{
++      if (!dev)
++              return -ENODEV;
++
++      v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
++      v4l2_m2m_release(dev->m2m_dev);
++      video_unregister_device(&dev->vfd);
++      v4l2_device_unregister(&dev->v4l2_dev);
++
++      return 0;
++}
++
++static int bcm2835_codec_probe(struct platform_device *pdev)
++{
++      struct bcm2835_codec_driver *drv;
++      int ret = 0;
++
++      drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
++      if (!drv)
++              return -ENOMEM;
++
++      ret = bcm2835_codec_create(pdev, &drv->encode, false);
++      if (ret)
++              goto out;
++
++      ret = bcm2835_codec_create(pdev, &drv->decode, true);
++      if (ret)
++              goto out;
++
++      platform_set_drvdata(pdev, drv);
++
++      return 0;
++
++out:
++      if (drv->encode) {
++              bcm2835_codec_destroy(drv->encode);
++              drv->encode = NULL;
++      }
++      return ret;
++}
++
++static int bcm2835_codec_remove(struct platform_device *pdev)
++{
++      struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
++
++      bcm2835_codec_destroy(drv->encode);
++
++      bcm2835_codec_destroy(drv->decode);
++
++      return 0;
++}
++
++static struct platform_driver bcm2835_v4l2_codec_driver = {
++      .probe = bcm2835_codec_probe,
++      .remove = bcm2835_codec_remove,
++      .driver = {
++                 .name = "bcm2835-codec",
++                 .owner = THIS_MODULE,
++                 },
++};
++
++module_platform_driver(bcm2835_v4l2_codec_driver);
++
++MODULE_DESCRIPTION("BCM2835 codec V4L2 driver");
++MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.0.1");
++MODULE_ALIAS("platform:bcm2835-codec");
diff --git a/target/linux/brcm2708/patches-4.19/950-0244-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch b/target/linux/brcm2708/patches-4.19/950-0244-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch
deleted file mode 100644 (file)
index 8c69f65..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-From bcb0dccc1f02ed3dd01834ca0e35c4043df8988e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 16:07:55 +0100
-Subject: [PATCH] staging: vc04_services: Use vc-sm-cma to support zero
- copy
-
-With the vc-sm-cma driver we can support zero copy of buffers between
-the kernel and VPU. Add this support to vchiq-mmal.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vchiq-mmal/Kconfig  |  1 +
- .../vc04_services/vchiq-mmal/mmal-common.h    |  4 ++
- .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 66 ++++++++++++++++++-
- .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  1 +
- 4 files changed, 70 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/Kconfig
-+++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
-@@ -2,6 +2,7 @@ config BCM2835_VCHIQ_MMAL
-       tristate "BCM2835 MMAL VCHIQ service"
-       depends on (ARCH_BCM2835 || COMPILE_TEST)
-       select BCM2835_VCHIQ
-+      select BCM_VC_SM_CMA
-       help
-         Enables the MMAL API over VCHIQ as used for the
-         majority of the multimedia services on VideoCore.
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -51,6 +51,10 @@ struct mmal_buffer {
-       struct mmal_msg_context *msg_context;
-+      struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
-+      int vcsm_handle;        /* VCSM handle having imported the dmabuf */
-+      u32 vc_handle;          /* VC handle to that dmabuf */
-+
-       u32 cmd;                /* MMAL command. 0=data. */
-       unsigned long length;
-       u32 mmal_flags;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -27,9 +27,12 @@
- #include <media/videobuf2-vmalloc.h>
- #include "mmal-common.h"
-+#include "mmal-parameters.h"
- #include "mmal-vchiq.h"
- #include "mmal-msg.h"
-+#include "vc-sm-cma/vc_sm_knl.h"
-+
- #define USE_VCHIQ_ARM
- #include "interface/vchi/vchi.h"
-@@ -425,8 +428,13 @@ buffer_from_host(struct vchiq_mmal_insta
-       /* buffer header */
-       m.u.buffer_from_host.buffer_header.cmd = 0;
--      m.u.buffer_from_host.buffer_header.data =
--              (u32)(unsigned long)buf->buffer;
-+      if (port->zero_copy) {
-+              m.u.buffer_from_host.buffer_header.data = buf->vc_handle;
-+      } else {
-+              m.u.buffer_from_host.buffer_header.data =
-+                      (u32)(unsigned long)buf->buffer;
-+      }
-+
-       m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
-       if (port->type == MMAL_PORT_TYPE_OUTPUT) {
-               m.u.buffer_from_host.buffer_header.length = 0;
-@@ -591,6 +599,22 @@ static void buffer_to_host_cb(struct vch
-               msg_context->u.bulk.status = msg->h.status;
-+      } else if (msg->u.buffer_from_host.is_zero_copy) {
-+              /*
-+               * Zero copy buffer, so nothing to do.
-+               * Copy buffer info and make callback.
-+               */
-+              msg_context->u.bulk.buffer_used =
-+                              msg->u.buffer_from_host.buffer_header.length;
-+              msg_context->u.bulk.mmal_flags =
-+                              msg->u.buffer_from_host.buffer_header.flags;
-+              msg_context->u.bulk.dts =
-+                              msg->u.buffer_from_host.buffer_header.dts;
-+              msg_context->u.bulk.pts =
-+                              msg->u.buffer_from_host.buffer_header.pts;
-+              msg_context->u.bulk.cmd =
-+                              msg->u.buffer_from_host.buffer_header.cmd;
-+
-       } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
-               /* empty buffer */
-               if (msg->u.buffer_from_host.buffer_header.flags &
-@@ -1538,6 +1562,9 @@ int vchiq_mmal_port_parameter_set(struct
-       mutex_unlock(&instance->vchiq_mutex);
-+      if (parameter == MMAL_PARAMETER_ZERO_COPY && !ret)
-+              port->zero_copy = !!(*(bool *)value);
-+
-       return ret;
- }
- EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
-@@ -1706,6 +1733,31 @@ int vchiq_mmal_submit_buffer(struct vchi
-       unsigned long flags = 0;
-       int ret;
-+      /*
-+       * We really want to do this in mmal_vchi_buffer_init but can't as
-+       * videobuf2 won't let us have the dmabuf there.
-+       */
-+      if (port->zero_copy && buffer->dma_buf && !buffer->vcsm_handle) {
-+              pr_debug("%s: import dmabuf %p\n", __func__, buffer->dma_buf);
-+              ret = vc_sm_cma_import_dmabuf(buffer->dma_buf,
-+                                            &buffer->vcsm_handle);
-+              if (ret) {
-+                      pr_err("%s: vc_sm_import_dmabuf_fd failed, ret %d\n",
-+                             __func__, ret);
-+                      return ret;
-+              }
-+
-+              buffer->vc_handle = vc_sm_cma_int_handle(buffer->vcsm_handle);
-+              if (!buffer->vc_handle) {
-+                      pr_err("%s: vc_sm_int_handle failed %d\n",
-+                             __func__, ret);
-+                      vc_sm_cma_free(buffer->vcsm_handle);
-+                      return ret;
-+              }
-+              pr_debug("%s: import dmabuf %p - got vc handle %08X\n",
-+                       __func__, buffer->dma_buf, buffer->vc_handle);
-+      }
-+
-       ret = buffer_from_host(instance, port, buffer);
-       if (ret == -EINVAL) {
-               /* Port is disabled. Queue for when it is enabled. */
-@@ -1739,6 +1791,16 @@ int mmal_vchi_buffer_cleanup(struct mmal
-               release_msg_context(msg_context);
-       buf->msg_context = NULL;
-+      if (buf->vcsm_handle) {
-+              int ret;
-+
-+              pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
-+                       buf->vcsm_handle);
-+              ret = vc_sm_cma_free(buf->vcsm_handle);
-+              if (ret)
-+                      pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
-+              buf->vcsm_handle = 0;
-+      }
-       return 0;
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -49,6 +49,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
- struct vchiq_mmal_port {
-       u32 enabled:1;
-+      u32 zero_copy:1;
-       u32 handle;
-       u32 type; /* port type, cached to use on port info set */
-       u32 index; /* port index, cached to use on port info set */
diff --git a/target/linux/brcm2708/patches-4.19/950-0245-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch b/target/linux/brcm2708/patches-4.19/950-0245-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch
deleted file mode 100644 (file)
index fbaa3c2..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-From 0b2a62596d0e6efe17bb87a3a5ebd91cee60c64b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 17:57:45 +0000
-Subject: [PATCH] media: videobuf2: Allow exporting of a struct dmabuf
-
-videobuf2 only allowed exporting a dmabuf as a file descriptor,
-but there are instances where having the struct dma_buf is
-useful within the kernel.
-
-Split the current implementation into two, one step which
-exports a struct dma_buf, and the second which converts that
-into an fd.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/common/videobuf2/videobuf2-core.c   | 21 ++++++++++++++++---
- include/media/videobuf2-core.h                | 15 +++++++++++++
- 2 files changed, 33 insertions(+), 3 deletions(-)
-
---- a/drivers/media/common/videobuf2/videobuf2-core.c
-+++ b/drivers/media/common/videobuf2/videobuf2-core.c
-@@ -1851,12 +1851,12 @@ static int __find_plane_by_offset(struct
-       return -EINVAL;
- }
--int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
--              unsigned int index, unsigned int plane, unsigned int flags)
-+int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
-+                         unsigned int index, unsigned int plane,
-+                         unsigned int flags, struct dma_buf **dmabuf)
- {
-       struct vb2_buffer *vb = NULL;
-       struct vb2_plane *vb_plane;
--      int ret;
-       struct dma_buf *dbuf;
-       if (q->memory != VB2_MEMORY_MMAP) {
-@@ -1906,6 +1906,21 @@ int vb2_core_expbuf(struct vb2_queue *q,
-               return -EINVAL;
-       }
-+      *dmabuf = dbuf;
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(vb2_core_expbuf_dmabuf);
-+
-+int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
-+                  unsigned int index, unsigned int plane, unsigned int flags)
-+{
-+      struct dma_buf *dbuf;
-+      int ret;
-+
-+      ret = vb2_core_expbuf_dmabuf(q, type, index, plane, flags, &dbuf);
-+      if (ret)
-+              return ret;
-+
-       ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
-       if (ret < 0) {
-               dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
---- a/include/media/videobuf2-core.h
-+++ b/include/media/videobuf2-core.h
-@@ -825,6 +825,21 @@ int vb2_core_streamon(struct vb2_queue *
- int vb2_core_streamoff(struct vb2_queue *q, unsigned int type);
- /**
-+ * vb2_core_expbuf_dmabuf() - Export a buffer as a dma_buf structure
-+ * @q:         videobuf2 queue
-+ * @type:      buffer type
-+ * @index:     id number of the buffer
-+ * @plane:     index of the plane to be exported, 0 for single plane queues
-+ * @flags:     flags for newly created file, currently only O_CLOEXEC is
-+ *             supported, refer to manual of open syscall for more details
-+ * @dmabuf:    Returns the dmabuf pointer
-+ *
-+ */
-+int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
-+                         unsigned int index, unsigned int plane,
-+                         unsigned int flags, struct dma_buf **dmabuf);
-+
-+/**
-  * vb2_core_expbuf() - Export a buffer as a file descriptor.
-  * @q:                pointer to &struct vb2_queue with videobuf2 queue.
-  * @fd:               pointer to the file descriptor associated with DMABUF
diff --git a/target/linux/brcm2708/patches-4.19/950-0245-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch b/target/linux/brcm2708/patches-4.19/950-0245-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch
new file mode 100644 (file)
index 0000000..51cc4a4
--- /dev/null
@@ -0,0 +1,34 @@
+From b28dac3003b4c756b72201bb1d83647e33e2f4f1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 26 Oct 2018 15:14:16 +0100
+Subject: [PATCH] staging: vchiq_arm: Register bcm2835-codec as a
+ platform driver
+
+Following the same pattern as bcm2835-camera and bcm2835-audio,
+register the V4L2 codec driver as a platform driver
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -170,6 +170,7 @@ static struct class  *vchiq_class;
+ static struct device *vchiq_dev;
+ static DEFINE_SPINLOCK(msg_queue_spinlock);
+ static struct platform_device *bcm2835_camera;
++static struct platform_device *bcm2835_codec;
+ static const char *const ioctl_names[] = {
+       "CONNECT",
+@@ -3656,6 +3657,9 @@ static int vchiq_probe(struct platform_d
+       bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
+       if (IS_ERR(bcm2835_camera))
+               bcm2835_camera = NULL;
++      bcm2835_codec = vchiq_register_child(pdev, "bcm2835-codec");
++      if (IS_ERR(bcm2835_codec))
++              bcm2835_codec = NULL;
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0246-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch b/target/linux/brcm2708/patches-4.19/950-0246-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch
deleted file mode 100644 (file)
index 0a6552b..0000000
+++ /dev/null
@@ -1,2467 +0,0 @@
-From 2758fab4321519446fe5444769b6257dd18e794b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 14:53:49 +0100
-Subject: [PATCH] staging: vc04_services: Add a V4L2 M2M codec driver
-
-This adds a V4L2 memory to memory device that wraps the MMAL
-video decode and video_encode components for H264 and MJPEG encode
-and decode, MPEG4, H263, and VP8 decode (and MPEG2 decode
-if the appropriate licence has been purchased).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/Kconfig         |    1 +
- drivers/staging/vc04_services/Makefile        |    9 +-
- .../vc04_services/bcm2835-codec/Kconfig       |   11 +
- .../vc04_services/bcm2835-codec/Makefile      |    8 +
- .../staging/vc04_services/bcm2835-codec/TODO  |   24 +
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 2359 +++++++++++++++++
- 6 files changed, 2408 insertions(+), 4 deletions(-)
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Kconfig
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Makefile
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/TODO
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-
---- a/drivers/staging/vc04_services/Kconfig
-+++ b/drivers/staging/vc04_services/Kconfig
-@@ -23,6 +23,7 @@ source "drivers/staging/vc04_services/bc
- source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
- source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
- source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
-+source "drivers/staging/vc04_services/bcm2835-codec/Kconfig"
- endif
---- a/drivers/staging/vc04_services/Makefile
-+++ b/drivers/staging/vc04_services/Makefile
-@@ -10,10 +10,11 @@ vchiq-objs := \
-    interface/vchiq_arm/vchiq_util.o \
-    interface/vchiq_arm/vchiq_connected.o \
--obj-$(CONFIG_SND_BCM2835)     += bcm2835-audio/
--obj-$(CONFIG_VIDEO_BCM2835)   += bcm2835-camera/
--obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
--obj-$(CONFIG_BCM_VC_SM_CMA)   += vc-sm-cma/
-+obj-$(CONFIG_SND_BCM2835)             += bcm2835-audio/
-+obj-$(CONFIG_VIDEO_BCM2835)           += bcm2835-camera/
-+obj-$(CONFIG_BCM2835_VCHIQ_MMAL)      += vchiq-mmal/
-+obj-$(CONFIG_BCM_VC_SM_CMA)           += vc-sm-cma/
-+obj-$(CONFIG_VIDEO_CODEC_BCM2835)     += bcm2835-codec/
- ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
-@@ -0,0 +1,11 @@
-+config VIDEO_CODEC_BCM2835
-+      tristate "BCM2835 Video codec support"
-+      depends on MEDIA_SUPPORT
-+      depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
-+      select BCM2835_VCHIQ_MMAL
-+      select VIDEOBUF2_DMA_CONTIG
-+      select V4L2_MEM2MEM_DEV
-+      help
-+        Say Y here to enable the V4L2 video codecs for
-+        Broadcom BCM2835 SoC. This operates over the VCHIQ interface
-+        to a service running on VideoCore.
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/Makefile
-@@ -0,0 +1,8 @@
-+# SPDX-License-Identifier: GPL-2.0
-+bcm2835-codec-objs := bcm2835-v4l2-codec.o
-+
-+obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec.o
-+
-+ccflags-y += \
-+      -Idrivers/staging/vc04_services \
-+      -D__VCCOREVER__=0x04000000
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/TODO
-@@ -0,0 +1,24 @@
-+1) Convert to be a platform driver.
-+
-+Right now when the module probes, it tries to initialize VCHI and
-+errors out if it wasn't ready yet.  If bcm2835-v4l2 was built in, then
-+VCHI generally isn't ready because it depends on both the firmware and
-+mailbox drivers having already loaded.
-+
-+We should have VCHI create a platform device once it's initialized,
-+and have this driver bind to it, so that we automatically load the
-+v4l2 module after VCHI loads.
-+
-+2) Support SELECTION API to define crop region on the image for encode.
-+
-+Particularly for resolutions that aren't a multiple of the macroblock
-+size, the codec will report a resolution that is a multiple of the macroblock
-+size (it has to have the memory to decode into), and then a different crop
-+region within that buffer.
-+The most common example is 1080P, where the buffer will be 1920x1088 with a
-+crop region of 1920x1080.
-+
-+3) Refactor so that the component creation is only on queue_setup, not open.
-+
-+Fixes v4l2-compliance failure on trying to open 100 instances of the
-+device.
-\ No newline at end of file
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -0,0 +1,2359 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+/*
-+ * A v4l2-mem2mem device that wraps the video codec MMAL component.
-+ *
-+ * Copyright 2018 Raspberry Pi (Trading) Ltd.
-+ * Author: Dave Stevenson (dave.stevenson@raspberrypi.org)
-+ *
-+ * Loosely based on the vim2m virtual driver by Pawel Osciak
-+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
-+ * Pawel Osciak, <pawel@osciak.com>
-+ * Marek Szyprowski, <m.szyprowski@samsung.com>
-+ *
-+ * Whilst this driver uses the v4l2_mem2mem framework, it does not need the
-+ * scheduling aspects, so will always take the buffers, pass them to the VPU,
-+ * and then signal the job as complete.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the
-+ * License, or (at your option) any later version
-+ */
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/fs.h>
-+#include <linux/timer.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/platform_device.h>
-+#include <linux/syscalls.h>
-+
-+#include <media/v4l2-mem2mem.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-ioctl.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-event.h>
-+#include <media/videobuf2-dma-contig.h>
-+
-+#include "vchiq-mmal/mmal-encodings.h"
-+#include "vchiq-mmal/mmal-msg.h"
-+#include "vchiq-mmal/mmal-parameters.h"
-+#include "vchiq-mmal/mmal-vchiq.h"
-+
-+/*
-+ * Default /dev/videoN node numbers for decode and encode.
-+ * Deliberately avoid the very low numbers as these are often taken by webcams
-+ * etc, and simple apps tend to only go for /dev/video0.
-+ */
-+static int decode_video_nr = 10;
-+module_param(decode_video_nr, int, 0644);
-+MODULE_PARM_DESC(decode_video_nr, "decoder video device number");
-+
-+static int encode_video_nr = 11;
-+module_param(encode_video_nr, int, 0644);
-+MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
-+
-+static unsigned int debug;
-+module_param(debug, uint, 0644);
-+MODULE_PARM_DESC(debug, "activates debug info (0-3)");
-+
-+#define MIN_W         32
-+#define MIN_H         32
-+#define MAX_W         1920
-+#define MAX_H         1088
-+#define BPL_ALIGN     32
-+#define DEFAULT_WIDTH 640
-+#define DEFAULT_HEIGHT        480
-+/*
-+ * The unanswered question - what is the maximum size of a compressed frame?
-+ * V4L2 mandates that the encoded frame must fit in a single buffer. Sizing
-+ * that buffer is a compromise between wasting memory and risking not fitting.
-+ * The 1080P version of Big Buck Bunny has some frames that exceed 512kB.
-+ * Adopt a moderately arbitrary split at 720P for switching between 512 and
-+ * 768kB buffers.
-+ */
-+#define DEF_COMP_BUF_SIZE_GREATER_720P        (768 << 10)
-+#define DEF_COMP_BUF_SIZE_720P_OR_LESS        (512 << 10)
-+
-+/* Flags that indicate a format can be used for capture/output */
-+#define MEM2MEM_CAPTURE               BIT(0)
-+#define MEM2MEM_OUTPUT                BIT(1)
-+
-+#define MEM2MEM_NAME          "bcm2835-codec"
-+
-+struct bcm2835_codec_fmt {
-+      u32     fourcc;
-+      int     depth;
-+      int     bytesperline_align;
-+      u32     flags;
-+      u32     mmal_fmt;
-+      bool    decode_only;
-+      bool    encode_only;
-+      int     size_multiplier_x2;
-+};
-+
-+/* Supported raw pixel formats. Those supported for both encode and decode
-+ * must come first, with those only supported for decode coming after (there
-+ * are no formats supported for encode only).
-+ */
-+static struct bcm2835_codec_fmt raw_formats[] = {
-+      {
-+              .fourcc                 = V4L2_PIX_FMT_YUV420,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_I420,
-+              .size_multiplier_x2     = 3,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_YVU420,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_YV12,
-+              .size_multiplier_x2     = 3,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_NV12,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_NV12,
-+              .size_multiplier_x2     = 3,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_NV21,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_NV21,
-+              .size_multiplier_x2     = 3,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_RGB565,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_RGB16,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_YUYV,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_YUYV,
-+              .encode_only            = true,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_UYVY,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_UYVY,
-+              .encode_only            = true,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_YVYU,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_YVYU,
-+              .encode_only            = true,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_VYUY,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_VYUY,
-+              .encode_only            = true,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_RGB24,
-+              .depth                  = 24,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_RGB24,
-+              .encode_only            = true,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_BGR24,
-+              .depth                  = 24,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BGR24,
-+              .encode_only            = true,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_BGR32,
-+              .depth                  = 32,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BGRA,
-+              .encode_only            = true,
-+              .size_multiplier_x2     = 2,
-+      },
-+};
-+
-+/* Supported encoded formats. Those supported for both encode and decode
-+ * must come first, with those only supported for decode coming after (there
-+ * are no formats supported for encode only).
-+ */
-+static struct bcm2835_codec_fmt encoded_formats[] = {
-+      {
-+              .fourcc                 = V4L2_PIX_FMT_H264,
-+              .depth                  = 0,
-+              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-+              .mmal_fmt               = MMAL_ENCODING_H264,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_MJPEG,
-+              .depth                  = 0,
-+              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-+              .mmal_fmt               = MMAL_ENCODING_MJPEG,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_MPEG4,
-+              .depth                  = 0,
-+              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-+              .mmal_fmt               = MMAL_ENCODING_MP4V,
-+              .decode_only            = true,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_H263,
-+              .depth                  = 0,
-+              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-+              .mmal_fmt               = MMAL_ENCODING_H263,
-+              .decode_only            = true,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_MPEG2,
-+              .depth                  = 0,
-+              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-+              .mmal_fmt               = MMAL_ENCODING_MP2V,
-+              .decode_only            = true,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_VP8,
-+              .depth                  = 0,
-+              .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-+              .mmal_fmt               = MMAL_ENCODING_VP8,
-+              .decode_only            = true,
-+      },
-+      /*
-+       * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
-+       * support them.
-+       */
-+};
-+
-+struct bcm2835_codec_fmt_list {
-+      struct bcm2835_codec_fmt *list;
-+      unsigned int num_entries;
-+};
-+
-+#define RAW_LIST      0
-+#define ENCODED_LIST  1
-+
-+struct bcm2835_codec_fmt_list formats[] = {
-+      {
-+              .list = raw_formats,
-+              .num_entries = ARRAY_SIZE(raw_formats),
-+      }, {
-+              .list = encoded_formats,
-+              .num_entries = ARRAY_SIZE(encoded_formats),
-+      },
-+};
-+
-+struct m2m_mmal_buffer {
-+      struct v4l2_m2m_buffer  m2m;
-+      struct mmal_buffer      mmal;
-+};
-+
-+/* Per-queue, driver-specific private data */
-+struct bcm2835_codec_q_data {
-+      /*
-+       * These parameters should be treated as gospel, with everything else
-+       * being determined from them.
-+       */
-+      /* Buffer width/height */
-+      unsigned int            bytesperline;
-+      unsigned int            height;
-+      /* Crop size used for selection handling */
-+      unsigned int            crop_width;
-+      unsigned int            crop_height;
-+      bool                    selection_set;
-+
-+      unsigned int            sizeimage;
-+      unsigned int            sequence;
-+      struct bcm2835_codec_fmt        *fmt;
-+
-+      /* One extra buffer header so we can send an EOS. */
-+      struct m2m_mmal_buffer  eos_buffer;
-+      bool                    eos_buffer_in_use;      /* debug only */
-+};
-+
-+enum {
-+      V4L2_M2M_SRC = 0,
-+      V4L2_M2M_DST = 1,
-+};
-+
-+static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
-+                                                           bool capture)
-+{
-+      return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
-+}
-+
-+static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
-+{
-+      return &get_format_list(decode, capture)->list[0];
-+}
-+
-+static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
-+                                           bool capture)
-+{
-+      struct bcm2835_codec_fmt *fmt;
-+      unsigned int k;
-+      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
-+
-+      for (k = 0; k < fmts->num_entries; k++) {
-+              fmt = &fmts->list[k];
-+              if (fmt->fourcc == f->fmt.pix.pixelformat)
-+                      break;
-+      }
-+
-+      /*
-+       * Some compressed formats are only supported for decoding, not
-+       * encoding.
-+       */
-+      if (!decode && fmts->list[k].decode_only)
-+              return NULL;
-+
-+      /* Some pixel formats are only supported for encoding, not decoding. */
-+      if (decode && fmts->list[k].encode_only)
-+              return NULL;
-+
-+      if (k == fmts->num_entries)
-+              return NULL;
-+
-+      return &fmts->list[k];
-+}
-+
-+struct bcm2835_codec_dev {
-+      struct platform_device *pdev;
-+
-+      /* v4l2 devices */
-+      struct v4l2_device      v4l2_dev;
-+      struct video_device     vfd;
-+      /* mutex for the v4l2 device */
-+      struct mutex            dev_mutex;
-+      atomic_t                num_inst;
-+
-+      /* allocated mmal instance and components */
-+      bool                    decode;  /* Is this instance a decoder? */
-+      struct vchiq_mmal_instance      *instance;
-+
-+      struct v4l2_m2m_dev     *m2m_dev;
-+};
-+
-+struct bcm2835_codec_ctx {
-+      struct v4l2_fh          fh;
-+      struct bcm2835_codec_dev        *dev;
-+
-+      struct v4l2_ctrl_handler hdl;
-+
-+      struct vchiq_mmal_component  *component;
-+      bool component_enabled;
-+
-+      enum v4l2_colorspace    colorspace;
-+      enum v4l2_ycbcr_encoding ycbcr_enc;
-+      enum v4l2_xfer_func     xfer_func;
-+      enum v4l2_quantization  quant;
-+
-+      /* Source and destination queue data */
-+      struct bcm2835_codec_q_data   q_data[2];
-+      s32  bitrate;
-+
-+      bool aborting;
-+      int num_ip_buffers;
-+      int num_op_buffers;
-+      struct completion frame_cmplt;
-+};
-+
-+struct bcm2835_codec_driver {
-+      struct bcm2835_codec_dev *encode;
-+      struct bcm2835_codec_dev *decode;
-+};
-+
-+static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
-+{
-+      return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
-+}
-+
-+static struct bcm2835_codec_q_data *get_q_data(struct bcm2835_codec_ctx *ctx,
-+                                             enum v4l2_buf_type type)
-+{
-+      switch (type) {
-+      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+              return &ctx->q_data[V4L2_M2M_SRC];
-+      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+              return &ctx->q_data[V4L2_M2M_DST];
-+      default:
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
-+                       __func__, type);
-+              break;
-+      }
-+      return NULL;
-+}
-+
-+static struct vchiq_mmal_port *get_port_data(struct bcm2835_codec_ctx *ctx,
-+                                           enum v4l2_buf_type type)
-+{
-+      if (!ctx->component)
-+              return NULL;
-+
-+      switch (type) {
-+      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+              return &ctx->component->input[0];
-+      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+              return &ctx->component->output[0];
-+      default:
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
-+                       __func__, type);
-+              break;
-+      }
-+      return NULL;
-+}
-+
-+/*
-+ * mem2mem callbacks
-+ */
-+
-+/**
-+ * job_ready() - check whether an instance is ready to be scheduled to run
-+ */
-+static int job_ready(void *priv)
-+{
-+      struct bcm2835_codec_ctx *ctx = priv;
-+
-+      if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
-+          !v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx))
-+              return 0;
-+
-+      return 1;
-+}
-+
-+static void job_abort(void *priv)
-+{
-+      struct bcm2835_codec_ctx *ctx = priv;
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s\n", __func__);
-+      /* Will cancel the transaction in the next interrupt handler */
-+      ctx->aborting = 1;
-+}
-+
-+static inline unsigned int get_sizeimage(int bpl, int height,
-+                                       struct bcm2835_codec_fmt *fmt)
-+{
-+      return (bpl * height * fmt->size_multiplier_x2) >> 1;
-+}
-+
-+static inline unsigned int get_bytesperline(int width,
-+                                          struct bcm2835_codec_fmt *fmt)
-+{
-+      return ALIGN((width * fmt->depth) >> 3, fmt->bytesperline_align);
-+}
-+
-+static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
-+                                 bool decode,
-+                                 struct bcm2835_codec_q_data *q_data,
-+                                 struct vchiq_mmal_port *port)
-+{
-+      port->format.encoding = q_data->fmt->mmal_fmt;
-+
-+      if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
-+              /* Raw image format - set width/height */
-+              port->es.video.width = q_data->bytesperline /
-+                                              (q_data->fmt->depth >> 3);
-+              port->es.video.height = q_data->height;
-+              port->es.video.crop.width = q_data->crop_width;
-+              port->es.video.crop.height = q_data->crop_height;
-+              port->es.video.frame_rate.num = 0;
-+              port->es.video.frame_rate.den = 1;
-+      } else {
-+              /* Compressed format - leave resolution as 0 for decode */
-+              if (decode) {
-+                      port->es.video.width = 0;
-+                      port->es.video.height = 0;
-+                      port->es.video.crop.width = 0;
-+                      port->es.video.crop.height = 0;
-+              } else {
-+                      port->es.video.width = q_data->crop_width;
-+                      port->es.video.height = q_data->height;
-+                      port->es.video.crop.width = q_data->crop_width;
-+                      port->es.video.crop.height = q_data->crop_height;
-+                      port->format.bitrate = ctx->bitrate;
-+              }
-+              port->es.video.frame_rate.num = 0;
-+              port->es.video.frame_rate.den = 1;
-+      }
-+      port->es.video.crop.x = 0;
-+      port->es.video.crop.y = 0;
-+
-+      port->current_buffer.size = q_data->sizeimage;
-+};
-+
-+static void ip_buffer_cb(struct vchiq_mmal_instance *instance,
-+                       struct vchiq_mmal_port *port, int status,
-+                       struct mmal_buffer *mmal_buf)
-+{
-+      struct bcm2835_codec_ctx *ctx = port->cb_ctx/*, *curr_ctx*/;
-+      struct m2m_mmal_buffer *buf =
-+                      container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
-+
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: port %p buf %p length %lu, flags %x\n",
-+               __func__, port, mmal_buf, mmal_buf->length,
-+               mmal_buf->mmal_flags);
-+
-+      if (buf == &ctx->q_data[V4L2_M2M_SRC].eos_buffer) {
-+              /* Do we need to add lcoking to prevent multiple submission of
-+               * the EOS, and therefore handle mutliple return here?
-+               */
-+              v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: eos buffer returned.\n",
-+                       __func__);
-+              ctx->q_data[V4L2_M2M_SRC].eos_buffer_in_use = false;
-+              return;
-+      }
-+
-+      if (status) {
-+              /* error in transfer */
-+              if (buf)
-+                      /* there was a buffer with the error so return it */
-+                      vb2_buffer_done(&buf->m2m.vb.vb2_buf,
-+                                      VB2_BUF_STATE_ERROR);
-+              return;
-+      }
-+      if (mmal_buf->cmd) {
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s: Not expecting cmd msgs on ip callback - %08x\n",
-+                       __func__, mmal_buf->cmd);
-+              /*
-+               * CHECKME: Should we return here. The buffer shouldn't have a
-+               * message context or vb2 buf associated.
-+               */
-+      }
-+
-+      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: no error. Return buffer %p\n",
-+               __func__, &buf->m2m.vb.vb2_buf);
-+      vb2_buffer_done(&buf->m2m.vb.vb2_buf, VB2_BUF_STATE_DONE);
-+
-+      ctx->num_ip_buffers++;
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d input buffers\n",
-+               __func__, ctx->num_ip_buffers);
-+
-+      if (!port->enabled)
-+              complete(&ctx->frame_cmplt);
-+}
-+
-+static void queue_res_chg_event(struct bcm2835_codec_ctx *ctx)
-+{
-+      static const struct v4l2_event ev_src_ch = {
-+              .type = V4L2_EVENT_SOURCE_CHANGE,
-+              .u.src_change.changes =
-+              V4L2_EVENT_SRC_CH_RESOLUTION,
-+      };
-+
-+      v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
-+}
-+
-+static void send_eos_event(struct bcm2835_codec_ctx *ctx)
-+{
-+      static const struct v4l2_event ev = {
-+              .type = V4L2_EVENT_EOS,
-+      };
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Sending EOS event\n");
-+
-+      v4l2_event_queue_fh(&ctx->fh, &ev);
-+}
-+
-+static void color_mmal2v4l(struct bcm2835_codec_ctx *ctx, u32 mmal_color_space)
-+{
-+      switch (mmal_color_space) {
-+      case MMAL_COLOR_SPACE_ITUR_BT601:
-+              ctx->colorspace = V4L2_COLORSPACE_REC709;
-+              ctx->xfer_func = V4L2_XFER_FUNC_709;
-+              ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
-+              ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
-+              break;
-+
-+      case MMAL_COLOR_SPACE_ITUR_BT709:
-+              ctx->colorspace = V4L2_COLORSPACE_REC709;
-+              ctx->xfer_func = V4L2_XFER_FUNC_709;
-+              ctx->ycbcr_enc = V4L2_YCBCR_ENC_709;
-+              ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
-+              break;
-+      }
-+}
-+
-+static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
-+                             struct mmal_buffer *mmal_buf)
-+{
-+      struct bcm2835_codec_q_data *q_data;
-+      struct mmal_msg_event_format_changed *format =
-+              (struct mmal_msg_event_format_changed *)mmal_buf->buffer;
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
-+               __func__,
-+               format->buffer_size_min,
-+               format->buffer_size_recommended,
-+               format->buffer_num_min,
-+               format->buffer_num_recommended
-+              );
-+      if (format->format.type != MMAL_ES_TYPE_VIDEO) {
-+              v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed but not video %u\n",
-+                       __func__, format->format.type);
-+              return;
-+      }
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed to %ux%u, crop %ux%u, colourspace %08X\n",
-+               __func__, format->es.video.width, format->es.video.height,
-+               format->es.video.crop.width, format->es.video.crop.height,
-+               format->es.video.color_space);
-+
-+      q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-+      q_data->crop_width = format->es.video.crop.width;
-+      q_data->crop_height = format->es.video.crop.height;
-+      q_data->bytesperline = format->es.video.crop.width;
-+      q_data->height = format->es.video.height;
-+      q_data->sizeimage = format->buffer_size_min;
-+      if (format->es.video.color_space)
-+              color_mmal2v4l(ctx, format->es.video.color_space);
-+
-+      queue_res_chg_event(ctx);
-+}
-+
-+static void op_buffer_cb(struct vchiq_mmal_instance *instance,
-+                       struct vchiq_mmal_port *port, int status,
-+                       struct mmal_buffer *mmal_buf)
-+{
-+      struct bcm2835_codec_ctx *ctx = port->cb_ctx;
-+      struct m2m_mmal_buffer *buf;
-+      struct vb2_v4l2_buffer *vb2;
-+
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev,
-+               "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
-+               __func__, status, mmal_buf, mmal_buf->length,
-+               mmal_buf->mmal_flags, mmal_buf->pts);
-+
-+      if (status) {
-+              /* error in transfer */
-+              if (vb2) {
-+                      /* there was a buffer with the error so return it */
-+                      vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
-+              }
-+              return;
-+      }
-+
-+      if (mmal_buf->cmd) {
-+              switch (mmal_buf->cmd) {
-+              case MMAL_EVENT_FORMAT_CHANGED:
-+              {
-+                      handle_fmt_changed(ctx, mmal_buf);
-+                      break;
-+              }
-+              default:
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Unexpected event on output callback - %08x\n",
-+                               __func__, mmal_buf->cmd);
-+                      break;
-+              }
-+              return;
-+      }
-+
-+      buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
-+      vb2 = &buf->m2m.vb;
-+
-+      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
-+               __func__, mmal_buf->length, mmal_buf->mmal_flags,
-+               vb2->vb2_buf.index);
-+
-+      if (mmal_buf->length == 0) {
-+              /* stream ended, or buffer being returned during disable. */
-+              v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: Empty buffer - flags %04x",
-+                       __func__, mmal_buf->mmal_flags);
-+              if (!mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
-+                      vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
-+                      if (!port->enabled)
-+                              complete(&ctx->frame_cmplt);
-+                      return;
-+              }
-+      }
-+      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
-+              /* EOS packet from the VPU */
-+              send_eos_event(ctx);
-+              vb2->flags |= V4L2_BUF_FLAG_LAST;
-+      }
-+
-+      vb2->vb2_buf.timestamp = mmal_buf->pts;
-+
-+      vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
-+      if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-+              vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
-+
-+      vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_DONE);
-+      ctx->num_op_buffers++;
-+
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d output buffers\n",
-+               __func__, ctx->num_op_buffers);
-+
-+      if (!port->enabled)
-+              complete(&ctx->frame_cmplt);
-+}
-+
-+/* vb2_to_mmal_buffer() - converts vb2 buffer header to MMAL
-+ *
-+ * Copies all the required fields from a VB2 buffer to the MMAL buffer header,
-+ * ready for sending to the VPU.
-+ */
-+static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
-+                             struct vb2_v4l2_buffer *vb2)
-+{
-+      buf->mmal.mmal_flags = 0;
-+      if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
-+              buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
-+
-+      /*
-+       * Adding this means that the data must be framed correctly as one frame
-+       * per buffer. The underlying decoder has no such requirement, but it
-+       * will reduce latency as the bistream parser will be kicked immediately
-+       * to parse the frame, rather than relying on its own heuristics for
-+       * when to wake up.
-+       */
-+      buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
-+
-+      buf->mmal.length = vb2->vb2_buf.planes[0].bytesused;
-+      /*
-+       * Minor ambiguity in the V4L2 spec as to whether passing in a 0 length
-+       * buffer, or one with V4L2_BUF_FLAG_LAST set denotes end of stream.
-+       * Handle either.
-+       */
-+      if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
-+              buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
-+
-+      buf->mmal.pts = vb2->vb2_buf.timestamp;
-+      buf->mmal.dts = MMAL_TIME_UNKNOWN;
-+}
-+
-+/* device_run() - prepares and starts the device
-+ *
-+ * This simulates all the immediate preparations required before starting
-+ * a device. This will be called by the framework when it decides to schedule
-+ * a particular instance.
-+ */
-+static void device_run(void *priv)
-+{
-+      struct bcm2835_codec_ctx *ctx = priv;
-+      struct bcm2835_codec_dev *dev = ctx->dev;
-+      struct vb2_v4l2_buffer *src_buf, *dst_buf;
-+      struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
-+      struct v4l2_m2m_buffer *m2m;
-+      int ret;
-+
-+      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: off we go\n", __func__);
-+
-+      src_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->out_q_ctx);
-+      if (src_buf) {
-+              m2m = container_of(src_buf, struct v4l2_m2m_buffer, vb);
-+              src_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
-+              vb2_to_mmal_buffer(src_m2m_buf, src_buf);
-+
-+              ret = vchiq_mmal_submit_buffer(dev->instance,
-+                                             &ctx->component->input[0],
-+                                             &src_m2m_buf->mmal);
-+              v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted ip buffer len %lu, pts %llu, flags %04x\n",
-+                       __func__, src_m2m_buf->mmal.length,
-+                       src_m2m_buf->mmal.pts, src_m2m_buf->mmal.mmal_flags);
-+              if (ret)
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting ip buffer\n",
-+                               __func__);
-+      }
-+
-+      dst_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->cap_q_ctx);
-+      if (dst_buf) {
-+              m2m = container_of(dst_buf, struct v4l2_m2m_buffer, vb);
-+              dst_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
-+              vb2_to_mmal_buffer(dst_m2m_buf, dst_buf);
-+
-+              ret = vchiq_mmal_submit_buffer(dev->instance,
-+                                             &ctx->component->output[0],
-+                                             &dst_m2m_buf->mmal);
-+              if (ret)
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting op buffer\n",
-+                               __func__);
-+      }
-+
-+      v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted src %p, dst %p\n",
-+               __func__, src_m2m_buf, dst_m2m_buf);
-+
-+      /* Complete the job here. */
-+      v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
-+}
-+
-+/*
-+ * video ioctls
-+ */
-+static int vidioc_querycap(struct file *file, void *priv,
-+                         struct v4l2_capability *cap)
-+{
-+      strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
-+      strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-+      snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-+               MEM2MEM_NAME);
-+      cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
-+      cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-+      return 0;
-+}
-+
-+static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
-+{
-+      struct bcm2835_codec_fmt *fmt;
-+      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
-+
-+      if (f->index < fmts->num_entries) {
-+              /* Format found */
-+              /* Check format isn't a decode only format when encoding */
-+              if (!decode &&
-+                  fmts->list[f->index].decode_only)
-+                      return -EINVAL;
-+              /* Check format isn't a decode only format when encoding */
-+              if (decode &&
-+                  fmts->list[f->index].encode_only)
-+                      return -EINVAL;
-+
-+              fmt = &fmts->list[f->index];
-+              f->pixelformat = fmt->fourcc;
-+              f->flags = fmt->flags;
-+              return 0;
-+      }
-+
-+      /* Format not found */
-+      return -EINVAL;
-+}
-+
-+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-+                                 struct v4l2_fmtdesc *f)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      return enum_fmt(f, ctx->dev->decode, true);
-+}
-+
-+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
-+                                 struct v4l2_fmtdesc *f)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      return enum_fmt(f, ctx->dev->decode, false);
-+}
-+
-+static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
-+{
-+      struct vb2_queue *vq;
-+      struct bcm2835_codec_q_data *q_data;
-+
-+      vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-+      if (!vq)
-+              return -EINVAL;
-+
-+      q_data = get_q_data(ctx, f->type);
-+
-+      f->fmt.pix.width        = q_data->crop_width;
-+      f->fmt.pix.height       = q_data->height;
-+      f->fmt.pix.field        = V4L2_FIELD_NONE;
-+      f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
-+      f->fmt.pix.bytesperline = q_data->bytesperline;
-+      f->fmt.pix.sizeimage    = q_data->sizeimage;
-+      f->fmt.pix.colorspace   = ctx->colorspace;
-+      f->fmt.pix.xfer_func    = ctx->xfer_func;
-+      f->fmt.pix.ycbcr_enc    = ctx->ycbcr_enc;
-+      f->fmt.pix.quantization = ctx->quant;
-+
-+      return 0;
-+}
-+
-+static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
-+                              struct v4l2_format *f)
-+{
-+      return vidioc_g_fmt(file2ctx(file), f);
-+}
-+
-+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-+                              struct v4l2_format *f)
-+{
-+      return vidioc_g_fmt(file2ctx(file), f);
-+}
-+
-+static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
-+{
-+      /*
-+       * The V4L2 specification requires the driver to correct the format
-+       * struct if any of the dimensions is unsupported
-+       */
-+      if (f->fmt.pix.width > MAX_W)
-+              f->fmt.pix.width = MAX_W;
-+      if (f->fmt.pix.height > MAX_H)
-+              f->fmt.pix.height = MAX_H;
-+
-+      if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
-+              /* Only clip min w/h on capture. Treat 0x0 as unknown. */
-+              if (f->fmt.pix.width < MIN_W)
-+                      f->fmt.pix.width = MIN_W;
-+              if (f->fmt.pix.height < MIN_H)
-+                      f->fmt.pix.height = MIN_H;
-+
-+              /*
-+               * Buffer must have a vertical alignment of 16 lines.
-+               * The selection will reflect any cropping rectangle when only
-+               * some of the pixels are active.
-+               */
-+              f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
-+
-+              f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
-+                                                         fmt);
-+              f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
-+                                                   f->fmt.pix.height,
-+                                                   fmt);
-+      } else {
-+              u32 min_size = f->fmt.pix.width > 1280 ||
-+                             f->fmt.pix.height > 720 ?
-+                             DEF_COMP_BUF_SIZE_GREATER_720P :
-+                             DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+
-+              f->fmt.pix.bytesperline = 0;
-+              if (f->fmt.pix.sizeimage < min_size)
-+                      f->fmt.pix.sizeimage = min_size;
-+      }
-+
-+      f->fmt.pix.field = V4L2_FIELD_NONE;
-+
-+      return 0;
-+}
-+
-+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-+                                struct v4l2_format *f)
-+{
-+      struct bcm2835_codec_fmt *fmt;
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      fmt = find_format(f, ctx->dev->decode, true);
-+      if (!fmt) {
-+              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+                                                          true)->fourcc;
-+              fmt = find_format(f, ctx->dev->decode, true);
-+      }
-+
-+      return vidioc_try_fmt(f, fmt);
-+}
-+
-+static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
-+                                struct v4l2_format *f)
-+{
-+      struct bcm2835_codec_fmt *fmt;
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      fmt = find_format(f, ctx->dev->decode, false);
-+      if (!fmt) {
-+              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+                                                          false)->fourcc;
-+              fmt = find_format(f, ctx->dev->decode, false);
-+      }
-+
-+      if (!f->fmt.pix.colorspace)
-+              f->fmt.pix.colorspace = ctx->colorspace;
-+
-+      return vidioc_try_fmt(f, fmt);
-+}
-+
-+static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
-+                      unsigned int requested_height)
-+{
-+      struct bcm2835_codec_q_data *q_data;
-+      struct vb2_queue *vq;
-+      struct vchiq_mmal_port *port;
-+      bool update_capture_port = false;
-+      int ret;
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
-+               f->type, f->fmt.pix.width, f->fmt.pix.height,
-+               f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
-+
-+      vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-+      if (!vq)
-+              return -EINVAL;
-+
-+      q_data = get_q_data(ctx, f->type);
-+      if (!q_data)
-+              return -EINVAL;
-+
-+      if (vb2_is_busy(vq)) {
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
-+              return -EBUSY;
-+      }
-+
-+      q_data->fmt = find_format(f, ctx->dev->decode,
-+                                f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
-+      q_data->crop_width = f->fmt.pix.width;
-+      q_data->height = f->fmt.pix.height;
-+      if (!q_data->selection_set)
-+              q_data->crop_height = requested_height;
-+
-+      /*
-+       * Copying the behaviour of vicodec which retains a single set of
-+       * colorspace parameters for both input and output.
-+       */
-+      ctx->colorspace = f->fmt.pix.colorspace;
-+      ctx->xfer_func = f->fmt.pix.xfer_func;
-+      ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
-+      ctx->quant = f->fmt.pix.quantization;
-+
-+      /* All parameters should have been set correctly by try_fmt */
-+      q_data->bytesperline = f->fmt.pix.bytesperline;
-+      q_data->sizeimage = f->fmt.pix.sizeimage;
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
-+               q_data->bytesperline, q_data->sizeimage);
-+
-+      if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
-+          f->fmt.pix.width && f->fmt.pix.height) {
-+              /*
-+               * On the decoder, if provided with a resolution on the input
-+               * side, then replicate that to the output side.
-+               * GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
-+               * nor set up a resolution on the output side, therefore
-+               * we can't decode anything at a resolution other than the
-+               * default one.
-+               */
-+              struct bcm2835_codec_q_data *q_data_dst =
-+                                              &ctx->q_data[V4L2_M2M_DST];
-+
-+              q_data_dst->crop_width = q_data->crop_width;
-+              q_data_dst->crop_height = q_data->crop_height;
-+              q_data_dst->height = ALIGN(q_data->crop_height, 16);
-+
-+              q_data_dst->bytesperline =
-+                      get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
-+              q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
-+                                                    q_data_dst->height,
-+                                                    q_data_dst->fmt);
-+              update_capture_port = true;
-+      }
-+
-+      /* If we have a component then setup the port as well */
-+      port = get_port_data(ctx, vq->type);
-+      if (!port)
-+              return 0;
-+
-+      setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
-+      ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
-+      if (ret) {
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
-+                       __func__, ret);
-+              ret = -EINVAL;
-+      }
-+
-+      if (q_data->sizeimage < port->minimum_buffer.size) {
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s: Current buffer size of %u < min buf size %u - driver mismatch to MMAL\n",
-+                       __func__, q_data->sizeimage,
-+                       port->minimum_buffer.size);
-+      }
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
-+               f->type, q_data->crop_width, q_data->height,
-+               q_data->fmt->fourcc, q_data->sizeimage);
-+
-+      if (update_capture_port) {
-+              struct vchiq_mmal_port *port_dst = &ctx->component->output[0];
-+              struct bcm2835_codec_q_data *q_data_dst =
-+                                              &ctx->q_data[V4L2_M2M_DST];
-+
-+              setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
-+                                     port_dst);
-+              ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
-+              if (ret) {
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
-+                               __func__, ret);
-+                      ret = -EINVAL;
-+              }
-+      }
-+      return ret;
-+}
-+
-+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-+                              struct v4l2_format *f)
-+{
-+      unsigned int height = f->fmt.pix.height;
-+      int ret;
-+
-+      ret = vidioc_try_fmt_vid_cap(file, priv, f);
-+      if (ret)
-+              return ret;
-+
-+      return vidioc_s_fmt(file2ctx(file), f, height);
-+}
-+
-+static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
-+                              struct v4l2_format *f)
-+{
-+      unsigned int height = f->fmt.pix.height;
-+      int ret;
-+
-+      ret = vidioc_try_fmt_vid_out(file, priv, f);
-+      if (ret)
-+              return ret;
-+
-+      ret = vidioc_s_fmt(file2ctx(file), f, height);
-+      return ret;
-+}
-+
-+static int vidioc_g_selection(struct file *file, void *priv,
-+                            struct v4l2_selection *s)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+      struct bcm2835_codec_q_data *q_data;
-+      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
-+                                                              true : false;
-+
-+      if (capture_queue ^ ctx->dev->decode)
-+              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
-+              return -EINVAL;
-+
-+      q_data = get_q_data(ctx, s->type);
-+      if (!q_data)
-+              return -EINVAL;
-+
-+      if (ctx->dev->decode) {
-+              switch (s->target) {
-+              case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-+              case V4L2_SEL_TGT_COMPOSE:
-+                      s->r.left = 0;
-+                      s->r.top = 0;
-+                      s->r.width = q_data->crop_width;
-+                      s->r.height = q_data->crop_height;
-+                      break;
-+              case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-+                      s->r.left = 0;
-+                      s->r.top = 0;
-+                      s->r.width = q_data->crop_width;
-+                      s->r.height = q_data->crop_height;
-+                      break;
-+              default:
-+                      return -EINVAL;
-+              }
-+      } else {
-+              switch (s->target) {
-+              case V4L2_SEL_TGT_CROP_DEFAULT:
-+              case V4L2_SEL_TGT_CROP_BOUNDS:
-+                      s->r.top = 0;
-+                      s->r.left = 0;
-+                      s->r.width = q_data->bytesperline;
-+                      s->r.height = q_data->height;
-+                      break;
-+              case V4L2_SEL_TGT_CROP:
-+                      s->r.top = 0;
-+                      s->r.left = 0;
-+                      s->r.width = q_data->crop_width;
-+                      s->r.height = q_data->crop_height;
-+                      break;
-+              default:
-+                      return -EINVAL;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int vidioc_s_selection(struct file *file, void *priv,
-+                            struct v4l2_selection *s)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+      struct bcm2835_codec_q_data *q_data = NULL;
-+      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
-+                                                              true : false;
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
-+               __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
-+               s->r.width, s->r.height);
-+
-+      if (capture_queue ^ ctx->dev->decode)
-+              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
-+              return -EINVAL;
-+
-+      q_data = get_q_data(ctx, s->type);
-+      if (!q_data)
-+              return -EINVAL;
-+
-+      if (ctx->dev->decode) {
-+              switch (s->target) {
-+              case V4L2_SEL_TGT_COMPOSE:
-+                      /* Accept cropped image */
-+                      s->r.left = 0;
-+                      s->r.top = 0;
-+                      s->r.width = min(s->r.width, q_data->crop_width);
-+                      s->r.height = min(s->r.height, q_data->height);
-+                      q_data->crop_width = s->r.width;
-+                      q_data->crop_height = s->r.height;
-+                      q_data->selection_set = true;
-+                      break;
-+              default:
-+                      return -EINVAL;
-+              }
-+      } else {
-+              switch (s->target) {
-+              case V4L2_SEL_TGT_CROP:
-+                      /* Only support crop from (0,0) */
-+                      s->r.top = 0;
-+                      s->r.left = 0;
-+                      s->r.width = min(s->r.width, q_data->crop_width);
-+                      s->r.height = min(s->r.height, q_data->crop_height);
-+                      q_data->crop_width = s->r.width;
-+                      q_data->crop_height = s->r.height;
-+                      q_data->selection_set = true;
-+                      break;
-+              default:
-+                      return -EINVAL;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int vidioc_subscribe_evt(struct v4l2_fh *fh,
-+                              const struct v4l2_event_subscription *sub)
-+{
-+      switch (sub->type) {
-+      case V4L2_EVENT_EOS:
-+              return v4l2_event_subscribe(fh, sub, 2, NULL);
-+      case V4L2_EVENT_SOURCE_CHANGE:
-+              return v4l2_src_change_event_subscribe(fh, sub);
-+      default:
-+              return v4l2_ctrl_subscribe_event(fh, sub);
-+      }
-+}
-+
-+static int bcm2835_codec_set_level_profile(struct bcm2835_codec_ctx *ctx,
-+                                         struct v4l2_ctrl *ctrl)
-+{
-+      struct mmal_parameter_video_profile param;
-+      int param_size = sizeof(param);
-+      int ret;
-+
-+      /*
-+       * Level and Profile are set via the same MMAL parameter.
-+       * Retrieve the current settings and amend the one that has changed.
-+       */
-+      ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
-+                                          &ctx->component->output[0],
-+                                          MMAL_PARAMETER_PROFILE,
-+                                          &param,
-+                                          &param_size);
-+      if (ret)
-+              return ret;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-+              switch (ctrl->val) {
-+              case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
-+                      param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
-+                      param.profile =
-+                              MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
-+                      param.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
-+                      param.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
-+                      break;
-+              default:
-+                      /* Should never get here */
-+                      break;
-+              }
-+              break;
-+
-+      case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-+              switch (ctrl->val) {
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_1;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_1b;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_11;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_12;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_13;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_2;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_21;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_22;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_3;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_31;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_32;
-+                      break;
-+              case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
-+                      param.level = MMAL_VIDEO_LEVEL_H264_4;
-+                      break;
-+              default:
-+                      /* Should never get here */
-+                      break;
-+              }
-+      }
-+      ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+                                          &ctx->component->output[0],
-+                                          MMAL_PARAMETER_PROFILE,
-+                                          &param,
-+                                          param_size);
-+
-+      return ret;
-+}
-+
-+static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct bcm2835_codec_ctx *ctx =
-+              container_of(ctrl->handler, struct bcm2835_codec_ctx, hdl);
-+      int ret = 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_MPEG_VIDEO_BITRATE:
-+              ctx->bitrate = ctrl->val;
-+              if (!ctx->component)
-+                      break;
-+
-+              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+                                                  &ctx->component->output[0],
-+                                                  MMAL_PARAMETER_VIDEO_BIT_RATE,
-+                                                  &ctrl->val,
-+                                                  sizeof(ctrl->val));
-+              break;
-+
-+      case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
-+              u32 bitrate_mode;
-+
-+              if (!ctx->component)
-+                      break;
-+
-+              switch (ctrl->val) {
-+              default:
-+              case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
-+                      bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
-+                      break;
-+              case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
-+                      bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
-+                      break;
-+              }
-+
-+              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+                                                  &ctx->component->output[0],
-+                                                  MMAL_PARAMETER_RATECONTROL,
-+                                                  &bitrate_mode,
-+                                                  sizeof(bitrate_mode));
-+              break;
-+      }
-+      case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
-+              if (!ctx->component)
-+                      break;
-+
-+              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+                                                  &ctx->component->output[0],
-+                                                  MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
-+                                                  &ctrl->val,
-+                                                  sizeof(ctrl->val));
-+              break;
-+
-+      case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
-+              if (!ctx->component)
-+                      break;
-+
-+              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+                                                  &ctx->component->output[0],
-+                                                  MMAL_PARAMETER_INTRAPERIOD,
-+                                                  &ctrl->val,
-+                                                  sizeof(ctrl->val));
-+              break;
-+
-+      case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-+      case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-+              if (!ctx->component)
-+                      break;
-+
-+              ret = bcm2835_codec_set_level_profile(ctx, ctrl);
-+              break;
-+
-+      default:
-+              v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
-+              return -EINVAL;
-+      }
-+
-+      if (ret)
-+              v4l2_err(&ctx->dev->v4l2_dev, "Failed setting ctrl %08x, ret %d\n",
-+                       ctrl->id, ret);
-+      return ret ? -EINVAL : 0;
-+}
-+
-+static const struct v4l2_ctrl_ops bcm2835_codec_ctrl_ops = {
-+      .s_ctrl = bcm2835_codec_s_ctrl,
-+};
-+
-+static int vidioc_try_decoder_cmd(struct file *file, void *priv,
-+                                struct v4l2_decoder_cmd *cmd)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      if (!ctx->dev->decode)
-+              return -EINVAL;
-+
-+      switch (cmd->cmd) {
-+      case V4L2_DEC_CMD_STOP:
-+              if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) {
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: DEC cmd->flags=%u stop to black not supported",
-+                               __func__, cmd->flags);
-+                      return -EINVAL;
-+              }
-+              break;
-+      case V4L2_DEC_CMD_START:
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+      return 0;
-+}
-+
-+static int vidioc_decoder_cmd(struct file *file, void *priv,
-+                            struct v4l2_decoder_cmd *cmd)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+      struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
-+      int ret;
-+
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
-+               cmd->cmd);
-+      ret = vidioc_try_decoder_cmd(file, priv, cmd);
-+      if (ret)
-+              return ret;
-+
-+      switch (cmd->cmd) {
-+      case V4L2_DEC_CMD_STOP:
-+              if (q_data->eos_buffer_in_use)
-+                      v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
-+              q_data->eos_buffer_in_use = true;
-+
-+              q_data->eos_buffer.mmal.buffer_size = 0;
-+              q_data->eos_buffer.mmal.length = 0;
-+              q_data->eos_buffer.mmal.mmal_flags =
-+                                              MMAL_BUFFER_HEADER_FLAG_EOS;
-+              q_data->eos_buffer.mmal.pts = 0;
-+              q_data->eos_buffer.mmal.dts = 0;
-+
-+              if (!ctx->component)
-+                      break;
-+
-+              ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
-+                                             &ctx->component->input[0],
-+                                             &q_data->eos_buffer.mmal);
-+              if (ret)
-+                      v4l2_err(&ctx->dev->v4l2_dev,
-+                               "%s: EOS buffer submit failed %d\n",
-+                               __func__, ret);
-+
-+              break;
-+
-+      case V4L2_DEC_CMD_START:
-+              /* Do we need to do anything here? */
-+              break;
-+
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static int vidioc_try_encoder_cmd(struct file *file, void *priv,
-+                                struct v4l2_encoder_cmd *cmd)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      if (ctx->dev->decode)
-+              return -EINVAL;
-+
-+      switch (cmd->cmd) {
-+      case V4L2_ENC_CMD_STOP:
-+              break;
-+
-+      case V4L2_ENC_CMD_START:
-+              /* Do we need to do anything here? */
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+      return 0;
-+}
-+
-+static int vidioc_encoder_cmd(struct file *file, void *priv,
-+                            struct v4l2_encoder_cmd *cmd)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+      struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
-+      int ret;
-+
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
-+               cmd->cmd);
-+      ret = vidioc_try_encoder_cmd(file, priv, cmd);
-+      if (ret)
-+              return ret;
-+
-+      switch (cmd->cmd) {
-+      case V4L2_ENC_CMD_STOP:
-+              if (q_data->eos_buffer_in_use)
-+                      v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
-+              q_data->eos_buffer_in_use = true;
-+
-+              q_data->eos_buffer.mmal.buffer_size = 0;
-+              q_data->eos_buffer.mmal.length = 0;
-+              q_data->eos_buffer.mmal.mmal_flags =
-+                                              MMAL_BUFFER_HEADER_FLAG_EOS;
-+              q_data->eos_buffer.mmal.pts = 0;
-+              q_data->eos_buffer.mmal.dts = 0;
-+
-+              if (!ctx->component)
-+                      break;
-+
-+              ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
-+                                             &ctx->component->input[0],
-+                                             &q_data->eos_buffer.mmal);
-+              if (ret)
-+                      v4l2_err(&ctx->dev->v4l2_dev,
-+                               "%s: EOS buffer submit failed %d\n",
-+                               __func__, ret);
-+
-+              break;
-+      case V4L2_ENC_CMD_START:
-+              /* Do we need to do anything here? */
-+              break;
-+
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
-+      .vidioc_querycap        = vidioc_querycap,
-+
-+      .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-+      .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
-+      .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
-+      .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
-+
-+      .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
-+      .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
-+      .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
-+      .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
-+
-+      .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
-+      .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
-+      .vidioc_qbuf            = v4l2_m2m_ioctl_qbuf,
-+      .vidioc_dqbuf           = v4l2_m2m_ioctl_dqbuf,
-+      .vidioc_prepare_buf     = v4l2_m2m_ioctl_prepare_buf,
-+      .vidioc_create_bufs     = v4l2_m2m_ioctl_create_bufs,
-+      .vidioc_expbuf          = v4l2_m2m_ioctl_expbuf,
-+
-+      .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
-+      .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
-+
-+      .vidioc_g_selection     = vidioc_g_selection,
-+      .vidioc_s_selection     = vidioc_s_selection,
-+
-+      .vidioc_subscribe_event = vidioc_subscribe_evt,
-+      .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-+
-+      .vidioc_decoder_cmd = vidioc_decoder_cmd,
-+      .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
-+      .vidioc_encoder_cmd = vidioc_encoder_cmd,
-+      .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
-+};
-+
-+static int bcm2835_codec_set_ctrls(struct bcm2835_codec_ctx *ctx)
-+{
-+      /*
-+       * Query the control handler for the value of the various controls and
-+       * set them.
-+       */
-+      const u32 control_ids[] = {
-+              V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-+              V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
-+              V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
-+              V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-+              V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-+      };
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(control_ids); i++) {
-+              struct v4l2_ctrl *ctrl;
-+
-+              ctrl = v4l2_ctrl_find(&ctx->hdl, control_ids[i]);
-+              if (ctrl)
-+                      bcm2835_codec_s_ctrl(ctrl);
-+      }
-+
-+      return 0;
-+}
-+
-+static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
-+{
-+      struct bcm2835_codec_dev *dev = ctx->dev;
-+      unsigned int enable = 1;
-+      int ret;
-+
-+      ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
-+                                      "ril.video_decode" : "ril.video_encode",
-+                                      &ctx->component);
-+      if (ret < 0) {
-+              v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
-+                       __func__, dev->decode ? "decode" : "encode");
-+              return -ENOMEM;
-+      }
-+
-+      vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->input[0],
-+                                    MMAL_PARAMETER_ZERO_COPY, &enable,
-+                                    sizeof(enable));
-+      vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->output[0],
-+                                    MMAL_PARAMETER_ZERO_COPY, &enable,
-+                                    sizeof(enable));
-+
-+      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
-+                             &ctx->component->input[0]);
-+
-+      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
-+                             &ctx->component->output[0]);
-+
-+      ret = vchiq_mmal_port_set_format(dev->instance,
-+                                       &ctx->component->input[0]);
-+      if (ret < 0)
-+              goto destroy_component;
-+
-+      ret = vchiq_mmal_port_set_format(dev->instance,
-+                                       &ctx->component->output[0]);
-+      if (ret < 0)
-+              goto destroy_component;
-+
-+      if (dev->decode) {
-+              if (ctx->q_data[V4L2_M2M_DST].sizeimage <
-+                      ctx->component->output[0].minimum_buffer.size)
-+                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-+                               ctx->q_data[V4L2_M2M_DST].sizeimage,
-+                               ctx->component->output[0].minimum_buffer.size);
-+      } else {
-+              if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
-+                      ctx->component->output[0].minimum_buffer.size)
-+                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-+                               ctx->q_data[V4L2_M2M_SRC].sizeimage,
-+                               ctx->component->output[0].minimum_buffer.size);
-+
-+              /* Now we have a component we can set all the ctrls */
-+              bcm2835_codec_set_ctrls(ctx);
-+      }
-+
-+      return 0;
-+
-+destroy_component:
-+      vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
-+
-+      return ret;
-+}
-+
-+/*
-+ * Queue operations
-+ */
-+
-+static int bcm2835_codec_queue_setup(struct vb2_queue *vq,
-+                                   unsigned int *nbuffers,
-+                                   unsigned int *nplanes,
-+                                   unsigned int sizes[],
-+                                   struct device *alloc_devs[])
-+{
-+      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vq);
-+      struct bcm2835_codec_q_data *q_data;
-+      struct vchiq_mmal_port *port;
-+      unsigned int size;
-+
-+      q_data = get_q_data(ctx, vq->type);
-+      if (!q_data)
-+              return -EINVAL;
-+
-+      if (!ctx->component)
-+              if (bcm2835_codec_create_component(ctx))
-+                      return -EINVAL;
-+
-+      port = get_port_data(ctx, vq->type);
-+
-+      size = q_data->sizeimage;
-+
-+      if (*nplanes)
-+              return sizes[0] < size ? -EINVAL : 0;
-+
-+      *nplanes = 1;
-+
-+      sizes[0] = size;
-+      port->current_buffer.size = size;
-+
-+      if (*nbuffers < port->minimum_buffer.num)
-+              *nbuffers = port->minimum_buffer.num;
-+      /* Add one buffer to take an EOS */
-+      port->current_buffer.num = *nbuffers + 1;
-+
-+      return 0;
-+}
-+
-+static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
-+{
-+      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+      struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
-+      struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
-+                                                 vb);
-+      struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
-+                                                 m2m);
-+
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
-+               __func__, ctx, vb);
-+      buf->mmal.buffer = vb2_plane_vaddr(&buf->m2m.vb.vb2_buf, 0);
-+      buf->mmal.buffer_size = vb2_plane_size(&buf->m2m.vb.vb2_buf, 0);
-+
-+      mmal_vchi_buffer_init(ctx->dev->instance, &buf->mmal);
-+
-+      return 0;
-+}
-+
-+static int bcm2835_codec_buf_prepare(struct vb2_buffer *vb)
-+{
-+      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+      struct bcm2835_codec_q_data *q_data;
-+      struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-+      struct v4l2_m2m_buffer *m2m = container_of(vbuf, struct v4l2_m2m_buffer,
-+                                                 vb);
-+      struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
-+                                                 m2m);
-+      int ret;
-+
-+      v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
-+               __func__, vb->vb2_queue->type, vb);
-+
-+      q_data = get_q_data(ctx, vb->vb2_queue->type);
-+      if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
-+              if (vbuf->field == V4L2_FIELD_ANY)
-+                      vbuf->field = V4L2_FIELD_NONE;
-+              if (vbuf->field != V4L2_FIELD_NONE) {
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s field isn't supported\n",
-+                               __func__);
-+                      return -EINVAL;
-+              }
-+      }
-+
-+      if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
-+                       __func__, vb2_plane_size(vb, 0),
-+                       (long)q_data->sizeimage);
-+              return -EINVAL;
-+      }
-+
-+      if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
-+              vb2_set_plane_payload(vb, 0, q_data->sizeimage);
-+
-+      /*
-+       * We want to do this at init, but vb2_core_expbuf checks that the
-+       * index < q->num_buffers, and q->num_buffers only gets updated once
-+       * all the buffers are allocated.
-+       */
-+      if (!buf->mmal.dma_buf) {
-+              ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
-+                                           vb->vb2_queue->type, vb->index, 0,
-+                                           O_CLOEXEC, &buf->mmal.dma_buf);
-+              if (ret)
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
-+                               __func__, vb->index, ret);
-+      } else {
-+              ret = 0;
-+      }
-+
-+      return ret;
-+}
-+
-+static void bcm2835_codec_buf_queue(struct vb2_buffer *vb)
-+{
-+      struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-+      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+
-+      v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p vbuf->flags %u, seq %u, bytesused %u\n",
-+               __func__, vb->vb2_queue->type, vb, vbuf->flags, vbuf->sequence,
-+               vb->planes[0].bytesused);
-+      v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-+}
-+
-+static void bcm2835_codec_buffer_cleanup(struct vb2_buffer *vb)
-+{
-+      struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+      struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
-+      struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
-+                                                 vb);
-+      struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
-+                                                 m2m);
-+
-+      v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
-+               __func__, ctx, vb);
-+
-+      mmal_vchi_buffer_cleanup(&buf->mmal);
-+
-+      if (buf->mmal.dma_buf) {
-+              dma_buf_put(buf->mmal.dma_buf);
-+              buf->mmal.dma_buf = NULL;
-+      }
-+}
-+
-+static int bcm2835_codec_start_streaming(struct vb2_queue *q,
-+                                       unsigned int count)
-+{
-+      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);
-+      int ret;
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
-+               __func__, q->type, count);
-+      q_data->sequence = 0;
-+
-+      if (!ctx->component_enabled) {
-+              ret = vchiq_mmal_component_enable(dev->instance,
-+                                                ctx->component);
-+              if (ret)
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
-+                               __func__, ret);
-+              ctx->component_enabled = true;
-+      }
-+
-+      if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-+              /*
-+               * Create the EOS buffer.
-+               * We only need the MMAL part, and want to NOT attach a memory
-+               * buffer to it as it should only take flags.
-+               */
-+              memset(&q_data->eos_buffer, 0, sizeof(q_data->eos_buffer));
-+              mmal_vchi_buffer_init(dev->instance,
-+                                    &q_data->eos_buffer.mmal);
-+              q_data->eos_buffer_in_use = false;
-+
-+              ctx->component->input[0].cb_ctx = ctx;
-+              ret = vchiq_mmal_port_enable(dev->instance,
-+                                           &ctx->component->input[0],
-+                                           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;
-+              ret = vchiq_mmal_port_enable(dev->instance,
-+                                           &ctx->component->output[0],
-+                                           op_buffer_cb);
-+              if (ret)
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
-+                               __func__, ret);
-+      }
-+      return ret;
-+}
-+
-+static void bcm2835_codec_stop_streaming(struct vb2_queue *q)
-+{
-+      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);
-+      struct vb2_v4l2_buffer *vbuf;
-+      struct vb2_v4l2_buffer *vb2;
-+      struct v4l2_m2m_buffer *m2m;
-+      struct m2m_mmal_buffer *buf;
-+      int ret, i;
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n",
-+               __func__, q->type);
-+
-+      init_completion(&ctx->frame_cmplt);
-+
-+      /* Clear out all buffers held by m2m framework */
-+      for (;;) {
-+              if (V4L2_TYPE_IS_OUTPUT(q->type))
-+                      vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-+              else
-+                      vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-+              if (!vbuf)
-+                      break;
-+              v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: return buffer %p\n",
-+                       __func__, vbuf);
-+
-+              v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
-+      }
-+
-+      /* Disable MMAL port - this will flush buffers back */
-+      ret = vchiq_mmal_port_disable(dev->instance, port);
-+      if (ret)
-+              v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed disabling %s port, ret %d\n",
-+                       __func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
-+                       ret);
-+
-+      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);
-+              if (ret <= 0) {
-+                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
-+                               __func__,
-+                               atomic_read(&port->buffers_with_vpu));
-+                      break;
-+              }
-+      }
-+
-+      /*
-+       * 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);
-+
-+              mmal_vchi_buffer_cleanup(&buf->mmal);
-+              if (buf->mmal.dma_buf) {
-+                      dma_buf_put(buf->mmal.dma_buf);
-+                      buf->mmal.dma_buf = NULL;
-+              }
-+      }
-+
-+      /* If both ports disabled, then disable the component */
-+      if (!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);
-+      }
-+
-+      if (V4L2_TYPE_IS_OUTPUT(q->type))
-+              mmal_vchi_buffer_cleanup(&q_data->eos_buffer.mmal);
-+
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: done\n", __func__);
-+}
-+
-+static const struct vb2_ops bcm2835_codec_qops = {
-+      .queue_setup     = bcm2835_codec_queue_setup,
-+      .buf_init        = bcm2835_codec_buf_init,
-+      .buf_prepare     = bcm2835_codec_buf_prepare,
-+      .buf_queue       = bcm2835_codec_buf_queue,
-+      .buf_cleanup     = bcm2835_codec_buffer_cleanup,
-+      .start_streaming = bcm2835_codec_start_streaming,
-+      .stop_streaming  = bcm2835_codec_stop_streaming,
-+      .wait_prepare    = vb2_ops_wait_prepare,
-+      .wait_finish     = vb2_ops_wait_finish,
-+};
-+
-+static int queue_init(void *priv, struct vb2_queue *src_vq,
-+                    struct vb2_queue *dst_vq)
-+{
-+      struct bcm2835_codec_ctx *ctx = priv;
-+      int ret;
-+
-+      src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-+      src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-+      src_vq->drv_priv = ctx;
-+      src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
-+      src_vq->ops = &bcm2835_codec_qops;
-+      src_vq->mem_ops = &vb2_dma_contig_memops;
-+      src_vq->dev = &ctx->dev->pdev->dev;
-+      src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-+      src_vq->lock = &ctx->dev->dev_mutex;
-+
-+      ret = vb2_queue_init(src_vq);
-+      if (ret)
-+              return ret;
-+
-+      dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+      dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-+      dst_vq->drv_priv = ctx;
-+      dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
-+      dst_vq->ops = &bcm2835_codec_qops;
-+      dst_vq->mem_ops = &vb2_dma_contig_memops;
-+      dst_vq->dev = &ctx->dev->pdev->dev;
-+      dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-+      dst_vq->lock = &ctx->dev->dev_mutex;
-+
-+      return vb2_queue_init(dst_vq);
-+}
-+
-+/*
-+ * File operations
-+ */
-+static int bcm2835_codec_open(struct file *file)
-+{
-+      struct bcm2835_codec_dev *dev = video_drvdata(file);
-+      struct bcm2835_codec_ctx *ctx = NULL;
-+      struct v4l2_ctrl_handler *hdl;
-+      int rc = 0;
-+
-+      v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
-+               dev->decode ? "decode" : "encode");
-+      if (mutex_lock_interruptible(&dev->dev_mutex)) {
-+              v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
-+              return -ERESTARTSYS;
-+      }
-+      ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-+      if (!ctx) {
-+              rc = -ENOMEM;
-+              goto open_unlock;
-+      }
-+
-+      ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
-+      ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
-+      if (dev->decode) {
-+              /*
-+               * Input width and height are irrelevant as they will be defined
-+               * by the bitstream not the format. Required by V4L2 though.
-+               */
-+              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-+              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
-+              ctx->q_data[V4L2_M2M_SRC].sizeimage =
-+                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+
-+              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-+              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_DST].bytesperline =
-+                              get_bytesperline(DEFAULT_WIDTH,
-+                                               ctx->q_data[V4L2_M2M_DST].fmt);
-+              ctx->q_data[V4L2_M2M_DST].sizeimage =
-+                      get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
-+                                    ctx->q_data[V4L2_M2M_DST].height,
-+                                    ctx->q_data[V4L2_M2M_DST].fmt);
-+      } else {
-+              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-+              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_SRC].bytesperline =
-+                              get_bytesperline(DEFAULT_WIDTH,
-+                                               ctx->q_data[V4L2_M2M_SRC].fmt);
-+              ctx->q_data[V4L2_M2M_SRC].sizeimage =
-+                      get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
-+                                    ctx->q_data[V4L2_M2M_SRC].height,
-+                                    ctx->q_data[V4L2_M2M_SRC].fmt);
-+
-+              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-+              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
-+              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-+              ctx->q_data[V4L2_M2M_DST].sizeimage =
-+                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+      }
-+
-+      ctx->colorspace = V4L2_COLORSPACE_REC709;
-+      ctx->bitrate = 10 * 1000 * 1000;
-+
-+      /* Initialise V4L2 contexts */
-+      v4l2_fh_init(&ctx->fh, video_devdata(file));
-+      file->private_data = &ctx->fh;
-+      ctx->dev = dev;
-+      hdl = &ctx->hdl;
-+      if (!dev->decode) {
-+              /* Encode controls */
-+              v4l2_ctrl_handler_init(hdl, 6);
-+
-+              v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
-+                                     V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-+                                     V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
-+                                     V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-+              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+                                V4L2_CID_MPEG_VIDEO_BITRATE,
-+                                25 * 1000, 25 * 1000 * 1000,
-+                                25 * 1000, 10 * 1000 * 1000);
-+              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+                                V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
-+                                0, 1,
-+                                1, 0);
-+              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+                                V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
-+                                0, 0x7FFFFFFF,
-+                                1, 60);
-+              v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
-+                                     V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-+                                     V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
-+                                     ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
-+                                     V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
-+              v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
-+                                     V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-+                                     V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
-+                                     ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
-+                                       BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
-+                                      V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
-+              if (hdl->error) {
-+                      rc = hdl->error;
-+                      goto free_ctrl_handler;
-+              }
-+              ctx->fh.ctrl_handler = hdl;
-+              v4l2_ctrl_handler_setup(hdl);
-+      }
-+
-+      ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
-+
-+      if (IS_ERR(ctx->fh.m2m_ctx)) {
-+              rc = PTR_ERR(ctx->fh.m2m_ctx);
-+
-+              goto free_ctrl_handler;
-+      }
-+
-+      /* Set both queues as buffered as we have buffering in the VPU. That
-+       * means that we will be scheduled whenever either an input or output
-+       * buffer is available (otherwise one of each are required).
-+       */
-+      v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
-+      v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
-+
-+      v4l2_fh_add(&ctx->fh);
-+      atomic_inc(&dev->num_inst);
-+
-+      mutex_unlock(&dev->dev_mutex);
-+      return 0;
-+
-+free_ctrl_handler:
-+      v4l2_ctrl_handler_free(hdl);
-+      kfree(ctx);
-+open_unlock:
-+      mutex_unlock(&dev->dev_mutex);
-+      return rc;
-+}
-+
-+static int bcm2835_codec_release(struct file *file)
-+{
-+      struct bcm2835_codec_dev *dev = video_drvdata(file);
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: Releasing instance %p\n",
-+               __func__, ctx);
-+
-+      v4l2_fh_del(&ctx->fh);
-+      v4l2_fh_exit(&ctx->fh);
-+      v4l2_ctrl_handler_free(&ctx->hdl);
-+      mutex_lock(&dev->dev_mutex);
-+      v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-+
-+      if (ctx->component)
-+              vchiq_mmal_component_finalise(dev->instance, ctx->component);
-+
-+      mutex_unlock(&dev->dev_mutex);
-+      kfree(ctx);
-+
-+      atomic_dec(&dev->num_inst);
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_file_operations bcm2835_codec_fops = {
-+      .owner          = THIS_MODULE,
-+      .open           = bcm2835_codec_open,
-+      .release        = bcm2835_codec_release,
-+      .poll           = v4l2_m2m_fop_poll,
-+      .unlocked_ioctl = video_ioctl2,
-+      .mmap           = v4l2_m2m_fop_mmap,
-+};
-+
-+static const struct video_device bcm2835_codec_videodev = {
-+      .name           = MEM2MEM_NAME,
-+      .vfl_dir        = VFL_DIR_M2M,
-+      .fops           = &bcm2835_codec_fops,
-+      .ioctl_ops      = &bcm2835_codec_ioctl_ops,
-+      .minor          = -1,
-+      .release        = video_device_release_empty,
-+};
-+
-+static const struct v4l2_m2m_ops m2m_ops = {
-+      .device_run     = device_run,
-+      .job_ready      = job_ready,
-+      .job_abort      = job_abort,
-+};
-+
-+static int bcm2835_codec_create(struct platform_device *pdev,
-+                              struct bcm2835_codec_dev **new_dev,
-+                              bool decode)
-+{
-+      struct bcm2835_codec_dev *dev;
-+      struct video_device *vfd;
-+      struct vchiq_mmal_instance *instance = NULL;
-+      int video_nr;
-+      int ret;
-+
-+      dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      dev->pdev = pdev;
-+
-+      dev->decode = decode;
-+
-+      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-+      if (ret)
-+              return ret;
-+
-+      atomic_set(&dev->num_inst, 0);
-+      mutex_init(&dev->dev_mutex);
-+
-+      dev->vfd = bcm2835_codec_videodev;
-+      vfd = &dev->vfd;
-+      vfd->lock = &dev->dev_mutex;
-+      vfd->v4l2_dev = &dev->v4l2_dev;
-+
-+      if (dev->decode) {
-+              v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
-+              v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-+              video_nr = decode_video_nr;
-+      } else {
-+              v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-+              v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-+              video_nr = encode_video_nr;
-+      }
-+
-+      ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-+      if (ret) {
-+              v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-+              goto unreg_dev;
-+      }
-+
-+      video_set_drvdata(vfd, dev);
-+      snprintf(vfd->name, sizeof(vfd->name), "%s",
-+               bcm2835_codec_videodev.name);
-+      v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
-+                vfd->num);
-+
-+      *new_dev = dev;
-+
-+      dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
-+      if (IS_ERR(dev->m2m_dev)) {
-+              v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
-+              ret = PTR_ERR(dev->m2m_dev);
-+              goto err_m2m;
-+      }
-+
-+      ret = vchiq_mmal_init(&instance);
-+      if (ret < 0)
-+              goto err_m2m;
-+      dev->instance = instance;
-+
-+      v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
-+                dev->decode ? "decode" : "encode");
-+      return 0;
-+
-+err_m2m:
-+      v4l2_m2m_release(dev->m2m_dev);
-+      video_unregister_device(&dev->vfd);
-+unreg_dev:
-+      v4l2_device_unregister(&dev->v4l2_dev);
-+
-+      return ret;
-+}
-+
-+static int bcm2835_codec_destroy(struct bcm2835_codec_dev *dev)
-+{
-+      if (!dev)
-+              return -ENODEV;
-+
-+      v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
-+      v4l2_m2m_release(dev->m2m_dev);
-+      video_unregister_device(&dev->vfd);
-+      v4l2_device_unregister(&dev->v4l2_dev);
-+
-+      return 0;
-+}
-+
-+static int bcm2835_codec_probe(struct platform_device *pdev)
-+{
-+      struct bcm2835_codec_driver *drv;
-+      int ret = 0;
-+
-+      drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
-+      if (!drv)
-+              return -ENOMEM;
-+
-+      ret = bcm2835_codec_create(pdev, &drv->encode, false);
-+      if (ret)
-+              goto out;
-+
-+      ret = bcm2835_codec_create(pdev, &drv->decode, true);
-+      if (ret)
-+              goto out;
-+
-+      platform_set_drvdata(pdev, drv);
-+
-+      return 0;
-+
-+out:
-+      if (drv->encode) {
-+              bcm2835_codec_destroy(drv->encode);
-+              drv->encode = NULL;
-+      }
-+      return ret;
-+}
-+
-+static int bcm2835_codec_remove(struct platform_device *pdev)
-+{
-+      struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
-+
-+      bcm2835_codec_destroy(drv->encode);
-+
-+      bcm2835_codec_destroy(drv->decode);
-+
-+      return 0;
-+}
-+
-+static struct platform_driver bcm2835_v4l2_codec_driver = {
-+      .probe = bcm2835_codec_probe,
-+      .remove = bcm2835_codec_remove,
-+      .driver = {
-+                 .name = "bcm2835-codec",
-+                 .owner = THIS_MODULE,
-+                 },
-+};
-+
-+module_platform_driver(bcm2835_v4l2_codec_driver);
-+
-+MODULE_DESCRIPTION("BCM2835 codec V4L2 driver");
-+MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("0.0.1");
-+MODULE_ALIAS("platform:bcm2835-codec");
diff --git a/target/linux/brcm2708/patches-4.19/950-0246-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch b/target/linux/brcm2708/patches-4.19/950-0246-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch
new file mode 100644 (file)
index 0000000..6bfa52d
--- /dev/null
@@ -0,0 +1,34 @@
+From 69c5c6d62b457ee88e55c4090dc09c0441b059f2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 26 Oct 2018 15:19:40 +0100
+Subject: [PATCH] staging: vchiq_arm: Register vcsm-cma as a platform
+ driver
+
+Following the same pattern as bcm2835-camera and bcm2835-audio,
+register the vcsm-cma driver as a platform driver
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -171,6 +171,7 @@ static struct device *vchiq_dev;
+ static DEFINE_SPINLOCK(msg_queue_spinlock);
+ static struct platform_device *bcm2835_camera;
+ static struct platform_device *bcm2835_codec;
++static struct platform_device *vcsm_cma;
+ static const char *const ioctl_names[] = {
+       "CONNECT",
+@@ -3654,6 +3655,9 @@ static int vchiq_probe(struct platform_d
+               VCHIQ_VERSION, VCHIQ_VERSION_MIN,
+               MAJOR(vchiq_devid), MINOR(vchiq_devid));
++      vcsm_cma = vchiq_register_child(pdev, "vcsm-cma");
++      if (IS_ERR(vcsm_cma))
++              vcsm_cma = NULL;
+       bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
+       if (IS_ERR(bcm2835_camera))
+               bcm2835_camera = NULL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0247-staging-bcm2835-camera-Fix-stride-on-RGB3-BGR3-forma.patch b/target/linux/brcm2708/patches-4.19/950-0247-staging-bcm2835-camera-Fix-stride-on-RGB3-BGR3-forma.patch
new file mode 100644 (file)
index 0000000..9659b10
--- /dev/null
@@ -0,0 +1,53 @@
+From 69e42b6209062b9cd3fc9aea8fb53ed703509e51 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 30 Nov 2018 16:00:54 +0000
+Subject: [PATCH] staging: bcm2835-camera: Fix stride on RGB3/BGR3
+ formats
+
+RGB3/BGR3 end up being 3 bytes per pixel, which meant that
+the alignment code ended up trying to align using bitmasking
+with a mask of 96.
+That doesn't work, so switch to an arithmetic alignment for
+those formats.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c           | 26 ++++++++++++++-----
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -1008,13 +1008,27 @@ static int vidioc_try_fmt_vid_cap(struct
+                             1, 0);
+       f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp;
+       if (!mfmt->remove_padding) {
+-              int align_mask = ((32 * mfmt->depth) >> 3) - 1;
+-              /* GPU isn't removing padding, so stride is aligned to 32 */
+-              f->fmt.pix.bytesperline =
+-                      (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
++              if (mfmt->depth == 24) {
++                      /*
++                       * 24bpp is a pain as we can't use simple masking.
++                       * Min stride is width aligned to 16, times 24bpp.
++                       */
++                      f->fmt.pix.bytesperline =
++                              ((f->fmt.pix.width + 15) & ~15) * 3;
++              } else {
++                      /*
++                       * GPU isn't removing padding, so stride is aligned to
++                       * 32
++                       */
++                      int align_mask = ((32 * mfmt->depth) >> 3) - 1;
++
++                      f->fmt.pix.bytesperline =
++                              (f->fmt.pix.bytesperline + align_mask) &
++                                                      ~align_mask;
++              }
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+-                       "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
+-                       f->fmt.pix.bytesperline, align_mask);
++                       "Not removing padding, so bytes/line = %d\n",
++                       f->fmt.pix.bytesperline);
+       }
+       /* Image buffer has to be padded to allow for alignment, even though
diff --git a/target/linux/brcm2708/patches-4.19/950-0247-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch b/target/linux/brcm2708/patches-4.19/950-0247-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch
deleted file mode 100644 (file)
index 51cc4a4..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From b28dac3003b4c756b72201bb1d83647e33e2f4f1 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 26 Oct 2018 15:14:16 +0100
-Subject: [PATCH] staging: vchiq_arm: Register bcm2835-codec as a
- platform driver
-
-Following the same pattern as bcm2835-camera and bcm2835-audio,
-register the V4L2 codec driver as a platform driver
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -170,6 +170,7 @@ static struct class  *vchiq_class;
- static struct device *vchiq_dev;
- static DEFINE_SPINLOCK(msg_queue_spinlock);
- static struct platform_device *bcm2835_camera;
-+static struct platform_device *bcm2835_codec;
- static const char *const ioctl_names[] = {
-       "CONNECT",
-@@ -3656,6 +3657,9 @@ static int vchiq_probe(struct platform_d
-       bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
-       if (IS_ERR(bcm2835_camera))
-               bcm2835_camera = NULL;
-+      bcm2835_codec = vchiq_register_child(pdev, "bcm2835-codec");
-+      if (IS_ERR(bcm2835_codec))
-+              bcm2835_codec = NULL;
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0248-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch b/target/linux/brcm2708/patches-4.19/950-0248-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch
deleted file mode 100644 (file)
index 6bfa52d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 69c5c6d62b457ee88e55c4090dc09c0441b059f2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 26 Oct 2018 15:19:40 +0100
-Subject: [PATCH] staging: vchiq_arm: Register vcsm-cma as a platform
- driver
-
-Following the same pattern as bcm2835-camera and bcm2835-audio,
-register the vcsm-cma driver as a platform driver
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -171,6 +171,7 @@ static struct device *vchiq_dev;
- static DEFINE_SPINLOCK(msg_queue_spinlock);
- static struct platform_device *bcm2835_camera;
- static struct platform_device *bcm2835_codec;
-+static struct platform_device *vcsm_cma;
- static const char *const ioctl_names[] = {
-       "CONNECT",
-@@ -3654,6 +3655,9 @@ static int vchiq_probe(struct platform_d
-               VCHIQ_VERSION, VCHIQ_VERSION_MIN,
-               MAJOR(vchiq_devid), MINOR(vchiq_devid));
-+      vcsm_cma = vchiq_register_child(pdev, "vcsm-cma");
-+      if (IS_ERR(vcsm_cma))
-+              vcsm_cma = NULL;
-       bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
-       if (IS_ERR(bcm2835_camera))
-               bcm2835_camera = NULL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0248-tpm-Make-SECURITYFS-a-weak-dependency.patch b/target/linux/brcm2708/patches-4.19/950-0248-tpm-Make-SECURITYFS-a-weak-dependency.patch
new file mode 100644 (file)
index 0000000..7e86b09
--- /dev/null
@@ -0,0 +1,35 @@
+From 38e82adecd1b7ae790a827c29e954d35a2bbee98 Mon Sep 17 00:00:00 2001
+From: Peter Huewe <peterhuewe@gmx.de>
+Date: Mon, 3 Sep 2018 21:51:51 +0200
+Subject: [PATCH] tpm: Make SECURITYFS a weak dependency
+
+commit 2f7d8dbb11287cbe9da6380ca14ed5d38c9ed91f upstream.
+
+While having SECURITYFS enabled for the tpm subsystem is beneficial in
+most cases, it is not strictly necessary to have it enabled at all.
+Especially on platforms without any boot firmware integration of the TPM
+(e.g. raspberry pi) it does not add any value for the tpm subsystem,
+as there is no eventlog present.
+
+By turning it from 'select' to 'imply' it still gets selected per
+default, but enables users who want to save some kb of ram by turning
+SECURITYFS off.
+
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+---
+ drivers/char/tpm/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/tpm/Kconfig
++++ b/drivers/char/tpm/Kconfig
+@@ -5,7 +5,7 @@
+ menuconfig TCG_TPM
+       tristate "TPM Hardware Support"
+       depends on HAS_IOMEM
+-      select SECURITYFS
++      imply SECURITYFS
+       select CRYPTO
+       select CRYPTO_HASH_INFO
+       ---help---
diff --git a/target/linux/brcm2708/patches-4.19/950-0249-Add-overlay-for-SLB9760-Iridium-LetsTrust-TPM.patch b/target/linux/brcm2708/patches-4.19/950-0249-Add-overlay-for-SLB9760-Iridium-LetsTrust-TPM.patch
new file mode 100644 (file)
index 0000000..16539aa
--- /dev/null
@@ -0,0 +1,92 @@
+From 82298c670f768f392f48526fe7c8a93682e83998 Mon Sep 17 00:00:00 2001
+From: Peter Huewe <peterhuewe@gmx.de>
+Date: Thu, 14 Jun 2018 22:51:24 +0200
+Subject: [PATCH] Add overlay for SLB9760 Iridium /LetsTrust TPM
+
+Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
+boards, which can be used as a secure key storage and hwrng.
+available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by
+pi3g.
+
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  8 ++++
+ .../boot/dts/overlays/tpm-slb9670-overlay.dts | 44 +++++++++++++++++++
+ 3 files changed, 53 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -137,6 +137,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       tc358743.dtbo \
+       tc358743-audio.dtbo \
+       tinylcd35.dtbo \
++      tpm-slb9670.dtbo \
+       uart0.dtbo \
+       uart1.dtbo \
+       upstream.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2012,6 +2012,14 @@ Params: speed                   Display
+                 dtoverlay=tinylcd35,touch,touchgpio=3
++Name:   tpm-slb9670
++Info:   Enables support for Infineon SLB9670 Trusted Platform Module add-on
++        boards, which can be used as a secure key storage and hwrng,
++        available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
++Load:   dtoverlay=tpm-slb9670
++Params: <None>
++
++
+ Name:   uart0
+ Info:   Change the pin usage of uart0
+ Load:   dtoverlay=uart0,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
+@@ -0,0 +1,44 @@
++/*
++ * Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
++ * boards, which can be used as a secure key storage and hwrng.
++ * available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++      fragment@0 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&spidev1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@2 {
++              target = <&spi0>;
++              __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      slb9670: slb9670@1 {
++                              compatible = "infineon,slb9670";
++                              reg = <1>;      /* CE1 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <32000000>;
++                              status = "okay";
++                      };
++
++              };
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0249-staging-bcm2835-camera-Fix-stride-on-RGB3-BGR3-forma.patch b/target/linux/brcm2708/patches-4.19/950-0249-staging-bcm2835-camera-Fix-stride-on-RGB3-BGR3-forma.patch
deleted file mode 100644 (file)
index 9659b10..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From 69e42b6209062b9cd3fc9aea8fb53ed703509e51 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 30 Nov 2018 16:00:54 +0000
-Subject: [PATCH] staging: bcm2835-camera: Fix stride on RGB3/BGR3
- formats
-
-RGB3/BGR3 end up being 3 bytes per pixel, which meant that
-the alignment code ended up trying to align using bitmasking
-with a mask of 96.
-That doesn't work, so switch to an arithmetic alignment for
-those formats.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c           | 26 ++++++++++++++-----
- 1 file changed, 20 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -1008,13 +1008,27 @@ static int vidioc_try_fmt_vid_cap(struct
-                             1, 0);
-       f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp;
-       if (!mfmt->remove_padding) {
--              int align_mask = ((32 * mfmt->depth) >> 3) - 1;
--              /* GPU isn't removing padding, so stride is aligned to 32 */
--              f->fmt.pix.bytesperline =
--                      (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
-+              if (mfmt->depth == 24) {
-+                      /*
-+                       * 24bpp is a pain as we can't use simple masking.
-+                       * Min stride is width aligned to 16, times 24bpp.
-+                       */
-+                      f->fmt.pix.bytesperline =
-+                              ((f->fmt.pix.width + 15) & ~15) * 3;
-+              } else {
-+                      /*
-+                       * GPU isn't removing padding, so stride is aligned to
-+                       * 32
-+                       */
-+                      int align_mask = ((32 * mfmt->depth) >> 3) - 1;
-+
-+                      f->fmt.pix.bytesperline =
-+                              (f->fmt.pix.bytesperline + align_mask) &
-+                                                      ~align_mask;
-+              }
-               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
--                       "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
--                       f->fmt.pix.bytesperline, align_mask);
-+                       "Not removing padding, so bytes/line = %d\n",
-+                       f->fmt.pix.bytesperline);
-       }
-       /* Image buffer has to be padded to allow for alignment, even though
diff --git a/target/linux/brcm2708/patches-4.19/950-0250-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch b/target/linux/brcm2708/patches-4.19/950-0250-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch
new file mode 100644 (file)
index 0000000..e335536
--- /dev/null
@@ -0,0 +1,483 @@
+From e740bd2cc3fcd632fcd6c8881b1fc671bcde5914 Mon Sep 17 00:00:00 2001
+From: dev-3Dlab <45081440+dev-3Dlab@users.noreply.github.com>
+Date: Wed, 5 Dec 2018 10:59:11 +0100
+Subject: [PATCH] ASoC: add driver for 3Dlab Nano soundcard (#2758)
+
+Signed-off-by: GT <dev@3d-lab-av.com>
+---
+ .../overlays/3dlab-nano-player-overlay.dts    |  32 ++
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   6 +
+ sound/soc/bcm/3dlab-nano-player.c             | 370 ++++++++++++++++++
+ sound/soc/bcm/Kconfig                         |   6 +
+ sound/soc/bcm/Makefile                        |   2 +
+ 8 files changed, 419 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
+ create mode 100644 sound/soc/bcm/3dlab-nano-player.c
+
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
+@@ -0,0 +1,32 @@
++// Definitions for 3Dlab Nano Player
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2708";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      nano-player@41 {
++                              compatible = "3dlab,nano-player";
++                              reg = <0x41>;
++                              i2s-controller = <&i2s>;
++                              status = "okay";
++                      };
++              };
++      };
++};
++
++// EOF
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -1,6 +1,7 @@
+ # Overlays for the Raspberry Pi platform
+ dtbo-$(CONFIG_ARCH_BCM2835) += \
++      3dlab-nano-player.dtbo \
+       adau1977-adc.dtbo \
+       adau7002-simple.dtbo \
+       ads1015.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -199,6 +199,12 @@ Params:
+         and the other i2c baudrate parameters.
++Name:   3dlab-nano-player
++Info:   Configures the 3Dlab Nano Player
++Load:   dtoverlay=3dlab-nano-player
++Params: <None>
++
++
+ Name:   adau1977-adc
+ Info:   Overlay for activation of ADAU1977 ADC codec over I2C for control
+         and I2S for data.
+--- /dev/null
++++ b/sound/soc/bcm/3dlab-nano-player.c
+@@ -0,0 +1,370 @@
++/*
++ * 3Dlab Nano Player ALSA SoC Audio driver.
++ *
++ * Copyright (C) 2018 3Dlab.
++ *
++ * Author: GT <dev@3d-lab-av.com>
++ *
++ * 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/i2c.h>
++#include <sound/soc.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/control.h>
++
++#define NANO_ID               0x00
++#define NANO_VER      0x01
++#define NANO_CFG      0x02
++#define NANO_STATUS   0x03
++#define NANO_SPI_ADDR 0x04
++#define NANO_SPI_DATA 0x05
++
++#define NANO_ID_VAL   0x3D
++#define NANO_CFG_OFF  0x00
++#define NANO_CFG_MULT1        0
++#define NANO_CFG_MULT2        1
++#define NANO_CFG_MULT4        2
++#define NANO_CFG_MULT8        3
++#define NANO_CFG_MULT16       4
++#define NANO_CFG_CLK22        0
++#define NANO_CFG_CLK24        BIT(3)
++#define NANO_CFG_DSD  BIT(4)
++#define NANO_CFG_ENA  BIT(5)
++#define NANO_CFG_BLINK        BIT(6)
++#define NANO_STATUS_P1  BIT(0)
++#define NANO_STATUS_P2  BIT(1)
++#define NANO_STATUS_FLG BIT(2)
++#define NANO_STATUS_CLK BIT(3)
++#define NANO_SPI_READ 0
++#define NANO_SPI_WRITE        BIT(5)
++
++#define NANO_DAC_CTRL1        0x00
++#define NANO_DAC_CTRL2        0x01
++#define NANO_DAC_CTRL3        0x02
++#define NANO_DAC_LATT 0x03
++#define NANO_DAC_RATT 0x04
++
++#define NANO_CTRL2_VAL        0x22
++
++static int nano_player_spi_write(struct regmap *map,
++                               unsigned int reg, unsigned int val)
++{
++      /* indirect register access */
++      regmap_write(map, NANO_SPI_DATA, val);
++      regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
++      return 0;
++}
++
++static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
++                               struct snd_ctl_elem_info *uinfo)
++{
++      /* describe control element */
++      if (strstr(kcontrol->id.name, "Volume")) {
++              uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++              uinfo->count = 1;
++              uinfo->value.integer.min = 0;
++              uinfo->value.integer.max = 100;
++      } else {
++              uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++              uinfo->count = 1;
++              uinfo->value.integer.min = 0;
++              uinfo->value.integer.max = 1;
++      }
++
++      return 0;
++}
++
++static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
++                              struct snd_ctl_elem_value *ucontrol)
++{
++      /* program control value to hardware */
++      struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
++      struct regmap *regmap = snd_soc_card_get_drvdata(card);
++
++      if (strstr(kcontrol->id.name, "Volume")) {
++              unsigned int vol = ucontrol->value.integer.value[0];
++              unsigned int att = 255 - (2 * (100 - vol));
++
++              nano_player_spi_write(regmap, NANO_DAC_LATT, att);
++              nano_player_spi_write(regmap, NANO_DAC_RATT, att);
++              kcontrol->private_value = vol;
++      } else {
++              unsigned int mute = ucontrol->value.integer.value[0];
++              unsigned int reg = NANO_CTRL2_VAL | mute;
++
++              nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
++              kcontrol->private_value = mute;
++      }
++      return 0;
++}
++
++static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
++                              struct snd_ctl_elem_value *ucontrol)
++{
++      /* return last programmed value */
++      ucontrol->value.integer.value[0] = kcontrol->private_value;
++      return 0;
++}
++
++#define SOC_NANO_PLAYER_CTRL(xname) \
++{     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
++      .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
++      .info = nano_player_ctrl_info, \
++      .put = nano_player_ctrl_put, \
++      .get = nano_player_ctrl_get }
++
++static const struct snd_kcontrol_new nano_player_controls[] = {
++      SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
++      SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
++};
++
++static const unsigned int nano_player_rates[] = {
++      44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
++      705600, 768000 /* only possible with fast clocks */
++};
++
++static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
++      .list   = nano_player_rates,
++      .count  = ARRAY_SIZE(nano_player_rates),
++};
++
++static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_card *card = rtd->card;
++      struct regmap *regmap = snd_soc_card_get_drvdata(card);
++      struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
++      struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
++      unsigned int sample_bits = 32;
++      unsigned int val;
++
++      /* configure cpu dai */
++      cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
++      cpu->rate_max = 768000;
++
++      /* configure dummy codec dai */
++      codec->rate_min = 44100;
++      codec->rates = SNDRV_PCM_RATE_KNOT;
++      codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
++
++      /* configure max supported rate */
++      regmap_read(regmap, NANO_STATUS, &val);
++      if (val & NANO_STATUS_CLK) {
++              dev_notice(card->dev, "Board with fast clocks installed\n");
++              codec->rate_max = 768000;
++      } else {
++              dev_notice(card->dev, "Board with normal clocks installed\n");
++              codec->rate_max = 384000;
++      }
++
++      /* frame length enforced by hardware */
++      return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
++}
++
++static int nano_player_startup(struct snd_pcm_substream *substream)
++{
++      return snd_pcm_hw_constraint_list(substream->runtime, 0,
++                                        SNDRV_PCM_HW_PARAM_RATE,
++                                        &nano_player_constraint_rates);
++}
++
++static int nano_player_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_card *card = rtd->card;
++      struct regmap *regmap = snd_soc_card_get_drvdata(card);
++      unsigned int config = NANO_CFG_ENA;
++      struct snd_mask *fmt;
++
++      /* configure PCM or DSD */
++      fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
++      if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
++              /* embed DSD in PCM data */
++              snd_mask_none(fmt);
++              snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
++              /* enable DSD mode */
++              config |= NANO_CFG_DSD;
++      }
++
++      /* configure clocks */
++      switch (params_rate(params)) {
++      case 44100:
++              config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
++              break;
++      case 88200:
++              config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
++              break;
++      case 176400:
++              config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
++              break;
++      case 352800:
++              config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
++              break;
++      case 705600:
++              config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
++              break;
++      case 48000:
++              config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
++              break;
++      case 96000:
++              config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
++              break;
++      case 192000:
++              config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
++              break;
++      case 384000:
++              config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
++              break;
++      case 768000:
++              config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
++      return regmap_write(regmap, NANO_CFG, config);
++}
++
++static struct snd_soc_ops nano_player_ops = {
++      .startup        = nano_player_startup,
++      .hw_params      = nano_player_hw_params,
++};
++
++static struct snd_soc_dai_link nano_player_link = {
++      .name           = "3Dlab Nano Player",
++      .stream_name    = "3Dlab Nano Player HiFi",
++      .platform_name  = "bcm2708-i2s.0",
++      .cpu_dai_name   = "bcm2708-i2s.0",
++      .codec_name     = "snd-soc-dummy",
++      .codec_dai_name = "snd-soc-dummy-dai",
++      .dai_fmt        = SND_SOC_DAIFMT_I2S |
++                        SND_SOC_DAIFMT_CONT |
++                        SND_SOC_DAIFMT_NB_NF |
++                        SND_SOC_DAIFMT_CBM_CFM,
++      .init           = nano_player_init,
++      .ops            = &nano_player_ops,
++};
++
++static const struct regmap_config nano_player_regmap = {
++      .reg_bits       = 8,
++      .val_bits       = 8,
++      .max_register   = 128,
++      .cache_type     = REGCACHE_RBTREE,
++};
++
++static int nano_player_card_probe(struct snd_soc_card *card)
++{
++      struct regmap *regmap = snd_soc_card_get_drvdata(card);
++      unsigned int val;
++
++      /* check hardware integrity */
++      regmap_read(regmap, NANO_ID, &val);
++      if (val != NANO_ID_VAL) {
++              dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
++              return -ENODEV;
++      }
++
++      /* report version to the user */
++      regmap_read(regmap, NANO_VER, &val);
++      dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
++
++      /* enable internal audio bus and blink status LED */
++      return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
++}
++
++static int nano_player_card_remove(struct snd_soc_card *card)
++{
++      /* disable internal audio bus */
++      struct regmap *regmap = snd_soc_card_get_drvdata(card);
++
++      return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
++}
++
++static struct snd_soc_card nano_player_card = {
++      .name           = "3Dlab_Nano_Player",
++      .owner          = THIS_MODULE,
++      .dai_link       = &nano_player_link,
++      .num_links      = 1,
++      .controls       = nano_player_controls,
++      .num_controls   = ARRAY_SIZE(nano_player_controls),
++      .probe          = nano_player_card_probe,
++      .remove         = nano_player_card_remove,
++};
++
++static int nano_player_i2c_probe(struct i2c_client *i2c,
++                               const struct i2c_device_id *id)
++{
++      struct regmap *regmap;
++      int ret;
++
++      regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
++      if (IS_ERR(regmap)) {
++              ret = PTR_ERR(regmap);
++              dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
++              return ret;
++      }
++
++      if (i2c->dev.of_node) {
++              struct snd_soc_dai_link *dai = &nano_player_link;
++              struct device_node *node;
++
++              /* cpu handle configured by device tree */
++              node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
++              if (node) {
++                      dai->platform_name = NULL;
++                      dai->platform_of_node = node;
++                      dai->cpu_dai_name = NULL;
++                      dai->cpu_of_node = node;
++              }
++      }
++
++      nano_player_card.dev = &i2c->dev;
++      snd_soc_card_set_drvdata(&nano_player_card, regmap);
++      ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
++
++      if (ret && ret != -EPROBE_DEFER)
++              dev_err(&i2c->dev, "Failed to register card %d\n", ret);
++
++      return ret;
++}
++
++static const struct of_device_id nano_player_of_match[] = {
++      { .compatible = "3dlab,nano-player", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, nano_player_of_match);
++
++static const struct i2c_device_id nano_player_i2c_id[] = {
++      { "nano-player", 0 },
++      { }
++};
++MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
++
++static struct i2c_driver nano_player_i2c_driver = {
++      .probe          = nano_player_i2c_probe,
++      .id_table       = nano_player_i2c_id,
++      .driver         = {
++              .name           = "nano-player",
++              .owner          = THIS_MODULE,
++              .of_match_table = nano_player_of_match,
++      },
++};
++
++module_i2c_driver(nano_player_i2c_driver);
++
++MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
++MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
++MODULE_LICENSE("GPL v2");
++
++/* EOF */
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -17,6 +17,12 @@ config SND_SOC_CYGNUS
+         If you don't know what to do here, say N.
++config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
++      tristate "Support for 3Dlab Nano Player"
++      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++      help
++        Say Y or M if you want to add support for 3Dlab Nano Player.
++
+ config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
+       tristate "Support for Google voiceHAT soundcard"
+       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
+ snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
+ # BCM2708 Machine Support
++snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+@@ -31,6 +32,7 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
+ snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
+ snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
++obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.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
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
diff --git a/target/linux/brcm2708/patches-4.19/950-0250-tpm-Make-SECURITYFS-a-weak-dependency.patch b/target/linux/brcm2708/patches-4.19/950-0250-tpm-Make-SECURITYFS-a-weak-dependency.patch
deleted file mode 100644 (file)
index 7e86b09..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From 38e82adecd1b7ae790a827c29e954d35a2bbee98 Mon Sep 17 00:00:00 2001
-From: Peter Huewe <peterhuewe@gmx.de>
-Date: Mon, 3 Sep 2018 21:51:51 +0200
-Subject: [PATCH] tpm: Make SECURITYFS a weak dependency
-
-commit 2f7d8dbb11287cbe9da6380ca14ed5d38c9ed91f upstream.
-
-While having SECURITYFS enabled for the tpm subsystem is beneficial in
-most cases, it is not strictly necessary to have it enabled at all.
-Especially on platforms without any boot firmware integration of the TPM
-(e.g. raspberry pi) it does not add any value for the tpm subsystem,
-as there is no eventlog present.
-
-By turning it from 'select' to 'imply' it still gets selected per
-default, but enables users who want to save some kb of ram by turning
-SECURITYFS off.
-
-Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
-Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
-Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
----
- drivers/char/tpm/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/char/tpm/Kconfig
-+++ b/drivers/char/tpm/Kconfig
-@@ -5,7 +5,7 @@
- menuconfig TCG_TPM
-       tristate "TPM Hardware Support"
-       depends on HAS_IOMEM
--      select SECURITYFS
-+      imply SECURITYFS
-       select CRYPTO
-       select CRYPTO_HASH_INFO
-       ---help---
diff --git a/target/linux/brcm2708/patches-4.19/950-0251-Add-overlay-for-SLB9760-Iridium-LetsTrust-TPM.patch b/target/linux/brcm2708/patches-4.19/950-0251-Add-overlay-for-SLB9760-Iridium-LetsTrust-TPM.patch
deleted file mode 100644 (file)
index 16539aa..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-From 82298c670f768f392f48526fe7c8a93682e83998 Mon Sep 17 00:00:00 2001
-From: Peter Huewe <peterhuewe@gmx.de>
-Date: Thu, 14 Jun 2018 22:51:24 +0200
-Subject: [PATCH] Add overlay for SLB9760 Iridium /LetsTrust TPM
-
-Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
-boards, which can be used as a secure key storage and hwrng.
-available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by
-pi3g.
-
-Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             |  8 ++++
- .../boot/dts/overlays/tpm-slb9670-overlay.dts | 44 +++++++++++++++++++
- 3 files changed, 53 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -137,6 +137,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       tc358743.dtbo \
-       tc358743-audio.dtbo \
-       tinylcd35.dtbo \
-+      tpm-slb9670.dtbo \
-       uart0.dtbo \
-       uart1.dtbo \
-       upstream.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2012,6 +2012,14 @@ Params: speed                   Display
-                 dtoverlay=tinylcd35,touch,touchgpio=3
-+Name:   tpm-slb9670
-+Info:   Enables support for Infineon SLB9670 Trusted Platform Module add-on
-+        boards, which can be used as a secure key storage and hwrng,
-+        available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
-+Load:   dtoverlay=tpm-slb9670
-+Params: <None>
-+
-+
- Name:   uart0
- Info:   Change the pin usage of uart0
- Load:   dtoverlay=uart0,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-@@ -0,0 +1,44 @@
-+/*
-+ * Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
-+ * boards, which can be used as a secure key storage and hwrng.
-+ * available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+      fragment@0 {
-+              target = <&spi0>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spidev1>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&spi0>;
-+              __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      slb9670: slb9670@1 {
-+                              compatible = "infineon,slb9670";
-+                              reg = <1>;      /* CE1 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <32000000>;
-+                              status = "okay";
-+                      };
-+
-+              };
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0251-overlays-Update-README-with-removal-of-lirc-rpi.patch b/target/linux/brcm2708/patches-4.19/950-0251-overlays-Update-README-with-removal-of-lirc-rpi.patch
new file mode 100644 (file)
index 0000000..0216212
--- /dev/null
@@ -0,0 +1,91 @@
+From f2c24ce7e03d059fa9f674d8ebf6286e8f0c38b6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 5 Dec 2018 11:56:40 +0000
+Subject: [PATCH] overlays: Update README with removal of lirc-rpi
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 57 ++++++++++++-------------------
+ 1 file changed, 21 insertions(+), 36 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -56,23 +56,29 @@ have its contents deleted (or commented
+ Using Overlays
+ ==============
+-Overlays are loaded using the "dtoverlay" directive. As an example, consider
+-the popular lirc-rpi module, the Linux Infrared Remote Control driver. In the
+-pre-DT world this would be loaded from /etc/modules, with an explicit
+-"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled,
+-this becomes a line in config.txt:
+-
+-    dtoverlay=lirc-rpi
+-
+-This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By
+-default it will use GPIOs 17 (out) and 18 (in), but this can be modified using
+-DT parameters:
+-
+-    dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13
+-
+-Parameters always have default values, although in some cases (e.g. "w1-gpio")
+-it is necessary to provided multiple overlays in order to get the desired
+-behaviour. See the list of overlays below for a description of the parameters
++Overlays are loaded using the "dtoverlay" config.txt setting. As an example,
++consider I2C Real Time Clock drivers. In the pre-DT world these would be loaded
++by writing a magic string comprising a device identifier and an I2C address to
++a special file in /sys/class/i2c-adapter, having first loaded the driver for
++the I2C interface and the RTC device - something like this:
++
++    modprobe i2c-bcm2835
++    modprobe rtc-ds1307
++    echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
++
++With DT enabled, this becomes a line in config.txt:
++
++    dtoverlay=i2c-rtc,ds1307
++
++This causes the file /boot/overlays/i2c-rtc.dtbo to be loaded and a "node"
++describing the DS1307 I2C device to be added to the Device Tree for the Pi. By
++default it usees address 0x68, but this can be modified with an additional DT
++parameter:
++
++    dtoverlay=i2c-rtc,ds1307,addr=0x68
++
++Parameters usually have default values, although certain parameters are
++mandatory. See the list of overlays below for a description of the parameters
+ and their defaults.
+ The Overlay and Parameter Reference
+@@ -1135,29 +1141,8 @@ Params: <None>
+ Name:   lirc-rpi
+-Info:   Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi)
+-        Consult the module documentation for more details.
+-Load:   dtoverlay=lirc-rpi,<param>=<val>
+-Params: gpio_out_pin            GPIO for output (default "17")
+-
+-        gpio_in_pin             GPIO for input (default "18")
+-
+-        gpio_in_pull            Pull up/down/off on the input pin
+-                                (default "down")
+-
+-        sense                   Override the IR receive auto-detection logic:
+-                                 "0" = force active-high
+-                                 "1" = force active-low
+-                                 "-1" = use auto-detection
+-                                (default "-1")
+-
+-        softcarrier             Turn the software carrier "on" or "off"
+-                                (default "on")
+-
+-        invert                  "on" = invert the output pin (default "off")
+-
+-        debug                   "on" = enable additional debug messages
+-                                (default "off")
++Info:   This overlay has been deprecated and removed - see gpio-ir
++Load:   <Deprecated>
+ Name:   ltc294x
diff --git a/target/linux/brcm2708/patches-4.19/950-0252-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch b/target/linux/brcm2708/patches-4.19/950-0252-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch
deleted file mode 100644 (file)
index e335536..0000000
+++ /dev/null
@@ -1,483 +0,0 @@
-From e740bd2cc3fcd632fcd6c8881b1fc671bcde5914 Mon Sep 17 00:00:00 2001
-From: dev-3Dlab <45081440+dev-3Dlab@users.noreply.github.com>
-Date: Wed, 5 Dec 2018 10:59:11 +0100
-Subject: [PATCH] ASoC: add driver for 3Dlab Nano soundcard (#2758)
-
-Signed-off-by: GT <dev@3d-lab-av.com>
----
- .../overlays/3dlab-nano-player-overlay.dts    |  32 ++
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |   6 +
- sound/soc/bcm/3dlab-nano-player.c             | 370 ++++++++++++++++++
- sound/soc/bcm/Kconfig                         |   6 +
- sound/soc/bcm/Makefile                        |   2 +
- 8 files changed, 419 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
- create mode 100644 sound/soc/bcm/3dlab-nano-player.c
-
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
-@@ -0,0 +1,32 @@
-+// Definitions for 3Dlab Nano Player
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2708";
-+
-+      fragment@0 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      nano-player@41 {
-+                              compatible = "3dlab,nano-player";
-+                              reg = <0x41>;
-+                              i2s-controller = <&i2s>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+};
-+
-+// EOF
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -1,6 +1,7 @@
- # Overlays for the Raspberry Pi platform
- dtbo-$(CONFIG_ARCH_BCM2835) += \
-+      3dlab-nano-player.dtbo \
-       adau1977-adc.dtbo \
-       adau7002-simple.dtbo \
-       ads1015.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -199,6 +199,12 @@ Params:
-         and the other i2c baudrate parameters.
-+Name:   3dlab-nano-player
-+Info:   Configures the 3Dlab Nano Player
-+Load:   dtoverlay=3dlab-nano-player
-+Params: <None>
-+
-+
- Name:   adau1977-adc
- Info:   Overlay for activation of ADAU1977 ADC codec over I2C for control
-         and I2S for data.
---- /dev/null
-+++ b/sound/soc/bcm/3dlab-nano-player.c
-@@ -0,0 +1,370 @@
-+/*
-+ * 3Dlab Nano Player ALSA SoC Audio driver.
-+ *
-+ * Copyright (C) 2018 3Dlab.
-+ *
-+ * Author: GT <dev@3d-lab-av.com>
-+ *
-+ * 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/i2c.h>
-+#include <sound/soc.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/control.h>
-+
-+#define NANO_ID               0x00
-+#define NANO_VER      0x01
-+#define NANO_CFG      0x02
-+#define NANO_STATUS   0x03
-+#define NANO_SPI_ADDR 0x04
-+#define NANO_SPI_DATA 0x05
-+
-+#define NANO_ID_VAL   0x3D
-+#define NANO_CFG_OFF  0x00
-+#define NANO_CFG_MULT1        0
-+#define NANO_CFG_MULT2        1
-+#define NANO_CFG_MULT4        2
-+#define NANO_CFG_MULT8        3
-+#define NANO_CFG_MULT16       4
-+#define NANO_CFG_CLK22        0
-+#define NANO_CFG_CLK24        BIT(3)
-+#define NANO_CFG_DSD  BIT(4)
-+#define NANO_CFG_ENA  BIT(5)
-+#define NANO_CFG_BLINK        BIT(6)
-+#define NANO_STATUS_P1  BIT(0)
-+#define NANO_STATUS_P2  BIT(1)
-+#define NANO_STATUS_FLG BIT(2)
-+#define NANO_STATUS_CLK BIT(3)
-+#define NANO_SPI_READ 0
-+#define NANO_SPI_WRITE        BIT(5)
-+
-+#define NANO_DAC_CTRL1        0x00
-+#define NANO_DAC_CTRL2        0x01
-+#define NANO_DAC_CTRL3        0x02
-+#define NANO_DAC_LATT 0x03
-+#define NANO_DAC_RATT 0x04
-+
-+#define NANO_CTRL2_VAL        0x22
-+
-+static int nano_player_spi_write(struct regmap *map,
-+                               unsigned int reg, unsigned int val)
-+{
-+      /* indirect register access */
-+      regmap_write(map, NANO_SPI_DATA, val);
-+      regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
-+      return 0;
-+}
-+
-+static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
-+                               struct snd_ctl_elem_info *uinfo)
-+{
-+      /* describe control element */
-+      if (strstr(kcontrol->id.name, "Volume")) {
-+              uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-+              uinfo->count = 1;
-+              uinfo->value.integer.min = 0;
-+              uinfo->value.integer.max = 100;
-+      } else {
-+              uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-+              uinfo->count = 1;
-+              uinfo->value.integer.min = 0;
-+              uinfo->value.integer.max = 1;
-+      }
-+
-+      return 0;
-+}
-+
-+static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
-+                              struct snd_ctl_elem_value *ucontrol)
-+{
-+      /* program control value to hardware */
-+      struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
-+      struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+
-+      if (strstr(kcontrol->id.name, "Volume")) {
-+              unsigned int vol = ucontrol->value.integer.value[0];
-+              unsigned int att = 255 - (2 * (100 - vol));
-+
-+              nano_player_spi_write(regmap, NANO_DAC_LATT, att);
-+              nano_player_spi_write(regmap, NANO_DAC_RATT, att);
-+              kcontrol->private_value = vol;
-+      } else {
-+              unsigned int mute = ucontrol->value.integer.value[0];
-+              unsigned int reg = NANO_CTRL2_VAL | mute;
-+
-+              nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
-+              kcontrol->private_value = mute;
-+      }
-+      return 0;
-+}
-+
-+static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
-+                              struct snd_ctl_elem_value *ucontrol)
-+{
-+      /* return last programmed value */
-+      ucontrol->value.integer.value[0] = kcontrol->private_value;
-+      return 0;
-+}
-+
-+#define SOC_NANO_PLAYER_CTRL(xname) \
-+{     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-+      .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
-+      .info = nano_player_ctrl_info, \
-+      .put = nano_player_ctrl_put, \
-+      .get = nano_player_ctrl_get }
-+
-+static const struct snd_kcontrol_new nano_player_controls[] = {
-+      SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
-+      SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
-+};
-+
-+static const unsigned int nano_player_rates[] = {
-+      44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
-+      705600, 768000 /* only possible with fast clocks */
-+};
-+
-+static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
-+      .list   = nano_player_rates,
-+      .count  = ARRAY_SIZE(nano_player_rates),
-+};
-+
-+static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      struct snd_soc_card *card = rtd->card;
-+      struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+      struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
-+      struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
-+      unsigned int sample_bits = 32;
-+      unsigned int val;
-+
-+      /* configure cpu dai */
-+      cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
-+      cpu->rate_max = 768000;
-+
-+      /* configure dummy codec dai */
-+      codec->rate_min = 44100;
-+      codec->rates = SNDRV_PCM_RATE_KNOT;
-+      codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
-+
-+      /* configure max supported rate */
-+      regmap_read(regmap, NANO_STATUS, &val);
-+      if (val & NANO_STATUS_CLK) {
-+              dev_notice(card->dev, "Board with fast clocks installed\n");
-+              codec->rate_max = 768000;
-+      } else {
-+              dev_notice(card->dev, "Board with normal clocks installed\n");
-+              codec->rate_max = 384000;
-+      }
-+
-+      /* frame length enforced by hardware */
-+      return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
-+}
-+
-+static int nano_player_startup(struct snd_pcm_substream *substream)
-+{
-+      return snd_pcm_hw_constraint_list(substream->runtime, 0,
-+                                        SNDRV_PCM_HW_PARAM_RATE,
-+                                        &nano_player_constraint_rates);
-+}
-+
-+static int nano_player_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_card *card = rtd->card;
-+      struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+      unsigned int config = NANO_CFG_ENA;
-+      struct snd_mask *fmt;
-+
-+      /* configure PCM or DSD */
-+      fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-+      if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
-+              /* embed DSD in PCM data */
-+              snd_mask_none(fmt);
-+              snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
-+              /* enable DSD mode */
-+              config |= NANO_CFG_DSD;
-+      }
-+
-+      /* configure clocks */
-+      switch (params_rate(params)) {
-+      case 44100:
-+              config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
-+              break;
-+      case 88200:
-+              config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
-+              break;
-+      case 176400:
-+              config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
-+              break;
-+      case 352800:
-+              config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
-+              break;
-+      case 705600:
-+              config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
-+              break;
-+      case 48000:
-+              config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
-+              break;
-+      case 96000:
-+              config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
-+              break;
-+      case 192000:
-+              config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
-+              break;
-+      case 384000:
-+              config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
-+              break;
-+      case 768000:
-+              config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
-+      return regmap_write(regmap, NANO_CFG, config);
-+}
-+
-+static struct snd_soc_ops nano_player_ops = {
-+      .startup        = nano_player_startup,
-+      .hw_params      = nano_player_hw_params,
-+};
-+
-+static struct snd_soc_dai_link nano_player_link = {
-+      .name           = "3Dlab Nano Player",
-+      .stream_name    = "3Dlab Nano Player HiFi",
-+      .platform_name  = "bcm2708-i2s.0",
-+      .cpu_dai_name   = "bcm2708-i2s.0",
-+      .codec_name     = "snd-soc-dummy",
-+      .codec_dai_name = "snd-soc-dummy-dai",
-+      .dai_fmt        = SND_SOC_DAIFMT_I2S |
-+                        SND_SOC_DAIFMT_CONT |
-+                        SND_SOC_DAIFMT_NB_NF |
-+                        SND_SOC_DAIFMT_CBM_CFM,
-+      .init           = nano_player_init,
-+      .ops            = &nano_player_ops,
-+};
-+
-+static const struct regmap_config nano_player_regmap = {
-+      .reg_bits       = 8,
-+      .val_bits       = 8,
-+      .max_register   = 128,
-+      .cache_type     = REGCACHE_RBTREE,
-+};
-+
-+static int nano_player_card_probe(struct snd_soc_card *card)
-+{
-+      struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+      unsigned int val;
-+
-+      /* check hardware integrity */
-+      regmap_read(regmap, NANO_ID, &val);
-+      if (val != NANO_ID_VAL) {
-+              dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
-+              return -ENODEV;
-+      }
-+
-+      /* report version to the user */
-+      regmap_read(regmap, NANO_VER, &val);
-+      dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
-+
-+      /* enable internal audio bus and blink status LED */
-+      return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
-+}
-+
-+static int nano_player_card_remove(struct snd_soc_card *card)
-+{
-+      /* disable internal audio bus */
-+      struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+
-+      return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
-+}
-+
-+static struct snd_soc_card nano_player_card = {
-+      .name           = "3Dlab_Nano_Player",
-+      .owner          = THIS_MODULE,
-+      .dai_link       = &nano_player_link,
-+      .num_links      = 1,
-+      .controls       = nano_player_controls,
-+      .num_controls   = ARRAY_SIZE(nano_player_controls),
-+      .probe          = nano_player_card_probe,
-+      .remove         = nano_player_card_remove,
-+};
-+
-+static int nano_player_i2c_probe(struct i2c_client *i2c,
-+                               const struct i2c_device_id *id)
-+{
-+      struct regmap *regmap;
-+      int ret;
-+
-+      regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
-+      if (IS_ERR(regmap)) {
-+              ret = PTR_ERR(regmap);
-+              dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
-+              return ret;
-+      }
-+
-+      if (i2c->dev.of_node) {
-+              struct snd_soc_dai_link *dai = &nano_player_link;
-+              struct device_node *node;
-+
-+              /* cpu handle configured by device tree */
-+              node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
-+              if (node) {
-+                      dai->platform_name = NULL;
-+                      dai->platform_of_node = node;
-+                      dai->cpu_dai_name = NULL;
-+                      dai->cpu_of_node = node;
-+              }
-+      }
-+
-+      nano_player_card.dev = &i2c->dev;
-+      snd_soc_card_set_drvdata(&nano_player_card, regmap);
-+      ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
-+
-+      if (ret && ret != -EPROBE_DEFER)
-+              dev_err(&i2c->dev, "Failed to register card %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static const struct of_device_id nano_player_of_match[] = {
-+      { .compatible = "3dlab,nano-player", },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(of, nano_player_of_match);
-+
-+static const struct i2c_device_id nano_player_i2c_id[] = {
-+      { "nano-player", 0 },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
-+
-+static struct i2c_driver nano_player_i2c_driver = {
-+      .probe          = nano_player_i2c_probe,
-+      .id_table       = nano_player_i2c_id,
-+      .driver         = {
-+              .name           = "nano-player",
-+              .owner          = THIS_MODULE,
-+              .of_match_table = nano_player_of_match,
-+      },
-+};
-+
-+module_i2c_driver(nano_player_i2c_driver);
-+
-+MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
-+MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
-+MODULE_LICENSE("GPL v2");
-+
-+/* EOF */
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -17,6 +17,12 @@ config SND_SOC_CYGNUS
-         If you don't know what to do here, say N.
-+config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
-+      tristate "Support for 3Dlab Nano Player"
-+      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+      help
-+        Say Y or M if you want to add support for 3Dlab Nano Player.
-+
- config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
-       tristate "Support for Google voiceHAT soundcard"
-       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
- snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
- # BCM2708 Machine Support
-+snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
-@@ -31,6 +32,7 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
- snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
- snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
-+obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.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
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
diff --git a/target/linux/brcm2708/patches-4.19/950-0252-staging-bcm2835-camera-Check-the-error-for-REPEAT_SE.patch b/target/linux/brcm2708/patches-4.19/950-0252-staging-bcm2835-camera-Check-the-error-for-REPEAT_SE.patch
new file mode 100644 (file)
index 0000000..40260a6
--- /dev/null
@@ -0,0 +1,31 @@
+From 81f6d4e84fd127cf0b31c9822a2beb9b298aa7bb Mon Sep 17 00:00:00 2001
+From: 6by9 <6by9@users.noreply.github.com>
+Date: Tue, 11 Dec 2018 15:18:02 +0000
+Subject: [PATCH] staging: bcm2835-camera: Check the error for
+ REPEAT_SEQ_HEADER (#2782)
+
+When handling for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER was added
+the firmware would reject the setting if H264 hadn't already been
+selected. This was fixed in the firmware at that point, but to
+enable backwards compatibility the returned error was ignored.
+
+That was Dec 2013, so the chances of having a firmware that still
+has that issue is so close to zero that the workaround can be
+removed.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -1100,7 +1100,7 @@ static const struct bm2835_mmal_v4l2_ctr
+               0, 1, NULL,
+               MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
+               &ctrl_set_video_encode_param_output,
+-              true    /* Errors ignored as requires latest firmware to work */
++              false
+       },
+       {
+               V4L2_CID_MPEG_VIDEO_H264_PROFILE,
diff --git a/target/linux/brcm2708/patches-4.19/950-0253-gpio-ir-change-default-pull-configuration-to-up.patch b/target/linux/brcm2708/patches-4.19/950-0253-gpio-ir-change-default-pull-configuration-to-up.patch
new file mode 100644 (file)
index 0000000..40bfc01
--- /dev/null
@@ -0,0 +1,47 @@
+From d1cf5fb57ee5ee4512a93614d67d15af9c8070b2 Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Wed, 9 Jan 2019 14:51:01 +0100
+Subject: [PATCH] gpio-ir: change default pull configuration to up
+
+IR receivers like the TSOP series from Vishay and compatible ones
+have active-low open collector outputs with an internal pull up of
+about 30k (according to the TSOP datasheets).
+
+Activating a pull-down resistor on the GPIO will make it work against
+the pull-up in the IR receiver and brings the idle input voltage down
+to about 1.9V (measured on a RPi3B+ with a TSOP4438). While that's
+usually enough to make the RPi see a high signal it's certainly not
+optimal and may even fail when using an IR receiver with a weaker pull-up.
+
+Switching the default GPIO pull to "up" results in an input voltage
+level of about 3.3V and ensures that an idle state (high signal) will
+be detected if no IR receiver is attached.
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ arch/arm/boot/dts/overlays/README              | 2 +-
+ arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -611,7 +611,7 @@ Load:   dtoverlay=gpio-ir,<param>=<val>
+ Params: gpio_pin                Input pin number. Default is 18.
+         gpio_pull               Desired pull-up/down state (off, down, up)
+-                                Default is "down".
++                                Default is "up".
+         rc-map-name             Default rc keymap (can also be changed by
+                                 ir-keytable), defaults to "rc-rc6-mce"
+--- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
+@@ -30,7 +30,7 @@
+                         gpio_ir_pins: gpio_ir_pins@12 {
+                                 brcm,pins = <18>;                       // pin 18
+                                 brcm,function = <0>;                    // in
+-                                brcm,pull = <1>;                        // down
++                                brcm,pull = <2>;                        // up
+                         };
+                 };
+         };
diff --git a/target/linux/brcm2708/patches-4.19/950-0253-overlays-Update-README-with-removal-of-lirc-rpi.patch b/target/linux/brcm2708/patches-4.19/950-0253-overlays-Update-README-with-removal-of-lirc-rpi.patch
deleted file mode 100644 (file)
index 0216212..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-From f2c24ce7e03d059fa9f674d8ebf6286e8f0c38b6 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 5 Dec 2018 11:56:40 +0000
-Subject: [PATCH] overlays: Update README with removal of lirc-rpi
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 57 ++++++++++++-------------------
- 1 file changed, 21 insertions(+), 36 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -56,23 +56,29 @@ have its contents deleted (or commented
- Using Overlays
- ==============
--Overlays are loaded using the "dtoverlay" directive. As an example, consider
--the popular lirc-rpi module, the Linux Infrared Remote Control driver. In the
--pre-DT world this would be loaded from /etc/modules, with an explicit
--"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled,
--this becomes a line in config.txt:
--
--    dtoverlay=lirc-rpi
--
--This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By
--default it will use GPIOs 17 (out) and 18 (in), but this can be modified using
--DT parameters:
--
--    dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13
--
--Parameters always have default values, although in some cases (e.g. "w1-gpio")
--it is necessary to provided multiple overlays in order to get the desired
--behaviour. See the list of overlays below for a description of the parameters
-+Overlays are loaded using the "dtoverlay" config.txt setting. As an example,
-+consider I2C Real Time Clock drivers. In the pre-DT world these would be loaded
-+by writing a magic string comprising a device identifier and an I2C address to
-+a special file in /sys/class/i2c-adapter, having first loaded the driver for
-+the I2C interface and the RTC device - something like this:
-+
-+    modprobe i2c-bcm2835
-+    modprobe rtc-ds1307
-+    echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
-+
-+With DT enabled, this becomes a line in config.txt:
-+
-+    dtoverlay=i2c-rtc,ds1307
-+
-+This causes the file /boot/overlays/i2c-rtc.dtbo to be loaded and a "node"
-+describing the DS1307 I2C device to be added to the Device Tree for the Pi. By
-+default it usees address 0x68, but this can be modified with an additional DT
-+parameter:
-+
-+    dtoverlay=i2c-rtc,ds1307,addr=0x68
-+
-+Parameters usually have default values, although certain parameters are
-+mandatory. See the list of overlays below for a description of the parameters
- and their defaults.
- The Overlay and Parameter Reference
-@@ -1135,29 +1141,8 @@ Params: <None>
- Name:   lirc-rpi
--Info:   Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi)
--        Consult the module documentation for more details.
--Load:   dtoverlay=lirc-rpi,<param>=<val>
--Params: gpio_out_pin            GPIO for output (default "17")
--
--        gpio_in_pin             GPIO for input (default "18")
--
--        gpio_in_pull            Pull up/down/off on the input pin
--                                (default "down")
--
--        sense                   Override the IR receive auto-detection logic:
--                                 "0" = force active-high
--                                 "1" = force active-low
--                                 "-1" = use auto-detection
--                                (default "-1")
--
--        softcarrier             Turn the software carrier "on" or "off"
--                                (default "on")
--
--        invert                  "on" = invert the output pin (default "off")
--
--        debug                   "on" = enable additional debug messages
--                                (default "off")
-+Info:   This overlay has been deprecated and removed - see gpio-ir
-+Load:   <Deprecated>
- Name:   ltc294x
diff --git a/target/linux/brcm2708/patches-4.19/950-0254-firmware-raspberrypi-Report-the-fw-variant-during-pr.patch b/target/linux/brcm2708/patches-4.19/950-0254-firmware-raspberrypi-Report-the-fw-variant-during-pr.patch
new file mode 100644 (file)
index 0000000..a41e46b
--- /dev/null
@@ -0,0 +1,79 @@
+From dfd66230d2d538e7f290436d2952124d6eadeb3d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 10 Jan 2019 17:58:06 +0000
+Subject: [PATCH] firmware: raspberrypi: Report the fw variant during
+ probe
+
+The driver already reported the firmware build date during probe.
+The mailbox calls have been extended to also report the variant
+ 1 = standard start.elf
+ 2 = start_x.elf (includes camera stack)
+ 3 = start_db.elf (includes assert logging)
+ 4 = start_cd.elf (cutdown version for smallest memory footprint).
+Log the variant during probe.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/firmware/raspberrypi.c             | 32 +++++++++++++++++-----
+ include/soc/bcm2835/raspberrypi-firmware.h |  1 +
+ 2 files changed, 26 insertions(+), 7 deletions(-)
+
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -227,21 +227,39 @@ static const struct attribute_group rpi_
+ static void
+ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
+ {
++      static const char * const variant_strs[] = {
++              "unknown",
++              "start",
++              "start_x",
++              "start_db",
++              "start_cd",
++      };
++      const char *variant_str = "cmd unsupported";
+       u32 packet;
++      u32 variant;
++      struct tm tm;
+       int ret = rpi_firmware_property(fw,
+                                       RPI_FIRMWARE_GET_FIRMWARE_REVISION,
+                                       &packet, sizeof(packet));
+-      if (ret == 0) {
+-              struct tm tm;
++      if (ret)
++              return;
+-              time64_to_tm(packet, 0, &tm);
++      ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_FIRMWARE_VARIANT,
++                                  &variant, sizeof(variant));
+-              dev_info(fw->cl.dev,
+-                       "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n",
+-                       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+-                       tm.tm_hour, tm.tm_min);
++      if (!ret) {
++              if (variant >= ARRAY_SIZE(variant_strs))
++                      variant = 0;
++              variant_str = variant_strs[variant];
+       }
++
++      time64_to_tm(packet, 0, &tm);
++
++      dev_info(fw->cl.dev,
++               "Attached to firmware from %04ld-%02d-%02d %02d:%02d, variant %s\n",
++               tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
++               tm.tm_min, variant_str);
+ }
+ static void
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -41,6 +41,7 @@ struct rpi_firmware_property_tag_header
+ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_PROPERTY_END =                           0,
+       RPI_FIRMWARE_GET_FIRMWARE_REVISION =                  0x00000001,
++      RPI_FIRMWARE_GET_FIRMWARE_VARIANT =                   0x00000002,
+       RPI_FIRMWARE_SET_CURSOR_INFO =                        0x00008010,
+       RPI_FIRMWARE_SET_CURSOR_STATE =                       0x00008011,
diff --git a/target/linux/brcm2708/patches-4.19/950-0254-staging-bcm2835-camera-Check-the-error-for-REPEAT_SE.patch b/target/linux/brcm2708/patches-4.19/950-0254-staging-bcm2835-camera-Check-the-error-for-REPEAT_SE.patch
deleted file mode 100644 (file)
index 40260a6..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 81f6d4e84fd127cf0b31c9822a2beb9b298aa7bb Mon Sep 17 00:00:00 2001
-From: 6by9 <6by9@users.noreply.github.com>
-Date: Tue, 11 Dec 2018 15:18:02 +0000
-Subject: [PATCH] staging: bcm2835-camera: Check the error for
- REPEAT_SEQ_HEADER (#2782)
-
-When handling for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER was added
-the firmware would reject the setting if H264 hadn't already been
-selected. This was fixed in the firmware at that point, but to
-enable backwards compatibility the returned error was ignored.
-
-That was Dec 2013, so the chances of having a firmware that still
-has that issue is so close to zero that the workaround can be
-removed.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -1100,7 +1100,7 @@ static const struct bm2835_mmal_v4l2_ctr
-               0, 1, NULL,
-               MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
-               &ctrl_set_video_encode_param_output,
--              true    /* Errors ignored as requires latest firmware to work */
-+              false
-       },
-       {
-               V4L2_CID_MPEG_VIDEO_H264_PROFILE,
diff --git a/target/linux/brcm2708/patches-4.19/950-0255-firmware-raspberrypi-Report-the-fw-git-hash-during-p.patch b/target/linux/brcm2708/patches-4.19/950-0255-firmware-raspberrypi-Report-the-fw-git-hash-during-p.patch
new file mode 100644 (file)
index 0000000..84d8a89
--- /dev/null
@@ -0,0 +1,58 @@
+From 9abde0ff52268580501b3120629f3c92f0e5d589 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 10 Jan 2019 18:48:54 +0000
+Subject: [PATCH] firmware: raspberrypi: Report the fw git hash during
+ probe
+
+The firmware can now report the git hash from which it was built
+via the mailbox, so report it during probe.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/firmware/raspberrypi.c             | 17 +++++++++++++++++
+ include/soc/bcm2835/raspberrypi-firmware.h |  1 +
+ 2 files changed, 18 insertions(+)
+
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -263,6 +263,22 @@ rpi_firmware_print_firmware_revision(str
+ }
+ static void
++rpi_firmware_print_firmware_hash(struct rpi_firmware *fw)
++{
++      u32 hash[5];
++      int ret = rpi_firmware_property(fw,
++                                      RPI_FIRMWARE_GET_FIRMWARE_HASH,
++                                      hash, sizeof(hash));
++
++      if (ret)
++              return;
++
++      dev_info(fw->cl.dev,
++               "Firmware hash is %08x%08x%08x%08x%08x\n",
++               hash[0], hash[1], hash[2], hash[3], hash[4]);
++}
++
++static void
+ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
+ {
+       u32 packet;
+@@ -308,6 +324,7 @@ static int rpi_firmware_probe(struct pla
+       g_pdev = pdev;
+       rpi_firmware_print_firmware_revision(fw);
++      rpi_firmware_print_firmware_hash(fw);
+       rpi_register_hwmon_driver(dev, fw);
+       return 0;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -42,6 +42,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_PROPERTY_END =                           0,
+       RPI_FIRMWARE_GET_FIRMWARE_REVISION =                  0x00000001,
+       RPI_FIRMWARE_GET_FIRMWARE_VARIANT =                   0x00000002,
++      RPI_FIRMWARE_GET_FIRMWARE_HASH =                      0x00000003,
+       RPI_FIRMWARE_SET_CURSOR_INFO =                        0x00008010,
+       RPI_FIRMWARE_SET_CURSOR_STATE =                       0x00008011,
diff --git a/target/linux/brcm2708/patches-4.19/950-0255-gpio-ir-change-default-pull-configuration-to-up.patch b/target/linux/brcm2708/patches-4.19/950-0255-gpio-ir-change-default-pull-configuration-to-up.patch
deleted file mode 100644 (file)
index 40bfc01..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From d1cf5fb57ee5ee4512a93614d67d15af9c8070b2 Mon Sep 17 00:00:00 2001
-From: Matthias Reichl <hias@horus.com>
-Date: Wed, 9 Jan 2019 14:51:01 +0100
-Subject: [PATCH] gpio-ir: change default pull configuration to up
-
-IR receivers like the TSOP series from Vishay and compatible ones
-have active-low open collector outputs with an internal pull up of
-about 30k (according to the TSOP datasheets).
-
-Activating a pull-down resistor on the GPIO will make it work against
-the pull-up in the IR receiver and brings the idle input voltage down
-to about 1.9V (measured on a RPi3B+ with a TSOP4438). While that's
-usually enough to make the RPi see a high signal it's certainly not
-optimal and may even fail when using an IR receiver with a weaker pull-up.
-
-Switching the default GPIO pull to "up" results in an input voltage
-level of about 3.3V and ensures that an idle state (high signal) will
-be detected if no IR receiver is attached.
-
-Signed-off-by: Matthias Reichl <hias@horus.com>
----
- arch/arm/boot/dts/overlays/README              | 2 +-
- arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -611,7 +611,7 @@ Load:   dtoverlay=gpio-ir,<param>=<val>
- Params: gpio_pin                Input pin number. Default is 18.
-         gpio_pull               Desired pull-up/down state (off, down, up)
--                                Default is "down".
-+                                Default is "up".
-         rc-map-name             Default rc keymap (can also be changed by
-                                 ir-keytable), defaults to "rc-rc6-mce"
---- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-@@ -30,7 +30,7 @@
-                         gpio_ir_pins: gpio_ir_pins@12 {
-                                 brcm,pins = <18>;                       // pin 18
-                                 brcm,function = <0>;                    // in
--                                brcm,pull = <1>;                        // down
-+                                brcm,pull = <2>;                        // up
-                         };
-                 };
-         };
diff --git a/target/linux/brcm2708/patches-4.19/950-0256-arm64-dts-broadcom-Enable-fixups-for-overlays.patch b/target/linux/brcm2708/patches-4.19/950-0256-arm64-dts-broadcom-Enable-fixups-for-overlays.patch
new file mode 100644 (file)
index 0000000..96d2ad4
--- /dev/null
@@ -0,0 +1,23 @@
+From bb8f38337d08dc1ac78ab251aa0b515eea45a79e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 15 Jan 2019 09:56:41 +0000
+Subject: [PATCH] arm64: dts: broadcom: Enable fixups for overlays
+
+See: https://github.com/raspberrypi/linux/pull/2733
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm64/boot/dts/broadcom/Makefile | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -9,3 +9,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rp
+ subdir-y      += northstar2
+ subdir-y      += stingray
++
++# Enable fixups to support overlays on BCM2835 platforms
++ifeq ($(CONFIG_ARCH_BCM2835),y)
++      DTC_FLAGS ?= -@
++endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0256-firmware-raspberrypi-Report-the-fw-variant-during-pr.patch b/target/linux/brcm2708/patches-4.19/950-0256-firmware-raspberrypi-Report-the-fw-variant-during-pr.patch
deleted file mode 100644 (file)
index a41e46b..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-From dfd66230d2d538e7f290436d2952124d6eadeb3d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 10 Jan 2019 17:58:06 +0000
-Subject: [PATCH] firmware: raspberrypi: Report the fw variant during
- probe
-
-The driver already reported the firmware build date during probe.
-The mailbox calls have been extended to also report the variant
- 1 = standard start.elf
- 2 = start_x.elf (includes camera stack)
- 3 = start_db.elf (includes assert logging)
- 4 = start_cd.elf (cutdown version for smallest memory footprint).
-Log the variant during probe.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/firmware/raspberrypi.c             | 32 +++++++++++++++++-----
- include/soc/bcm2835/raspberrypi-firmware.h |  1 +
- 2 files changed, 26 insertions(+), 7 deletions(-)
-
---- a/drivers/firmware/raspberrypi.c
-+++ b/drivers/firmware/raspberrypi.c
-@@ -227,21 +227,39 @@ static const struct attribute_group rpi_
- static void
- rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
- {
-+      static const char * const variant_strs[] = {
-+              "unknown",
-+              "start",
-+              "start_x",
-+              "start_db",
-+              "start_cd",
-+      };
-+      const char *variant_str = "cmd unsupported";
-       u32 packet;
-+      u32 variant;
-+      struct tm tm;
-       int ret = rpi_firmware_property(fw,
-                                       RPI_FIRMWARE_GET_FIRMWARE_REVISION,
-                                       &packet, sizeof(packet));
--      if (ret == 0) {
--              struct tm tm;
-+      if (ret)
-+              return;
--              time64_to_tm(packet, 0, &tm);
-+      ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_FIRMWARE_VARIANT,
-+                                  &variant, sizeof(variant));
--              dev_info(fw->cl.dev,
--                       "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n",
--                       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
--                       tm.tm_hour, tm.tm_min);
-+      if (!ret) {
-+              if (variant >= ARRAY_SIZE(variant_strs))
-+                      variant = 0;
-+              variant_str = variant_strs[variant];
-       }
-+
-+      time64_to_tm(packet, 0, &tm);
-+
-+      dev_info(fw->cl.dev,
-+               "Attached to firmware from %04ld-%02d-%02d %02d:%02d, variant %s\n",
-+               tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
-+               tm.tm_min, variant_str);
- }
- static void
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -41,6 +41,7 @@ struct rpi_firmware_property_tag_header
- enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_PROPERTY_END =                           0,
-       RPI_FIRMWARE_GET_FIRMWARE_REVISION =                  0x00000001,
-+      RPI_FIRMWARE_GET_FIRMWARE_VARIANT =                   0x00000002,
-       RPI_FIRMWARE_SET_CURSOR_INFO =                        0x00008010,
-       RPI_FIRMWARE_SET_CURSOR_STATE =                       0x00008011,
diff --git a/target/linux/brcm2708/patches-4.19/950-0257-dtoverlays-fe-pi-audio-fix-sgtl5000-compatible-strin.patch b/target/linux/brcm2708/patches-4.19/950-0257-dtoverlays-fe-pi-audio-fix-sgtl5000-compatible-strin.patch
new file mode 100644 (file)
index 0000000..09ff03e
--- /dev/null
@@ -0,0 +1,27 @@
+From 1d26e4d72f2d0563cc6455e682a5d4c491de178c Mon Sep 17 00:00:00 2001
+From: Ben Wolsieffer <benwolsieffer@gmail.com>
+Date: Sun, 9 Dec 2018 16:46:00 -0500
+Subject: [PATCH] dtoverlays: fe-pi-audio: fix sgtl5000 compatible
+ string
+
+The compatible string was set to "fepi,sgtl5000", which worked for some
+reason in 4.14, but does not work in 4.19, presumably due to some
+change in the kernel matching logic. The correct string is
+"fsl,sgtl5000".
+
+Signed-off-by: Ben Wolsieffer <benwolsieffer@gmail.com>
+---
+ arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
+@@ -39,7 +39,7 @@
+                       sgtl5000@0a {
+                               #sound-dai-cells = <0>;
+-                              compatible = "fepi,sgtl5000";
++                              compatible = "fsl,sgtl5000";
+                               reg = <0x0a>;
+                               clocks = <&sgtl5000_mclk>;
+                               micbias-resistor-k-ohms = <2>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0257-firmware-raspberrypi-Report-the-fw-git-hash-during-p.patch b/target/linux/brcm2708/patches-4.19/950-0257-firmware-raspberrypi-Report-the-fw-git-hash-during-p.patch
deleted file mode 100644 (file)
index 84d8a89..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 9abde0ff52268580501b3120629f3c92f0e5d589 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 10 Jan 2019 18:48:54 +0000
-Subject: [PATCH] firmware: raspberrypi: Report the fw git hash during
- probe
-
-The firmware can now report the git hash from which it was built
-via the mailbox, so report it during probe.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/firmware/raspberrypi.c             | 17 +++++++++++++++++
- include/soc/bcm2835/raspberrypi-firmware.h |  1 +
- 2 files changed, 18 insertions(+)
-
---- a/drivers/firmware/raspberrypi.c
-+++ b/drivers/firmware/raspberrypi.c
-@@ -263,6 +263,22 @@ rpi_firmware_print_firmware_revision(str
- }
- static void
-+rpi_firmware_print_firmware_hash(struct rpi_firmware *fw)
-+{
-+      u32 hash[5];
-+      int ret = rpi_firmware_property(fw,
-+                                      RPI_FIRMWARE_GET_FIRMWARE_HASH,
-+                                      hash, sizeof(hash));
-+
-+      if (ret)
-+              return;
-+
-+      dev_info(fw->cl.dev,
-+               "Firmware hash is %08x%08x%08x%08x%08x\n",
-+               hash[0], hash[1], hash[2], hash[3], hash[4]);
-+}
-+
-+static void
- rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
- {
-       u32 packet;
-@@ -308,6 +324,7 @@ static int rpi_firmware_probe(struct pla
-       g_pdev = pdev;
-       rpi_firmware_print_firmware_revision(fw);
-+      rpi_firmware_print_firmware_hash(fw);
-       rpi_register_hwmon_driver(dev, fw);
-       return 0;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -42,6 +42,7 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_PROPERTY_END =                           0,
-       RPI_FIRMWARE_GET_FIRMWARE_REVISION =                  0x00000001,
-       RPI_FIRMWARE_GET_FIRMWARE_VARIANT =                   0x00000002,
-+      RPI_FIRMWARE_GET_FIRMWARE_HASH =                      0x00000003,
-       RPI_FIRMWARE_SET_CURSOR_INFO =                        0x00008010,
-       RPI_FIRMWARE_SET_CURSOR_STATE =                       0x00008011,
diff --git a/target/linux/brcm2708/patches-4.19/950-0258-arm64-dts-broadcom-Enable-fixups-for-overlays.patch b/target/linux/brcm2708/patches-4.19/950-0258-arm64-dts-broadcom-Enable-fixups-for-overlays.patch
deleted file mode 100644 (file)
index 96d2ad4..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From bb8f38337d08dc1ac78ab251aa0b515eea45a79e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 15 Jan 2019 09:56:41 +0000
-Subject: [PATCH] arm64: dts: broadcom: Enable fixups for overlays
-
-See: https://github.com/raspberrypi/linux/pull/2733
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm64/boot/dts/broadcom/Makefile | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/arch/arm64/boot/dts/broadcom/Makefile
-+++ b/arch/arm64/boot/dts/broadcom/Makefile
-@@ -9,3 +9,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rp
- subdir-y      += northstar2
- subdir-y      += stingray
-+
-+# Enable fixups to support overlays on BCM2835 platforms
-+ifeq ($(CONFIG_ARCH_BCM2835),y)
-+      DTC_FLAGS ?= -@
-+endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0258-bcm2835_smi-re-add-dereference-to-fix-DMA-transfers.patch b/target/linux/brcm2708/patches-4.19/950-0258-bcm2835_smi-re-add-dereference-to-fix-DMA-transfers.patch
new file mode 100644 (file)
index 0000000..37f1cb5
--- /dev/null
@@ -0,0 +1,20 @@
+From e5111d81c8efc17d8d585510980d3fe49c998741 Mon Sep 17 00:00:00 2001
+From: Ezekiel Bethel <zek@9net.org>
+Date: Wed, 12 Dec 2018 19:11:13 +0000
+Subject: [PATCH] bcm2835_smi: re-add dereference to fix DMA transfers
+
+---
+ drivers/misc/bcm2835_smi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/misc/bcm2835_smi.c
++++ b/drivers/misc/bcm2835_smi.c
+@@ -879,7 +879,7 @@ static int bcm2835_smi_probe(struct plat
+               goto err;
+       }
+       addr = of_get_address(node, 0, NULL, NULL);
+-      inst->smi_regs_busaddr = be32_to_cpu(addr);
++      inst->smi_regs_busaddr = be32_to_cpu(*addr);
+       err = bcm2835_smi_dma_setup(inst);
+       if (err)
diff --git a/target/linux/brcm2708/patches-4.19/950-0259-dtoverlays-fe-pi-audio-fix-sgtl5000-compatible-strin.patch b/target/linux/brcm2708/patches-4.19/950-0259-dtoverlays-fe-pi-audio-fix-sgtl5000-compatible-strin.patch
deleted file mode 100644 (file)
index 09ff03e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 1d26e4d72f2d0563cc6455e682a5d4c491de178c Mon Sep 17 00:00:00 2001
-From: Ben Wolsieffer <benwolsieffer@gmail.com>
-Date: Sun, 9 Dec 2018 16:46:00 -0500
-Subject: [PATCH] dtoverlays: fe-pi-audio: fix sgtl5000 compatible
- string
-
-The compatible string was set to "fepi,sgtl5000", which worked for some
-reason in 4.14, but does not work in 4.19, presumably due to some
-change in the kernel matching logic. The correct string is
-"fsl,sgtl5000".
-
-Signed-off-by: Ben Wolsieffer <benwolsieffer@gmail.com>
----
- arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-@@ -39,7 +39,7 @@
-                       sgtl5000@0a {
-                               #sound-dai-cells = <0>;
--                              compatible = "fepi,sgtl5000";
-+                              compatible = "fsl,sgtl5000";
-                               reg = <0x0a>;
-                               clocks = <&sgtl5000_mclk>;
-                               micbias-resistor-k-ohms = <2>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0259-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch b/target/linux/brcm2708/patches-4.19/950-0259-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch
new file mode 100644 (file)
index 0000000..395934d
--- /dev/null
@@ -0,0 +1,44 @@
+From 020ee4d0d438b830ee40da8d9d3414de156a11e7 Mon Sep 17 00:00:00 2001
+From: Joshua Emele <jemele@acm.org>
+Date: Wed, 7 Nov 2018 16:07:40 -0800
+Subject: [PATCH] lan78xx: Debounce link events to minimize poll storm
+
+The bInterval is set to 4 (i.e. 8 microframes => 1ms) and the only bit
+that the driver pays attention to is "link was reset". If there's a
+flapping status bit in that endpoint data, (such as if PHY negotiation
+needs a few tries to get a stable link) then polling at a slower rate
+would act as a de-bounce.
+
+See: https://github.com/raspberrypi/linux/issues/2447
+---
+ drivers/net/usb/lan78xx.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -449,6 +449,11 @@ static bool enable_tso;
+ module_param(enable_tso, bool, 0644);
+ MODULE_PARM_DESC(enable_tso, "Enables TCP segmentation offload");
++#define INT_URB_MICROFRAMES_PER_MS    8
++static int int_urb_interval_ms = 8;
++module_param(int_urb_interval_ms, int, 0);
++MODULE_PARM_DESC(int_urb_interval_ms, "Override usb interrupt urb interval");
++
+ static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
+ {
+       u32 *buf = kmalloc(sizeof(u32), GFP_KERNEL);
+@@ -3838,7 +3843,12 @@ static int lan78xx_probe(struct usb_inte
+       dev->pipe_intr = usb_rcvintpipe(dev->udev,
+                                       dev->ep_intr->desc.bEndpointAddress &
+                                       USB_ENDPOINT_NUMBER_MASK);
+-      period = dev->ep_intr->desc.bInterval;
++      if (int_urb_interval_ms <= 0)
++              period = dev->ep_intr->desc.bInterval;
++      else
++              period = int_urb_interval_ms * INT_URB_MICROFRAMES_PER_MS;
++
++      netif_notice(dev, probe, netdev, "int urb period %d\n", period);
+       maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
+       buf = kmalloc(maxp, GFP_KERNEL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0260-ASoC-Add-support-for-AudioSense-Pi-add-on-soundcard.patch b/target/linux/brcm2708/patches-4.19/950-0260-ASoC-Add-support-for-AudioSense-Pi-add-on-soundcard.patch
new file mode 100644 (file)
index 0000000..1ab87d5
--- /dev/null
@@ -0,0 +1,320 @@
+From 5705594ae56861cb63e7a3de1854e29ad1e830fd Mon Sep 17 00:00:00 2001
+From: b-ak <anur.bhargav@gmail.com>
+Date: Thu, 3 Jan 2019 00:01:08 +0530
+Subject: [PATCH] ASoC: Add support for AudioSense-Pi add-on soundcard
+
+AudioSense-Pi is a RPi HAT based on a TI's TLV320AIC32x4 stereo codec
+
+This hardware provides multiple audio I/O capabilities to the RPi.
+The codec connects to the RPi's SoC through the I2S Bus.
+
+The following devices can be connected through a 3.5mm jack
+       1. Line-In: Plain old audio in from mobile phones, PCs, etc.,
+       2. Mic-In: Connect a microphone
+       3. Line-Out: Connect the output to a speaker
+       4. Headphones: Connect a Headphone w or w/o microphones
+
+Multiple Inputs:
+       It supports the following combinations
+       1. Two stereo Line-Inputs and a microphone
+       2. One stereo Line-Input and two microphones
+       3. Two stereo Line-Inputs, a microphone and
+               one mono line-input (with h/w hack)
+       4. One stereo Line-Input, two microphones and
+               one mono line-input (with h/w hack)
+
+Multiple Outputs:
+       Audio output can be routed to the headphones or
+               speakers (with additional hardware)
+
+Signed-off-by: b-ak <anur.bhargav@gmail.com>
+---
+ sound/soc/bcm/Kconfig         |   7 +
+ sound/soc/bcm/Makefile        |   2 +
+ sound/soc/bcm/audiosense-pi.c | 246 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 255 insertions(+)
+ create mode 100644 sound/soc/bcm/audiosense-pi.c
+
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -137,6 +137,13 @@ config SND_AUDIOINJECTOR_OCTO_SOUNDCARD
+       help
+         Say Y or M if you want to add support for audioinjector.net octo add on
++config SND_AUDIOSENSE_PI
++      tristate "Support for AudioSense Add-On Soundcard"
++      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++      select SND_SOC_TLV320AIC32X4_I2C
++      help
++        Say Y or M if you want to add support for tlv320aic32x4 add-on
++
+ config SND_DIGIDAC1_SOUNDCARD
+         tristate "Support for Red Rocks Audio DigiDAC1"
+         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -20,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+ snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
++snd-soc-audiosense-pi-objs := audiosense-pi.o
+ snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o
+ snd-soc-dionaudio-loco-objs := dionaudio_loco.o
+ snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o
+@@ -41,6 +42,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO)
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
++obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
+ obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o
+ 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
+--- /dev/null
++++ b/sound/soc/bcm/audiosense-pi.c
+@@ -0,0 +1,246 @@
++/*
++ * ASoC Driver for AudioSense add on soundcard
++ * Author:
++ *    Bhargav A K <anur.bhargav@gmail.com>
++ *    Copyright 2017
++ *
++ * 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/clk.h>
++#include <linux/i2c.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++#include <sound/control.h>
++
++#include <sound/tlv320aic32x4.h>
++#include "../codecs/tlv320aic32x4.h"
++
++#define AIC32X4_SYSCLK_XTAL   0x00
++
++/*
++ * Setup Codec Sample Rates and Channels
++ * Supported Rates:
++ *    8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000,
++ */
++static const unsigned int audiosense_pi_rate[] = {
++      48000,
++};
++
++static struct snd_pcm_hw_constraint_list audiosense_constraints_rates = {
++      .list = audiosense_pi_rate,
++      .count = ARRAY_SIZE(audiosense_pi_rate),
++};
++
++static const unsigned int audiosense_pi_channels[] = {
++      2,
++};
++
++static struct snd_pcm_hw_constraint_list audiosense_constraints_ch = {
++      .count = ARRAY_SIZE(audiosense_pi_channels),
++      .list = audiosense_pi_channels,
++      .mask = 0,
++};
++
++/* Setup DAPM widgets and paths */
++static const struct snd_soc_dapm_widget audiosense_pi_dapm_widgets[] = {
++      SND_SOC_DAPM_HP("Headphone Jack", NULL),
++      SND_SOC_DAPM_LINE("Line Out", NULL),
++      SND_SOC_DAPM_LINE("Line In", NULL),
++      SND_SOC_DAPM_INPUT("CM_L"),
++      SND_SOC_DAPM_INPUT("CM_R"),
++};
++
++static const struct snd_soc_dapm_route audiosense_pi_audio_map[] = {
++      /* Line Inputs are connected to
++       * (IN1_L | IN1_R)
++       * (IN2_L | IN2_R)
++       * (IN3_L | IN3_R)
++       */
++      {"IN1_L", NULL, "Line In"},
++      {"IN1_R", NULL, "Line In"},
++      {"IN2_L", NULL, "Line In"},
++      {"IN2_R", NULL, "Line In"},
++      {"IN3_L", NULL, "Line In"},
++      {"IN3_R", NULL, "Line In"},
++
++      /* Mic is connected to IN2_L and IN2_R */
++      {"Left ADC", NULL, "Mic Bias"},
++      {"Right ADC", NULL, "Mic Bias"},
++
++      /* Headphone connected to HPL, HPR */
++      {"Headphone Jack", NULL, "HPL"},
++      {"Headphone Jack", NULL, "HPR"},
++
++      /* Speakers connected to LOL and LOR */
++      {"Line Out", NULL, "LOL"},
++      {"Line Out", NULL, "LOR"},
++};
++
++static int audiosense_pi_card_init(struct snd_soc_pcm_runtime *rtd)
++{
++      /* TODO: init of the codec specific dapm data, ignore suspend/resume */
++      struct snd_soc_component *component = rtd->codec_dai->component;
++
++      snd_soc_component_update_bits(component, AIC32X4_MICBIAS, 0x78,
++                                    AIC32X4_MICBIAS_LDOIN |
++                                    AIC32X4_MICBIAS_2075V);
++      snd_soc_component_update_bits(component, AIC32X4_PWRCFG, 0x08,
++                                    AIC32X4_AVDDWEAKDISABLE);
++      snd_soc_component_update_bits(component, AIC32X4_LDOCTL, 0x01,
++                                    AIC32X4_LDOCTLEN);
++
++      return 0;
++}
++
++static int audiosense_pi_card_hw_params(
++              struct snd_pcm_substream *substream,
++              struct snd_pcm_hw_params *params)
++{
++      int ret = 0;
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_dai *codec_dai = rtd->codec_dai;
++
++      /* Set the codec system clock, there is a 12 MHz XTAL on the board */
++      ret = snd_soc_dai_set_sysclk(codec_dai, AIC32X4_SYSCLK_XTAL,
++                                   12000000, SND_SOC_CLOCK_IN);
++      if (ret) {
++              dev_err(rtd->card->dev,
++                      "could not set codec driver clock params\n");
++              return ret;
++      }
++      return 0;
++}
++
++static int audiosense_pi_card_startup(struct snd_pcm_substream *substream)
++{
++      struct snd_pcm_runtime *runtime = substream->runtime;
++
++      /*
++       * Set codec to 48Khz Sampling, Stereo I/O and 16 bit audio
++       */
++      runtime->hw.channels_max = 2;
++      snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
++                                 &audiosense_constraints_ch);
++
++      runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
++      snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
++
++
++      snd_pcm_hw_constraint_list(substream->runtime, 0,
++                                 SNDRV_PCM_HW_PARAM_RATE,
++                                 &audiosense_constraints_rates);
++      return 0;
++}
++
++static struct snd_soc_ops audiosense_pi_card_ops = {
++      .startup = audiosense_pi_card_startup,
++      .hw_params = audiosense_pi_card_hw_params,
++};
++
++static struct snd_soc_dai_link audiosense_pi_card_dai[] = {
++      {
++              .name           = "TLV320AIC3204 Audio",
++              .stream_name    = "TLV320AIC3204 Hifi Audio",
++              .cpu_dai_name   = "bcm2708-i2s.0",
++              .codec_dai_name = "tlv320aic32x4-hifi",
++              .platform_name  = "bcm2708-i2s.0",
++              .codec_name     = "tlv320aic32x4.1-0018",
++              .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++                      SND_SOC_DAIFMT_CBM_CFM,
++              .ops            = &audiosense_pi_card_ops,
++              .init           = audiosense_pi_card_init,
++      },
++};
++
++static struct snd_soc_card audiosense_pi_card = {
++      .name           = "audiosense-pi",
++      .driver_name    = "audiosense-pi",
++      .dai_link       = audiosense_pi_card_dai,
++      .owner          = THIS_MODULE,
++      .num_links      = ARRAY_SIZE(audiosense_pi_card_dai),
++      .dapm_widgets   = audiosense_pi_dapm_widgets,
++      .num_dapm_widgets = ARRAY_SIZE(audiosense_pi_dapm_widgets),
++      .dapm_routes    = audiosense_pi_audio_map,
++      .num_dapm_routes = ARRAY_SIZE(audiosense_pi_audio_map),
++};
++
++static int audiosense_pi_card_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++      struct snd_soc_card *card = &audiosense_pi_card;
++      struct snd_soc_dai_link *dai = &audiosense_pi_card_dai[0];
++      struct device_node *i2s_node = pdev->dev.of_node;
++
++      card->dev = &pdev->dev;
++
++      if (!dai) {
++              dev_err(&pdev->dev, "DAI not found. Missing or Invalid\n");
++              return -EINVAL;
++      }
++
++      i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
++      if (!i2s_node) {
++              dev_err(&pdev->dev,
++                      "Property 'i2s-controller' missing or invalid\n");
++              return -EINVAL;
++      }
++
++      dai->cpu_dai_name = NULL;
++      dai->cpu_of_node = i2s_node;
++      dai->platform_name = NULL;
++      dai->platform_of_node = i2s_node;
++
++      of_node_put(i2s_node);
++
++      ret = snd_soc_register_card(card);
++      if (ret && ret != -EPROBE_DEFER)
++              dev_err(&pdev->dev,
++                      "snd_soc_register_card() failed: %d\n", ret);
++
++      return ret;
++}
++
++static int audiosense_pi_card_remove(struct platform_device *pdev)
++{
++      struct snd_soc_card *card = platform_get_drvdata(pdev);
++
++      return snd_soc_unregister_card(card);
++
++}
++
++static const struct of_device_id audiosense_pi_card_of_match[] = {
++      { .compatible = "as,audiosense-pi", },
++      {},
++};
++MODULE_DEVICE_TABLE(of, audiosense_pi_card_of_match);
++
++static struct platform_driver audiosense_pi_card_driver = {
++      .driver = {
++              .name = "audiosense-snd-card",
++              .owner = THIS_MODULE,
++              .of_match_table = audiosense_pi_card_of_match,
++      },
++      .probe = audiosense_pi_card_probe,
++      .remove = audiosense_pi_card_remove,
++};
++
++module_platform_driver(audiosense_pi_card_driver);
++
++MODULE_AUTHOR("Bhargav AK <anur.bhargav@gmail.com>");
++MODULE_DESCRIPTION("ASoC Driver for TLV320AIC3204 Audio");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:audiosense-pi");
++
diff --git a/target/linux/brcm2708/patches-4.19/950-0260-bcm2835_smi-re-add-dereference-to-fix-DMA-transfers.patch b/target/linux/brcm2708/patches-4.19/950-0260-bcm2835_smi-re-add-dereference-to-fix-DMA-transfers.patch
deleted file mode 100644 (file)
index 37f1cb5..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From e5111d81c8efc17d8d585510980d3fe49c998741 Mon Sep 17 00:00:00 2001
-From: Ezekiel Bethel <zek@9net.org>
-Date: Wed, 12 Dec 2018 19:11:13 +0000
-Subject: [PATCH] bcm2835_smi: re-add dereference to fix DMA transfers
-
----
- drivers/misc/bcm2835_smi.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/misc/bcm2835_smi.c
-+++ b/drivers/misc/bcm2835_smi.c
-@@ -879,7 +879,7 @@ static int bcm2835_smi_probe(struct plat
-               goto err;
-       }
-       addr = of_get_address(node, 0, NULL, NULL);
--      inst->smi_regs_busaddr = be32_to_cpu(addr);
-+      inst->smi_regs_busaddr = be32_to_cpu(*addr);
-       err = bcm2835_smi_dma_setup(inst);
-       if (err)
diff --git a/target/linux/brcm2708/patches-4.19/950-0261-BCM270X-Adding-device-tree-support-for-AudioSense-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0261-BCM270X-Adding-device-tree-support-for-AudioSense-Pi.patch
new file mode 100644 (file)
index 0000000..1e85d9f
--- /dev/null
@@ -0,0 +1,135 @@
+From 0d2a0f4f4c00c958fb6e7a2673adbe51c2a932f2 Mon Sep 17 00:00:00 2001
+From: b-ak <anur.bhargav@gmail.com>
+Date: Thu, 3 Jan 2019 00:29:14 +0530
+Subject: [PATCH] BCM270X: Adding device tree support for AudioSense-Pi
+ add-on soundcard
+
+Device tree overlay for AudioSense-Pi card.
+
+To enable support for the hardware add the following
+line to the RPi /boot/config.txt:
+
+       dtoverlay=audiosense-pi
+
+More documentation @ arch/arm/boot/dts/overlays/README
+
+Signed-off-by: b-ak <anur.bhargav@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  8 ++
+ .../dts/overlays/audiosense-pi-overlay.dts    | 82 +++++++++++++++++++
+ 3 files changed, 91 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -20,6 +20,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       audioinjector-addons.dtbo \
+       audioinjector-ultra.dtbo \
+       audioinjector-wm8731-audio.dtbo \
++      audiosense-pi.dtbo \
+       audremap.dtbo \
+       balena-fin.dtbo \
+       bmp085_i2c-sensor.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -453,6 +453,14 @@ Load:   dtoverlay=audioinjector-wm8731-a
+ Params: <None>
++Name:   audiosense-pi
++Info:   Configures the audiosense-pi add on soundcard
++        For more information refer to
++        https://gitlab.com/kakar0t/audiosense-pi
++Load:   dtoverlay=audiosense-pi
++Params: <None>
++
++
+ Name:   audremap
+ Info:   Switches PWM sound output to pins 12 (Right) & 13 (Left)
+ Load:   dtoverlay=audremap,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
+@@ -0,0 +1,82 @@
++// Definitions for audiosense add on soundcard
++/dts-v1/;
++/plugin/;
++#include <dt-bindings/pinctrl/bcm2835.h>
++#include <dt-bindings/gpio/gpio.h>
++
++/ {
++      compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target-path = "/";
++              __overlay__ {
++                      codec_reg_1v8: codec-reg-1v8 {
++                              compatible = "regulator-fixed";
++                              regulator-name = "tlv320aic3204_1v8";
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-always-on;
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&gpio>;
++              __overlay__ {
++                      codec_rst: codec-rst {
++                              brcm,pins = <26>;
++                              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      /* audio external oscillator */
++                      codec_osc: codec_osc {
++                              compatible = "fixed-clock";
++                              #clock-cells = <0>;
++                              clock-frequency = <12000000>;   /* 12 MHz */
++                      };
++
++                      codec: tlv320aic32x4@18 {
++                              #sound-dai-cells = <0>;
++                              compatible = "ti,tlv320aic32x4";
++                              reg = <0x18>;
++
++                              clocks = <&codec_osc>;
++                              clock-names = "mclk";
++
++                              iov-supply = <&vdd_3v3_reg>;
++                              ldoin-supply = <&vdd_3v3_reg>;
++
++                              gpio-controller;
++                              #gpio-cells = <2>;
++                              reset-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
++
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@4 {
++              target = <&sound>;
++              __overlay__ {
++                      compatible = "as,audiosense-pi";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0261-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch b/target/linux/brcm2708/patches-4.19/950-0261-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch
deleted file mode 100644 (file)
index 395934d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 020ee4d0d438b830ee40da8d9d3414de156a11e7 Mon Sep 17 00:00:00 2001
-From: Joshua Emele <jemele@acm.org>
-Date: Wed, 7 Nov 2018 16:07:40 -0800
-Subject: [PATCH] lan78xx: Debounce link events to minimize poll storm
-
-The bInterval is set to 4 (i.e. 8 microframes => 1ms) and the only bit
-that the driver pays attention to is "link was reset". If there's a
-flapping status bit in that endpoint data, (such as if PHY negotiation
-needs a few tries to get a stable link) then polling at a slower rate
-would act as a de-bounce.
-
-See: https://github.com/raspberrypi/linux/issues/2447
----
- drivers/net/usb/lan78xx.c | 12 +++++++++++-
- 1 file changed, 11 insertions(+), 1 deletion(-)
-
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -449,6 +449,11 @@ static bool enable_tso;
- module_param(enable_tso, bool, 0644);
- MODULE_PARM_DESC(enable_tso, "Enables TCP segmentation offload");
-+#define INT_URB_MICROFRAMES_PER_MS    8
-+static int int_urb_interval_ms = 8;
-+module_param(int_urb_interval_ms, int, 0);
-+MODULE_PARM_DESC(int_urb_interval_ms, "Override usb interrupt urb interval");
-+
- static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
- {
-       u32 *buf = kmalloc(sizeof(u32), GFP_KERNEL);
-@@ -3838,7 +3843,12 @@ static int lan78xx_probe(struct usb_inte
-       dev->pipe_intr = usb_rcvintpipe(dev->udev,
-                                       dev->ep_intr->desc.bEndpointAddress &
-                                       USB_ENDPOINT_NUMBER_MASK);
--      period = dev->ep_intr->desc.bInterval;
-+      if (int_urb_interval_ms <= 0)
-+              period = dev->ep_intr->desc.bInterval;
-+      else
-+              period = int_urb_interval_ms * INT_URB_MICROFRAMES_PER_MS;
-+
-+      netif_notice(dev, probe, netdev, "int urb period %d\n", period);
-       maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
-       buf = kmalloc(maxp, GFP_KERNEL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0262-ASoC-Add-support-for-AudioSense-Pi-add-on-soundcard.patch b/target/linux/brcm2708/patches-4.19/950-0262-ASoC-Add-support-for-AudioSense-Pi-add-on-soundcard.patch
deleted file mode 100644 (file)
index 1ab87d5..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-From 5705594ae56861cb63e7a3de1854e29ad1e830fd Mon Sep 17 00:00:00 2001
-From: b-ak <anur.bhargav@gmail.com>
-Date: Thu, 3 Jan 2019 00:01:08 +0530
-Subject: [PATCH] ASoC: Add support for AudioSense-Pi add-on soundcard
-
-AudioSense-Pi is a RPi HAT based on a TI's TLV320AIC32x4 stereo codec
-
-This hardware provides multiple audio I/O capabilities to the RPi.
-The codec connects to the RPi's SoC through the I2S Bus.
-
-The following devices can be connected through a 3.5mm jack
-       1. Line-In: Plain old audio in from mobile phones, PCs, etc.,
-       2. Mic-In: Connect a microphone
-       3. Line-Out: Connect the output to a speaker
-       4. Headphones: Connect a Headphone w or w/o microphones
-
-Multiple Inputs:
-       It supports the following combinations
-       1. Two stereo Line-Inputs and a microphone
-       2. One stereo Line-Input and two microphones
-       3. Two stereo Line-Inputs, a microphone and
-               one mono line-input (with h/w hack)
-       4. One stereo Line-Input, two microphones and
-               one mono line-input (with h/w hack)
-
-Multiple Outputs:
-       Audio output can be routed to the headphones or
-               speakers (with additional hardware)
-
-Signed-off-by: b-ak <anur.bhargav@gmail.com>
----
- sound/soc/bcm/Kconfig         |   7 +
- sound/soc/bcm/Makefile        |   2 +
- sound/soc/bcm/audiosense-pi.c | 246 ++++++++++++++++++++++++++++++++++
- 3 files changed, 255 insertions(+)
- create mode 100644 sound/soc/bcm/audiosense-pi.c
-
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -137,6 +137,13 @@ config SND_AUDIOINJECTOR_OCTO_SOUNDCARD
-       help
-         Say Y or M if you want to add support for audioinjector.net octo add on
-+config SND_AUDIOSENSE_PI
-+      tristate "Support for AudioSense Add-On Soundcard"
-+      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+      select SND_SOC_TLV320AIC32X4_I2C
-+      help
-+        Say Y or M if you want to add support for tlv320aic32x4 add-on
-+
- config SND_DIGIDAC1_SOUNDCARD
-         tristate "Support for Red Rocks Audio DigiDAC1"
-         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -20,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
- snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
-+snd-soc-audiosense-pi-objs := audiosense-pi.o
- snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o
- snd-soc-dionaudio-loco-objs := dionaudio_loco.o
- snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o
-@@ -41,6 +42,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO)
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
-+obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
- obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o
- 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
---- /dev/null
-+++ b/sound/soc/bcm/audiosense-pi.c
-@@ -0,0 +1,246 @@
-+/*
-+ * ASoC Driver for AudioSense add on soundcard
-+ * Author:
-+ *    Bhargav A K <anur.bhargav@gmail.com>
-+ *    Copyright 2017
-+ *
-+ * 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/clk.h>
-+#include <linux/i2c.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+#include <sound/control.h>
-+
-+#include <sound/tlv320aic32x4.h>
-+#include "../codecs/tlv320aic32x4.h"
-+
-+#define AIC32X4_SYSCLK_XTAL   0x00
-+
-+/*
-+ * Setup Codec Sample Rates and Channels
-+ * Supported Rates:
-+ *    8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000,
-+ */
-+static const unsigned int audiosense_pi_rate[] = {
-+      48000,
-+};
-+
-+static struct snd_pcm_hw_constraint_list audiosense_constraints_rates = {
-+      .list = audiosense_pi_rate,
-+      .count = ARRAY_SIZE(audiosense_pi_rate),
-+};
-+
-+static const unsigned int audiosense_pi_channels[] = {
-+      2,
-+};
-+
-+static struct snd_pcm_hw_constraint_list audiosense_constraints_ch = {
-+      .count = ARRAY_SIZE(audiosense_pi_channels),
-+      .list = audiosense_pi_channels,
-+      .mask = 0,
-+};
-+
-+/* Setup DAPM widgets and paths */
-+static const struct snd_soc_dapm_widget audiosense_pi_dapm_widgets[] = {
-+      SND_SOC_DAPM_HP("Headphone Jack", NULL),
-+      SND_SOC_DAPM_LINE("Line Out", NULL),
-+      SND_SOC_DAPM_LINE("Line In", NULL),
-+      SND_SOC_DAPM_INPUT("CM_L"),
-+      SND_SOC_DAPM_INPUT("CM_R"),
-+};
-+
-+static const struct snd_soc_dapm_route audiosense_pi_audio_map[] = {
-+      /* Line Inputs are connected to
-+       * (IN1_L | IN1_R)
-+       * (IN2_L | IN2_R)
-+       * (IN3_L | IN3_R)
-+       */
-+      {"IN1_L", NULL, "Line In"},
-+      {"IN1_R", NULL, "Line In"},
-+      {"IN2_L", NULL, "Line In"},
-+      {"IN2_R", NULL, "Line In"},
-+      {"IN3_L", NULL, "Line In"},
-+      {"IN3_R", NULL, "Line In"},
-+
-+      /* Mic is connected to IN2_L and IN2_R */
-+      {"Left ADC", NULL, "Mic Bias"},
-+      {"Right ADC", NULL, "Mic Bias"},
-+
-+      /* Headphone connected to HPL, HPR */
-+      {"Headphone Jack", NULL, "HPL"},
-+      {"Headphone Jack", NULL, "HPR"},
-+
-+      /* Speakers connected to LOL and LOR */
-+      {"Line Out", NULL, "LOL"},
-+      {"Line Out", NULL, "LOR"},
-+};
-+
-+static int audiosense_pi_card_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      /* TODO: init of the codec specific dapm data, ignore suspend/resume */
-+      struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+      snd_soc_component_update_bits(component, AIC32X4_MICBIAS, 0x78,
-+                                    AIC32X4_MICBIAS_LDOIN |
-+                                    AIC32X4_MICBIAS_2075V);
-+      snd_soc_component_update_bits(component, AIC32X4_PWRCFG, 0x08,
-+                                    AIC32X4_AVDDWEAKDISABLE);
-+      snd_soc_component_update_bits(component, AIC32X4_LDOCTL, 0x01,
-+                                    AIC32X4_LDOCTLEN);
-+
-+      return 0;
-+}
-+
-+static int audiosense_pi_card_hw_params(
-+              struct snd_pcm_substream *substream,
-+              struct snd_pcm_hw_params *params)
-+{
-+      int ret = 0;
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+
-+      /* Set the codec system clock, there is a 12 MHz XTAL on the board */
-+      ret = snd_soc_dai_set_sysclk(codec_dai, AIC32X4_SYSCLK_XTAL,
-+                                   12000000, SND_SOC_CLOCK_IN);
-+      if (ret) {
-+              dev_err(rtd->card->dev,
-+                      "could not set codec driver clock params\n");
-+              return ret;
-+      }
-+      return 0;
-+}
-+
-+static int audiosense_pi_card_startup(struct snd_pcm_substream *substream)
-+{
-+      struct snd_pcm_runtime *runtime = substream->runtime;
-+
-+      /*
-+       * Set codec to 48Khz Sampling, Stereo I/O and 16 bit audio
-+       */
-+      runtime->hw.channels_max = 2;
-+      snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-+                                 &audiosense_constraints_ch);
-+
-+      runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
-+      snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
-+
-+
-+      snd_pcm_hw_constraint_list(substream->runtime, 0,
-+                                 SNDRV_PCM_HW_PARAM_RATE,
-+                                 &audiosense_constraints_rates);
-+      return 0;
-+}
-+
-+static struct snd_soc_ops audiosense_pi_card_ops = {
-+      .startup = audiosense_pi_card_startup,
-+      .hw_params = audiosense_pi_card_hw_params,
-+};
-+
-+static struct snd_soc_dai_link audiosense_pi_card_dai[] = {
-+      {
-+              .name           = "TLV320AIC3204 Audio",
-+              .stream_name    = "TLV320AIC3204 Hifi Audio",
-+              .cpu_dai_name   = "bcm2708-i2s.0",
-+              .codec_dai_name = "tlv320aic32x4-hifi",
-+              .platform_name  = "bcm2708-i2s.0",
-+              .codec_name     = "tlv320aic32x4.1-0018",
-+              .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+                      SND_SOC_DAIFMT_CBM_CFM,
-+              .ops            = &audiosense_pi_card_ops,
-+              .init           = audiosense_pi_card_init,
-+      },
-+};
-+
-+static struct snd_soc_card audiosense_pi_card = {
-+      .name           = "audiosense-pi",
-+      .driver_name    = "audiosense-pi",
-+      .dai_link       = audiosense_pi_card_dai,
-+      .owner          = THIS_MODULE,
-+      .num_links      = ARRAY_SIZE(audiosense_pi_card_dai),
-+      .dapm_widgets   = audiosense_pi_dapm_widgets,
-+      .num_dapm_widgets = ARRAY_SIZE(audiosense_pi_dapm_widgets),
-+      .dapm_routes    = audiosense_pi_audio_map,
-+      .num_dapm_routes = ARRAY_SIZE(audiosense_pi_audio_map),
-+};
-+
-+static int audiosense_pi_card_probe(struct platform_device *pdev)
-+{
-+      int ret = 0;
-+      struct snd_soc_card *card = &audiosense_pi_card;
-+      struct snd_soc_dai_link *dai = &audiosense_pi_card_dai[0];
-+      struct device_node *i2s_node = pdev->dev.of_node;
-+
-+      card->dev = &pdev->dev;
-+
-+      if (!dai) {
-+              dev_err(&pdev->dev, "DAI not found. Missing or Invalid\n");
-+              return -EINVAL;
-+      }
-+
-+      i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
-+      if (!i2s_node) {
-+              dev_err(&pdev->dev,
-+                      "Property 'i2s-controller' missing or invalid\n");
-+              return -EINVAL;
-+      }
-+
-+      dai->cpu_dai_name = NULL;
-+      dai->cpu_of_node = i2s_node;
-+      dai->platform_name = NULL;
-+      dai->platform_of_node = i2s_node;
-+
-+      of_node_put(i2s_node);
-+
-+      ret = snd_soc_register_card(card);
-+      if (ret && ret != -EPROBE_DEFER)
-+              dev_err(&pdev->dev,
-+                      "snd_soc_register_card() failed: %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static int audiosense_pi_card_remove(struct platform_device *pdev)
-+{
-+      struct snd_soc_card *card = platform_get_drvdata(pdev);
-+
-+      return snd_soc_unregister_card(card);
-+
-+}
-+
-+static const struct of_device_id audiosense_pi_card_of_match[] = {
-+      { .compatible = "as,audiosense-pi", },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, audiosense_pi_card_of_match);
-+
-+static struct platform_driver audiosense_pi_card_driver = {
-+      .driver = {
-+              .name = "audiosense-snd-card",
-+              .owner = THIS_MODULE,
-+              .of_match_table = audiosense_pi_card_of_match,
-+      },
-+      .probe = audiosense_pi_card_probe,
-+      .remove = audiosense_pi_card_remove,
-+};
-+
-+module_platform_driver(audiosense_pi_card_driver);
-+
-+MODULE_AUTHOR("Bhargav AK <anur.bhargav@gmail.com>");
-+MODULE_DESCRIPTION("ASoC Driver for TLV320AIC3204 Audio");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:audiosense-pi");
-+
diff --git a/target/linux/brcm2708/patches-4.19/950-0262-overlays-sdio-Add-enhanced-1-bit-support.patch b/target/linux/brcm2708/patches-4.19/950-0262-overlays-sdio-Add-enhanced-1-bit-support.patch
new file mode 100644 (file)
index 0000000..42a9f11
--- /dev/null
@@ -0,0 +1,107 @@
+From 788109b357ddb30a95be72ce46dc22e2335131af Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 10 Jan 2019 15:27:56 +0000
+Subject: [PATCH] overlays: sdio: Add enhanced 1-bit support
+
+"dtoverlay=sdio,bus_width=1,gpios_22_25" is equivalent to the sdio-1bit
+overlay, which is now deprecated.
+
+"dtoverlay=sdio,bus_width=1,gpios_34_37" enables 1-bit mode on GPIOs 34-37.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README           | 24 +++++++++++----------
+ arch/arm/boot/dts/overlays/sdio-overlay.dts | 20 ++++++++++++++++-
+ 2 files changed, 32 insertions(+), 12 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -479,8 +479,7 @@ Params: <None>
+ Name:   bmp085_i2c-sensor
+ Info:   This overlay is now deprecated - see i2c-sensor
+-Load:   dtoverlay=bmp085_i2c-sensor
+-Params: <None>
++Load:   <Deprecated>
+ Name:   dht11
+@@ -1737,7 +1736,8 @@ Params: overclock_50            Clock (i
+ Name:   sdio
+ Info:   Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
+-        and enables SDIO via GPIOs 22-27.
++        and enables SDIO via GPIOs 22-27. An example of use in 1-bit mode is
++        "dtoverlay=sdio,bus_width=1,gpios_22_25"
+ Load:   dtoverlay=sdio,<param>=<val>
+ Params: sdio_overclock          SDIO Clock (in MHz) to use when the MMC
+                                 framework requests 50MHz
+@@ -1747,16 +1747,18 @@ Params: sdio_overclock          SDIO Clo
+         bus_width               Set the SDIO host bus width (default 4 bits)
++        gpios_22_25             Select GPIOs 22-25 for 1-bit mode. Must be used
++                                with bus_width=1. This replaces the sdio-1bit
++                                overlay, which is now deprecated.
+-Name:   sdio-1bit
+-Info:   Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
+-        and enables 1-bit SDIO via GPIOs 22-25.
+-Load:   dtoverlay=sdio-1bit,<param>=<val>
+-Params: sdio_overclock          SDIO Clock (in MHz) to use when the MMC
+-                                framework requests 50MHz
++        gpios_34_37             Select GPIOs 34-37 for 1-bit mode. Must be used
++                                with bus_width=1.
+-        poll_once               Disable SDIO-device polling every second
+-                                (default on: polling once at boot-time)
++
++Name:   sdio-1bit
++Info:   This overlay is now deprecated. Use
++        "dtoverlay=sdio,bus_width=1,gpios_22_25" instead.
++Load:   <Deprecated>
+ Name:   sdtweak
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -32,7 +32,7 @@
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&sdio_ovl_pins>;
+                               non-removable;
+-                              bus-width = <1>;
++                              bus-width = <4>;
+                       };
+               };
+       };
+@@ -49,6 +49,22 @@
+       };
+       fragment@3 {
++              target = <&sdio_ovl_pins>;
++              __dormant__ {
++                      brcm,pins = <22 23 24 25>;
++                      brcm,pull = <0 2 2 2>;
++              };
++      };
++
++      fragment@4 {
++              target = <&sdio_ovl_pins>;
++              __dormant__ {
++                      brcm,pins = <34 35 36 37>;
++                      brcm,pull = <0 2 2 2>;
++              };
++      };
++
++      fragment@6 {
+               target-path = "/aliases";
+               __overlay__ {
+                       mmc1 = "/soc/sdio@7e300000";
+@@ -59,5 +75,7 @@
+               poll_once = <&sdio_ovl>,"non-removable?";
+               bus_width = <&sdio_ovl>,"bus-width:0";
+               sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
++              gpios_22_25 = <0>,"=3";
++              gpios_34_37 = <0>,"=4";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0263-BCM270X-Adding-device-tree-support-for-AudioSense-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0263-BCM270X-Adding-device-tree-support-for-AudioSense-Pi.patch
deleted file mode 100644 (file)
index 1e85d9f..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-From 0d2a0f4f4c00c958fb6e7a2673adbe51c2a932f2 Mon Sep 17 00:00:00 2001
-From: b-ak <anur.bhargav@gmail.com>
-Date: Thu, 3 Jan 2019 00:29:14 +0530
-Subject: [PATCH] BCM270X: Adding device tree support for AudioSense-Pi
- add-on soundcard
-
-Device tree overlay for AudioSense-Pi card.
-
-To enable support for the hardware add the following
-line to the RPi /boot/config.txt:
-
-       dtoverlay=audiosense-pi
-
-More documentation @ arch/arm/boot/dts/overlays/README
-
-Signed-off-by: b-ak <anur.bhargav@gmail.com>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             |  8 ++
- .../dts/overlays/audiosense-pi-overlay.dts    | 82 +++++++++++++++++++
- 3 files changed, 91 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -20,6 +20,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       audioinjector-addons.dtbo \
-       audioinjector-ultra.dtbo \
-       audioinjector-wm8731-audio.dtbo \
-+      audiosense-pi.dtbo \
-       audremap.dtbo \
-       balena-fin.dtbo \
-       bmp085_i2c-sensor.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -453,6 +453,14 @@ Load:   dtoverlay=audioinjector-wm8731-a
- Params: <None>
-+Name:   audiosense-pi
-+Info:   Configures the audiosense-pi add on soundcard
-+        For more information refer to
-+        https://gitlab.com/kakar0t/audiosense-pi
-+Load:   dtoverlay=audiosense-pi
-+Params: <None>
-+
-+
- Name:   audremap
- Info:   Switches PWM sound output to pins 12 (Right) & 13 (Left)
- Load:   dtoverlay=audremap,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-@@ -0,0 +1,82 @@
-+// Definitions for audiosense add on soundcard
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/pinctrl/bcm2835.h>
-+#include <dt-bindings/gpio/gpio.h>
-+
-+/ {
-+      compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+      fragment@0 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target-path = "/";
-+              __overlay__ {
-+                      codec_reg_1v8: codec-reg-1v8 {
-+                              compatible = "regulator-fixed";
-+                              regulator-name = "tlv320aic3204_1v8";
-+                              regulator-min-microvolt = <1800000>;
-+                              regulator-max-microvolt = <1800000>;
-+                              regulator-always-on;
-+                      };
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&gpio>;
-+              __overlay__ {
-+                      codec_rst: codec-rst {
-+                              brcm,pins = <26>;
-+                              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+                      };
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      /* audio external oscillator */
-+                      codec_osc: codec_osc {
-+                              compatible = "fixed-clock";
-+                              #clock-cells = <0>;
-+                              clock-frequency = <12000000>;   /* 12 MHz */
-+                      };
-+
-+                      codec: tlv320aic32x4@18 {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "ti,tlv320aic32x4";
-+                              reg = <0x18>;
-+
-+                              clocks = <&codec_osc>;
-+                              clock-names = "mclk";
-+
-+                              iov-supply = <&vdd_3v3_reg>;
-+                              ldoin-supply = <&vdd_3v3_reg>;
-+
-+                              gpio-controller;
-+                              #gpio-cells = <2>;
-+                              reset-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
-+
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@4 {
-+              target = <&sound>;
-+              __overlay__ {
-+                      compatible = "as,audiosense-pi";
-+                      i2s-controller = <&i2s>;
-+                      status = "okay";
-+              };
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0263-dwc_otg-fix-bug-with-port_addr-assignment-for-single.patch b/target/linux/brcm2708/patches-4.19/950-0263-dwc_otg-fix-bug-with-port_addr-assignment-for-single.patch
new file mode 100644 (file)
index 0000000..fd5f88f
--- /dev/null
@@ -0,0 +1,28 @@
+From 6e56da00afdf11416045213552514d10bab845cc Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 16 Jan 2019 10:17:52 +0000
+Subject: [PATCH] dwc_otg: fix bug with port_addr assignment for
+ single-TT hubs
+
+See https://github.com/raspberrypi/linux/issues/2734
+
+The "Hub Port" field in the split transaction packet was always set
+to 1 for single-TT hubs. The majority of single-TT hub products
+apparently ignore this field and broadcast to all downstream enabled
+ports, which masked the issue. A subset of hub devices apparently
+need the port number to be exact or split transactions will fail.
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -232,7 +232,7 @@ static int _hub_info(dwc_otg_hcd_t * hcd
+               else
+                       *hub_addr = urb->dev->tt->hub->devnum;
+       }
+-      *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
++      *port_addr = urb->dev->ttport;
+    } else {
+         *hub_addr = 0;
+       *port_addr = urb->dev->ttport;
diff --git a/target/linux/brcm2708/patches-4.19/950-0264-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch b/target/linux/brcm2708/patches-4.19/950-0264-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch
new file mode 100644 (file)
index 0000000..9cd839e
--- /dev/null
@@ -0,0 +1,576 @@
+From dde0ec6b9fd5755de3a8962489cde9c0ce5e5005 Mon Sep 17 00:00:00 2001
+From: HiFiBerry <info@hifiberry.com>
+Date: Mon, 8 Oct 2018 18:10:12 +0200
+Subject: [PATCH] Added driver for the HiFiBerry DAC+ ADC (#2694)
+
+Signed-off-by: Daniel Matuschek <daniel@hifiberry.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  21 +
+ .../overlays/hifiberry-dacplusadc-overlay.dts |  71 +++
+ sound/soc/bcm/Kconfig                         |   8 +
+ sound/soc/bcm/Makefile                        |   2 +
+ sound/soc/bcm/hifiberry_dacplusadc.c          | 407 ++++++++++++++++++
+ 8 files changed, 512 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
+ create mode 100644 sound/soc/bcm/hifiberry_dacplusadc.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -49,6 +49,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       hifiberry-amp.dtbo \
+       hifiberry-dac.dtbo \
+       hifiberry-dacplus.dtbo \
++      hifiberry-dacplusadc.dtbo \
+       hifiberry-digi.dtbo \
+       hifiberry-digi-pro.dtbo \
+       hy28a.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -779,6 +779,27 @@ Params: 24db_digital_gain       Allow ga
+                                 master for bit clock and frame clock.
++Name:   hifiberry-dacplusadc
++Info:   Configures the HifiBerry DAC+ADC audio card
++Load:   dtoverlay=hifiberry-dacplusadc,<param>=<val>
++Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
++                                Digital volume control. Enable with
++                                "dtoverlay=hifiberry-dacplus,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.
++
++
+ Name:   hifiberry-digi
+ Info:   Configures the HifiBerry Digi and Digi+ audio card
+ Load:   dtoverlay=hifiberry-digi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
+@@ -0,0 +1,71 @@
++// Definitions for HiFiBerry DAC+ADC
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2708";
++
++      fragment@0 {
++              target-path = "/clocks";
++              __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";
++
++                      pcm_codec: 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-path = "/";
++              __overlay__ {
++                      dmic {
++                              #sound-dai-cells = <0>;
++                              compatible = "dmic-codec";
++                              num-channels = <2>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@4 {
++              target = <&sound>;
++              hifiberry_dacplusadc: __overlay__ {
++                      compatible = "hifiberry,hifiberry-dacplusadc";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++
++      __overrides__ {
++              24db_digital_gain =
++                      <&hifiberry_dacplusadc>,"hifiberry,24db_digital_gain?";
++              slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?";
++      };
++};
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -46,6 +46,14 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
+         help
+          Say Y or M if you want to add support for HifiBerry DAC+.
++config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
++        tristate "Support for HifiBerry DAC+ADC"
++        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++        select SND_SOC_PCM512x_I2C
++      select SND_SOC_DMIC
++        help
++         Say Y or M if you want to add support for HifiBerry DAC+ADC.
++
+ config SND_BCM2708_SOC_HIFIBERRY_DIGI
+         tristate "Support for HifiBerry Digi"
+         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -14,6 +14,7 @@ snd-soc-googlevoicehat-codec-objs := goo
+ # BCM2708 Machine Support
+ snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
++snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+@@ -36,6 +37,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
+ obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.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
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+--- /dev/null
++++ b/sound/soc/bcm/hifiberry_dacplusadc.c
+@@ -0,0 +1,407 @@
++/*
++ * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC
++ *
++ * Author:    Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
++ *            Copyright 2014-2015
++ *            based on code by Florian Meier <florian.meier@koalo.de>
++ *            ADC added by Joerg Schambacher <joscha@schambacher.com>
++ *            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/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#include "../codecs/pcm512x.h"
++
++#define HIFIBERRY_DACPRO_NOCLOCK 0
++#define HIFIBERRY_DACPRO_CLK44EN 1
++#define HIFIBERRY_DACPRO_CLK48EN 2
++
++struct platform_device *dmic_codec_dev;
++
++struct pcm512x_priv {
++      struct regmap *regmap;
++      struct clk *sclk;
++};
++
++/* Clock rate of CLK44EN attached to GPIO6 pin */
++#define CLK_44EN_RATE 22579200UL
++/* Clock rate of CLK48EN attached to GPIO3 pin */
++#define CLK_48EN_RATE 24576000UL
++
++static bool slave;
++static bool snd_rpi_hifiberry_is_dacpro;
++static bool digital_gain_0db_limit = true;
++
++static void snd_rpi_hifiberry_dacplusadc_select_clk(struct snd_soc_component *component,
++      int clk_id)
++{
++      switch (clk_id) {
++      case HIFIBERRY_DACPRO_NOCLOCK:
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
++              break;
++      case HIFIBERRY_DACPRO_CLK44EN:
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
++              break;
++      case HIFIBERRY_DACPRO_CLK48EN:
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
++              break;
++      }
++}
++
++static void snd_rpi_hifiberry_dacplusadc_clk_gpio(struct snd_soc_component *component)
++{
++      snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
++      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
++      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
++}
++
++static bool snd_rpi_hifiberry_dacplusadc_is_sclk(struct snd_soc_component *component)
++{
++      unsigned int sck;
++
++      snd_soc_component_read(component, PCM512x_RATE_DET_4, &sck);
++      return (!(sck & 0x40));
++}
++
++static bool snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(
++      struct snd_soc_component *component)
++{
++      msleep(2);
++      return snd_rpi_hifiberry_dacplusadc_is_sclk(component);
++}
++
++static bool snd_rpi_hifiberry_dacplusadc_is_pro_card(struct snd_soc_component *component)
++{
++      bool isClk44EN, isClk48En, isNoClk;
++
++      snd_rpi_hifiberry_dacplusadc_clk_gpio(component);
++
++      snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
++      isClk44EN = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
++
++      snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
++      isNoClk = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
++
++      snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
++      isClk48En = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
++
++      return (isClk44EN && isClk48En && !isNoClk);
++}
++
++static int snd_rpi_hifiberry_dacplusadc_clk_for_rate(int sample_rate)
++{
++      int type;
++
++      switch (sample_rate) {
++      case 11025:
++      case 22050:
++      case 44100:
++      case 88200:
++      case 176400:
++      case 352800:
++              type = HIFIBERRY_DACPRO_CLK44EN;
++              break;
++      default:
++              type = HIFIBERRY_DACPRO_CLK48EN;
++              break;
++      }
++      return type;
++}
++
++static void snd_rpi_hifiberry_dacplusadc_set_sclk(struct snd_soc_component *component,
++      int sample_rate)
++{
++      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++
++      if (!IS_ERR(pcm512x->sclk)) {
++              int ctype;
++
++              ctype = snd_rpi_hifiberry_dacplusadc_clk_for_rate(sample_rate);
++              clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
++                      ? CLK_44EN_RATE : CLK_48EN_RATE);
++              snd_rpi_hifiberry_dacplusadc_select_clk(component, ctype);
++      }
++}
++
++static int snd_rpi_hifiberry_dacplusadc_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_component *component = rtd->codec_dai->component;
++      struct pcm512x_priv *priv;
++
++      if (slave)
++              snd_rpi_hifiberry_is_dacpro = false;
++      else
++              snd_rpi_hifiberry_is_dacpro =
++                              snd_rpi_hifiberry_dacplusadc_is_pro_card(component);
++
++      if (snd_rpi_hifiberry_is_dacpro) {
++              struct snd_soc_dai_link *dai = rtd->dai_link;
++
++              dai->name = "HiFiBerry ADCDAC+ Pro";
++              dai->stream_name = "HiFiBerry ADCDAC+ Pro HiFi";
++              dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++                      | SND_SOC_DAIFMT_CBM_CFM;
++
++              snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
++              snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
++              snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
++      } else {
++              priv = snd_soc_component_get_drvdata(component);
++              priv->sclk = ERR_PTR(-ENOENT);
++      }
++
++      snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
++      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
++      snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++      if (digital_gain_0db_limit) {
++              int ret;
++              struct snd_soc_card *card = rtd->card;
++
++              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);
++      }
++
++      return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadc_update_rate_den(
++      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *component = rtd->codec_dai->component;
++      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++      struct snd_ratnum *rats_no_pll;
++      unsigned int num = 0, den = 0;
++      int err;
++
++      rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
++      if (!rats_no_pll)
++              return -ENOMEM;
++
++      rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
++      rats_no_pll->den_min = 1;
++      rats_no_pll->den_max = 128;
++      rats_no_pll->den_step = 1;
++
++      err = snd_interval_ratnum(hw_param_interval(params,
++              SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
++      if (err >= 0 && den) {
++              params->rate_num = num;
++              params->rate_den = den;
++      }
++
++      devm_kfree(rtd->dev, rats_no_pll);
++      return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadc_hw_params(
++      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++      int ret = 0;
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      int channels = params_channels(params);
++      int width = 32;
++
++      if (snd_rpi_hifiberry_is_dacpro) {
++              struct snd_soc_component *component = rtd->codec_dai->component;
++
++              width = snd_pcm_format_physical_width(params_format(params));
++
++              snd_rpi_hifiberry_dacplusadc_set_sclk(component,
++                      params_rate(params));
++
++              ret = snd_rpi_hifiberry_dacplusadc_update_rate_den(
++                      substream, params);
++      }
++
++      ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x03, 0x03,
++              channels, width);
++      if (ret)
++              return ret;
++      ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03,
++              channels, width);
++      return ret;
++}
++
++static int hifiberry_dacplusadc_LED_cnt;
++
++static int snd_rpi_hifiberry_dacplusadc_startup(
++      struct snd_pcm_substream *substream)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *component = rtd->codec_dai->component;
++
++      snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
++                                       0x08, 0x08);
++      hifiberry_dacplusadc_LED_cnt++;
++      return 0;
++}
++
++static void snd_rpi_hifiberry_dacplusadc_shutdown(
++      struct snd_pcm_substream *substream)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *component = rtd->codec_dai->component;
++
++      hifiberry_dacplusadc_LED_cnt--;
++      if (!hifiberry_dacplusadc_LED_cnt)
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
++                                               0x08, 0x00);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_hifiberry_dacplusadc_ops = {
++      .hw_params = snd_rpi_hifiberry_dacplusadc_hw_params,
++      .startup = snd_rpi_hifiberry_dacplusadc_startup,
++      .shutdown = snd_rpi_hifiberry_dacplusadc_shutdown,
++};
++
++static struct snd_soc_dai_link_component snd_rpi_hifiberry_dacplusadc_codecs[] = {
++      {
++              .name = "pcm512x.1-004d",
++              .dai_name = "pcm512x-hifi",
++      },
++      {
++              .name = "dmic-codec",
++              .dai_name = "dmic-hifi",
++      },
++};
++
++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadc_dai[] = {
++{
++      .name           = "HiFiBerry DAC+ADC",
++      .stream_name    = "HiFiBerry DAC+ADC HiFi",
++      .cpu_dai_name   = "bcm2708-i2s.0",
++      .platform_name  = "bcm2708-i2s.0",
++      .codecs         = snd_rpi_hifiberry_dacplusadc_codecs,
++      .num_codecs     = 2,
++      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++                              SND_SOC_DAIFMT_CBS_CFS,
++      .ops            = &snd_rpi_hifiberry_dacplusadc_ops,
++      .init           = snd_rpi_hifiberry_dacplusadc_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_hifiberry_dacplusadc = {
++      .name         = "snd_rpi_hifiberry_dacplusadc",
++      .driver_name  = "HifiberryDacpAdc",
++      .owner        = THIS_MODULE,
++      .dai_link     = snd_rpi_hifiberry_dacplusadc_dai,
++      .num_links    = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadc_dai),
++};
++
++
++static int snd_rpi_hifiberry_dacplusadc_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++
++      snd_rpi_hifiberry_dacplusadc.dev = &pdev->dev;
++      if (pdev->dev.of_node) {
++              struct device_node *i2s_node;
++              struct snd_soc_dai_link *dai;
++
++              dai = &snd_rpi_hifiberry_dacplusadc_dai[0];
++              i2s_node = of_parse_phandle(pdev->dev.of_node,
++                      "i2s-controller", 0);
++              if (i2s_node) {
++                      dai->cpu_of_node = i2s_node;
++                      dai->platform_of_node = i2s_node;
++                      dai->cpu_dai_name = NULL;
++                      dai->platform_name = NULL;
++              }
++              dai = &snd_rpi_hifiberry_dacplusadc_dai[1];
++              i2s_node = of_parse_phandle(pdev->dev.of_node, "dmic", 0);
++              if (i2s_node) {
++                      dai->cpu_of_node = i2s_node;
++                      dai->platform_of_node = i2s_node;
++              }
++
++      }
++      digital_gain_0db_limit = !of_property_read_bool(
++              pdev->dev.of_node, "hifiberry,24db_digital_gain");
++      slave = of_property_read_bool(pdev->dev.of_node,
++                                      "hifiberry-dacplusadc,slave");
++
++      ret = devm_snd_soc_register_card(&pdev->dev,
++                                               &snd_rpi_hifiberry_dacplusadc);
++      if (ret && ret != -EPROBE_DEFER)
++              dev_err(&pdev->dev,
++                      "snd_soc_register_card() failed: %d\n", ret);
++
++      return ret;
++}
++
++static const struct of_device_id snd_rpi_hifiberry_dacplusadc_of_match[] = {
++      { .compatible = "hifiberry,hifiberry-dacplusadc", },
++      {},
++};
++
++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadc_of_match);
++
++static struct platform_driver snd_rpi_hifiberry_dacplusadc_driver = {
++      .driver = {
++              .name   = "snd-rpi-hifiberry-dacplusadc",
++              .owner  = THIS_MODULE,
++              .of_match_table = snd_rpi_hifiberry_dacplusadc_of_match,
++      },
++      .probe          = snd_rpi_hifiberry_dacplusadc_probe,
++};
++
++static int __init hifiberry_dacplusadc_init(void)
++{
++      int ret;
++
++      dmic_codec_dev = platform_device_register_simple("dmic-codec", -1, NULL,
++                                                       0);
++      if (IS_ERR(dmic_codec_dev)) {
++              pr_err("%s: dmic-codec device registration failed\n", __func__);
++              return PTR_ERR(dmic_codec_dev);
++      }
++
++      ret = platform_driver_register(&snd_rpi_hifiberry_dacplusadc_driver);
++      if (ret) {
++              pr_err("%s: platform driver registration failed\n", __func__);
++              platform_device_unregister(dmic_codec_dev);
++      }
++
++      return ret;
++}
++module_init(hifiberry_dacplusadc_init);
++
++static void __exit hifiberry_dacplusadc_exit(void)
++{
++      platform_driver_unregister(&snd_rpi_hifiberry_dacplusadc_driver);
++      platform_device_unregister(dmic_codec_dev);
++}
++module_exit(hifiberry_dacplusadc_exit);
++
++MODULE_AUTHOR("Joerg Schambacher <joscha@schambacher.com>");
++MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0264-overlays-sdio-Add-enhanced-1-bit-support.patch b/target/linux/brcm2708/patches-4.19/950-0264-overlays-sdio-Add-enhanced-1-bit-support.patch
deleted file mode 100644 (file)
index 42a9f11..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-From 788109b357ddb30a95be72ce46dc22e2335131af Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 10 Jan 2019 15:27:56 +0000
-Subject: [PATCH] overlays: sdio: Add enhanced 1-bit support
-
-"dtoverlay=sdio,bus_width=1,gpios_22_25" is equivalent to the sdio-1bit
-overlay, which is now deprecated.
-
-"dtoverlay=sdio,bus_width=1,gpios_34_37" enables 1-bit mode on GPIOs 34-37.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README           | 24 +++++++++++----------
- arch/arm/boot/dts/overlays/sdio-overlay.dts | 20 ++++++++++++++++-
- 2 files changed, 32 insertions(+), 12 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -479,8 +479,7 @@ Params: <None>
- Name:   bmp085_i2c-sensor
- Info:   This overlay is now deprecated - see i2c-sensor
--Load:   dtoverlay=bmp085_i2c-sensor
--Params: <None>
-+Load:   <Deprecated>
- Name:   dht11
-@@ -1737,7 +1736,8 @@ Params: overclock_50            Clock (i
- Name:   sdio
- Info:   Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
--        and enables SDIO via GPIOs 22-27.
-+        and enables SDIO via GPIOs 22-27. An example of use in 1-bit mode is
-+        "dtoverlay=sdio,bus_width=1,gpios_22_25"
- Load:   dtoverlay=sdio,<param>=<val>
- Params: sdio_overclock          SDIO Clock (in MHz) to use when the MMC
-                                 framework requests 50MHz
-@@ -1747,16 +1747,18 @@ Params: sdio_overclock          SDIO Clo
-         bus_width               Set the SDIO host bus width (default 4 bits)
-+        gpios_22_25             Select GPIOs 22-25 for 1-bit mode. Must be used
-+                                with bus_width=1. This replaces the sdio-1bit
-+                                overlay, which is now deprecated.
--Name:   sdio-1bit
--Info:   Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
--        and enables 1-bit SDIO via GPIOs 22-25.
--Load:   dtoverlay=sdio-1bit,<param>=<val>
--Params: sdio_overclock          SDIO Clock (in MHz) to use when the MMC
--                                framework requests 50MHz
-+        gpios_34_37             Select GPIOs 34-37 for 1-bit mode. Must be used
-+                                with bus_width=1.
--        poll_once               Disable SDIO-device polling every second
--                                (default on: polling once at boot-time)
-+
-+Name:   sdio-1bit
-+Info:   This overlay is now deprecated. Use
-+        "dtoverlay=sdio,bus_width=1,gpios_22_25" instead.
-+Load:   <Deprecated>
- Name:   sdtweak
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -32,7 +32,7 @@
-                               pinctrl-names = "default";
-                               pinctrl-0 = <&sdio_ovl_pins>;
-                               non-removable;
--                              bus-width = <1>;
-+                              bus-width = <4>;
-                       };
-               };
-       };
-@@ -49,6 +49,22 @@
-       };
-       fragment@3 {
-+              target = <&sdio_ovl_pins>;
-+              __dormant__ {
-+                      brcm,pins = <22 23 24 25>;
-+                      brcm,pull = <0 2 2 2>;
-+              };
-+      };
-+
-+      fragment@4 {
-+              target = <&sdio_ovl_pins>;
-+              __dormant__ {
-+                      brcm,pins = <34 35 36 37>;
-+                      brcm,pull = <0 2 2 2>;
-+              };
-+      };
-+
-+      fragment@6 {
-               target-path = "/aliases";
-               __overlay__ {
-                       mmc1 = "/soc/sdio@7e300000";
-@@ -59,5 +75,7 @@
-               poll_once = <&sdio_ovl>,"non-removable?";
-               bus_width = <&sdio_ovl>,"bus-width:0";
-               sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
-+              gpios_22_25 = <0>,"=3";
-+              gpios_34_37 = <0>,"=4";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0265-dwc_otg-fix-bug-with-port_addr-assignment-for-single.patch b/target/linux/brcm2708/patches-4.19/950-0265-dwc_otg-fix-bug-with-port_addr-assignment-for-single.patch
deleted file mode 100644 (file)
index fd5f88f..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 6e56da00afdf11416045213552514d10bab845cc Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Wed, 16 Jan 2019 10:17:52 +0000
-Subject: [PATCH] dwc_otg: fix bug with port_addr assignment for
- single-TT hubs
-
-See https://github.com/raspberrypi/linux/issues/2734
-
-The "Hub Port" field in the split transaction packet was always set
-to 1 for single-TT hubs. The majority of single-TT hub products
-apparently ignore this field and broadcast to all downstream enabled
-ports, which masked the issue. A subset of hub devices apparently
-need the port number to be exact or split transactions will fail.
----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -232,7 +232,7 @@ static int _hub_info(dwc_otg_hcd_t * hcd
-               else
-                       *hub_addr = urb->dev->tt->hub->devnum;
-       }
--      *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
-+      *port_addr = urb->dev->ttport;
-    } else {
-         *hub_addr = 0;
-       *port_addr = urb->dev->ttport;
diff --git a/target/linux/brcm2708/patches-4.19/950-0265-pwm-Send-a-uevent-on-the-pwmchip-device-upon-channel.patch b/target/linux/brcm2708/patches-4.19/950-0265-pwm-Send-a-uevent-on-the-pwmchip-device-upon-channel.patch
new file mode 100644 (file)
index 0000000..8136e3f
--- /dev/null
@@ -0,0 +1,86 @@
+From 20a5b38305df30e25b4429e0e34e35235dd57228 Mon Sep 17 00:00:00 2001
+From: Fabrice Gasnier <fabrice.gasnier@st.com>
+Date: Mon, 1 Oct 2018 15:23:57 +0200
+Subject: [PATCH] pwm: Send a uevent on the pwmchip device upon channel
+ sysfs (un)export
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 552c02e3e7cfe2744b59de285aaea70021ae95c9 upstream.
+
+This patch sends a uevent (KOBJ_CHANGE) on the pwmchipN device,
+everytime a pwmX channel has been exported/unexported via sysfs. This
+allows udev to implement rules on such events, like:
+
+SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
+        chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
+        chown -R root:gpio
+/sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770
+/sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
+'"
+
+This is a replacement patch for commit 7e5d1fd75c3d ("pwm: Set class for
+exported channels in sysfs"), see [1].
+
+basic testing:
+$ udevadm monitor --environment &
+$ echo 0 > /sys/class/pwm/pwmchip0/export
+KERNEL[197.321736] change   /devices/.../pwm/pwmchip0 (pwm)
+ACTION=change
+DEVPATH=/devices/.../pwm/pwmchip0
+EXPORT=pwm0
+SEQNUM=2045
+SUBSYSTEM=pwm
+
+[1] https://lkml.org/lkml/2018/9/25/713
+
+Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
+Tested-by: Gottfried Haider <gottfried.haider@gmail.com>
+Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
+Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
+---
+ drivers/pwm/sysfs.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/pwm/sysfs.c
++++ b/drivers/pwm/sysfs.c
+@@ -249,6 +249,7 @@ static void pwm_export_release(struct de
+ static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
+ {
+       struct pwm_export *export;
++      char *pwm_prop[2];
+       int ret;
+       if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags))
+@@ -276,6 +277,10 @@ static int pwm_export_child(struct devic
+               export = NULL;
+               return ret;
+       }
++      pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm);
++      pwm_prop[1] = NULL;
++      kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
++      kfree(pwm_prop[0]);
+       return 0;
+ }
+@@ -288,6 +293,7 @@ static int pwm_unexport_match(struct dev
+ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
+ {
+       struct device *child;
++      char *pwm_prop[2];
+       if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags))
+               return -ENODEV;
+@@ -296,6 +302,11 @@ static int pwm_unexport_child(struct dev
+       if (!child)
+               return -ENODEV;
++      pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm);
++      pwm_prop[1] = NULL;
++      kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
++      kfree(pwm_prop[0]);
++
+       /* for device_find_child() */
+       put_device(child);
+       device_unregister(child);
diff --git a/target/linux/brcm2708/patches-4.19/950-0266-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch b/target/linux/brcm2708/patches-4.19/950-0266-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch
deleted file mode 100644 (file)
index 9cd839e..0000000
+++ /dev/null
@@ -1,576 +0,0 @@
-From dde0ec6b9fd5755de3a8962489cde9c0ce5e5005 Mon Sep 17 00:00:00 2001
-From: HiFiBerry <info@hifiberry.com>
-Date: Mon, 8 Oct 2018 18:10:12 +0200
-Subject: [PATCH] Added driver for the HiFiBerry DAC+ ADC (#2694)
-
-Signed-off-by: Daniel Matuschek <daniel@hifiberry.com>
----
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |  21 +
- .../overlays/hifiberry-dacplusadc-overlay.dts |  71 +++
- sound/soc/bcm/Kconfig                         |   8 +
- sound/soc/bcm/Makefile                        |   2 +
- sound/soc/bcm/hifiberry_dacplusadc.c          | 407 ++++++++++++++++++
- 8 files changed, 512 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
- create mode 100644 sound/soc/bcm/hifiberry_dacplusadc.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -49,6 +49,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       hifiberry-amp.dtbo \
-       hifiberry-dac.dtbo \
-       hifiberry-dacplus.dtbo \
-+      hifiberry-dacplusadc.dtbo \
-       hifiberry-digi.dtbo \
-       hifiberry-digi-pro.dtbo \
-       hy28a.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -779,6 +779,27 @@ Params: 24db_digital_gain       Allow ga
-                                 master for bit clock and frame clock.
-+Name:   hifiberry-dacplusadc
-+Info:   Configures the HifiBerry DAC+ADC audio card
-+Load:   dtoverlay=hifiberry-dacplusadc,<param>=<val>
-+Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
-+                                Digital volume control. Enable with
-+                                "dtoverlay=hifiberry-dacplus,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.
-+
-+
- Name:   hifiberry-digi
- Info:   Configures the HifiBerry Digi and Digi+ audio card
- Load:   dtoverlay=hifiberry-digi
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
-@@ -0,0 +1,71 @@
-+// Definitions for HiFiBerry DAC+ADC
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2708";
-+
-+      fragment@0 {
-+              target-path = "/clocks";
-+              __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";
-+
-+                      pcm_codec: 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-path = "/";
-+              __overlay__ {
-+                      dmic {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "dmic-codec";
-+                              num-channels = <2>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@4 {
-+              target = <&sound>;
-+              hifiberry_dacplusadc: __overlay__ {
-+                      compatible = "hifiberry,hifiberry-dacplusadc";
-+                      i2s-controller = <&i2s>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      __overrides__ {
-+              24db_digital_gain =
-+                      <&hifiberry_dacplusadc>,"hifiberry,24db_digital_gain?";
-+              slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?";
-+      };
-+};
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -46,6 +46,14 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
-         help
-          Say Y or M if you want to add support for HifiBerry DAC+.
-+config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
-+        tristate "Support for HifiBerry DAC+ADC"
-+        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+        select SND_SOC_PCM512x_I2C
-+      select SND_SOC_DMIC
-+        help
-+         Say Y or M if you want to add support for HifiBerry DAC+ADC.
-+
- config SND_BCM2708_SOC_HIFIBERRY_DIGI
-         tristate "Support for HifiBerry Digi"
-         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -14,6 +14,7 @@ snd-soc-googlevoicehat-codec-objs := goo
- # BCM2708 Machine Support
- snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
-+snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
-@@ -36,6 +37,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
- obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.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
-+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
---- /dev/null
-+++ b/sound/soc/bcm/hifiberry_dacplusadc.c
-@@ -0,0 +1,407 @@
-+/*
-+ * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC
-+ *
-+ * Author:    Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
-+ *            Copyright 2014-2015
-+ *            based on code by Florian Meier <florian.meier@koalo.de>
-+ *            ADC added by Joerg Schambacher <joscha@schambacher.com>
-+ *            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/platform_device.h>
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+
-+#include "../codecs/pcm512x.h"
-+
-+#define HIFIBERRY_DACPRO_NOCLOCK 0
-+#define HIFIBERRY_DACPRO_CLK44EN 1
-+#define HIFIBERRY_DACPRO_CLK48EN 2
-+
-+struct platform_device *dmic_codec_dev;
-+
-+struct pcm512x_priv {
-+      struct regmap *regmap;
-+      struct clk *sclk;
-+};
-+
-+/* Clock rate of CLK44EN attached to GPIO6 pin */
-+#define CLK_44EN_RATE 22579200UL
-+/* Clock rate of CLK48EN attached to GPIO3 pin */
-+#define CLK_48EN_RATE 24576000UL
-+
-+static bool slave;
-+static bool snd_rpi_hifiberry_is_dacpro;
-+static bool digital_gain_0db_limit = true;
-+
-+static void snd_rpi_hifiberry_dacplusadc_select_clk(struct snd_soc_component *component,
-+      int clk_id)
-+{
-+      switch (clk_id) {
-+      case HIFIBERRY_DACPRO_NOCLOCK:
-+              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
-+              break;
-+      case HIFIBERRY_DACPRO_CLK44EN:
-+              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
-+              break;
-+      case HIFIBERRY_DACPRO_CLK48EN:
-+              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
-+              break;
-+      }
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadc_clk_gpio(struct snd_soc_component *component)
-+{
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
-+}
-+
-+static bool snd_rpi_hifiberry_dacplusadc_is_sclk(struct snd_soc_component *component)
-+{
-+      unsigned int sck;
-+
-+      snd_soc_component_read(component, PCM512x_RATE_DET_4, &sck);
-+      return (!(sck & 0x40));
-+}
-+
-+static bool snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(
-+      struct snd_soc_component *component)
-+{
-+      msleep(2);
-+      return snd_rpi_hifiberry_dacplusadc_is_sclk(component);
-+}
-+
-+static bool snd_rpi_hifiberry_dacplusadc_is_pro_card(struct snd_soc_component *component)
-+{
-+      bool isClk44EN, isClk48En, isNoClk;
-+
-+      snd_rpi_hifiberry_dacplusadc_clk_gpio(component);
-+
-+      snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
-+      isClk44EN = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
-+
-+      snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
-+      isNoClk = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
-+
-+      snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
-+      isClk48En = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
-+
-+      return (isClk44EN && isClk48En && !isNoClk);
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_clk_for_rate(int sample_rate)
-+{
-+      int type;
-+
-+      switch (sample_rate) {
-+      case 11025:
-+      case 22050:
-+      case 44100:
-+      case 88200:
-+      case 176400:
-+      case 352800:
-+              type = HIFIBERRY_DACPRO_CLK44EN;
-+              break;
-+      default:
-+              type = HIFIBERRY_DACPRO_CLK48EN;
-+              break;
-+      }
-+      return type;
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadc_set_sclk(struct snd_soc_component *component,
-+      int sample_rate)
-+{
-+      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+
-+      if (!IS_ERR(pcm512x->sclk)) {
-+              int ctype;
-+
-+              ctype = snd_rpi_hifiberry_dacplusadc_clk_for_rate(sample_rate);
-+              clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
-+                      ? CLK_44EN_RATE : CLK_48EN_RATE);
-+              snd_rpi_hifiberry_dacplusadc_select_clk(component, ctype);
-+      }
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      struct snd_soc_component *component = rtd->codec_dai->component;
-+      struct pcm512x_priv *priv;
-+
-+      if (slave)
-+              snd_rpi_hifiberry_is_dacpro = false;
-+      else
-+              snd_rpi_hifiberry_is_dacpro =
-+                              snd_rpi_hifiberry_dacplusadc_is_pro_card(component);
-+
-+      if (snd_rpi_hifiberry_is_dacpro) {
-+              struct snd_soc_dai_link *dai = rtd->dai_link;
-+
-+              dai->name = "HiFiBerry ADCDAC+ Pro";
-+              dai->stream_name = "HiFiBerry ADCDAC+ Pro HiFi";
-+              dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+                      | SND_SOC_DAIFMT_CBM_CFM;
-+
-+              snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
-+              snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
-+              snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
-+      } else {
-+              priv = snd_soc_component_get_drvdata(component);
-+              priv->sclk = ERR_PTR(-ENOENT);
-+      }
-+
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+
-+      if (digital_gain_0db_limit) {
-+              int ret;
-+              struct snd_soc_card *card = rtd->card;
-+
-+              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);
-+      }
-+
-+      return 0;
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_update_rate_den(
-+      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *component = rtd->codec_dai->component;
-+      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+      struct snd_ratnum *rats_no_pll;
-+      unsigned int num = 0, den = 0;
-+      int err;
-+
-+      rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
-+      if (!rats_no_pll)
-+              return -ENOMEM;
-+
-+      rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
-+      rats_no_pll->den_min = 1;
-+      rats_no_pll->den_max = 128;
-+      rats_no_pll->den_step = 1;
-+
-+      err = snd_interval_ratnum(hw_param_interval(params,
-+              SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
-+      if (err >= 0 && den) {
-+              params->rate_num = num;
-+              params->rate_den = den;
-+      }
-+
-+      devm_kfree(rtd->dev, rats_no_pll);
-+      return 0;
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_hw_params(
-+      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
-+{
-+      int ret = 0;
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      int channels = params_channels(params);
-+      int width = 32;
-+
-+      if (snd_rpi_hifiberry_is_dacpro) {
-+              struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+              width = snd_pcm_format_physical_width(params_format(params));
-+
-+              snd_rpi_hifiberry_dacplusadc_set_sclk(component,
-+                      params_rate(params));
-+
-+              ret = snd_rpi_hifiberry_dacplusadc_update_rate_den(
-+                      substream, params);
-+      }
-+
-+      ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x03, 0x03,
-+              channels, width);
-+      if (ret)
-+              return ret;
-+      ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03,
-+              channels, width);
-+      return ret;
-+}
-+
-+static int hifiberry_dacplusadc_LED_cnt;
-+
-+static int snd_rpi_hifiberry_dacplusadc_startup(
-+      struct snd_pcm_substream *substream)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
-+                                       0x08, 0x08);
-+      hifiberry_dacplusadc_LED_cnt++;
-+      return 0;
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadc_shutdown(
-+      struct snd_pcm_substream *substream)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+      hifiberry_dacplusadc_LED_cnt--;
-+      if (!hifiberry_dacplusadc_LED_cnt)
-+              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
-+                                               0x08, 0x00);
-+}
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_hifiberry_dacplusadc_ops = {
-+      .hw_params = snd_rpi_hifiberry_dacplusadc_hw_params,
-+      .startup = snd_rpi_hifiberry_dacplusadc_startup,
-+      .shutdown = snd_rpi_hifiberry_dacplusadc_shutdown,
-+};
-+
-+static struct snd_soc_dai_link_component snd_rpi_hifiberry_dacplusadc_codecs[] = {
-+      {
-+              .name = "pcm512x.1-004d",
-+              .dai_name = "pcm512x-hifi",
-+      },
-+      {
-+              .name = "dmic-codec",
-+              .dai_name = "dmic-hifi",
-+      },
-+};
-+
-+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadc_dai[] = {
-+{
-+      .name           = "HiFiBerry DAC+ADC",
-+      .stream_name    = "HiFiBerry DAC+ADC HiFi",
-+      .cpu_dai_name   = "bcm2708-i2s.0",
-+      .platform_name  = "bcm2708-i2s.0",
-+      .codecs         = snd_rpi_hifiberry_dacplusadc_codecs,
-+      .num_codecs     = 2,
-+      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+                              SND_SOC_DAIFMT_CBS_CFS,
-+      .ops            = &snd_rpi_hifiberry_dacplusadc_ops,
-+      .init           = snd_rpi_hifiberry_dacplusadc_init,
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_hifiberry_dacplusadc = {
-+      .name         = "snd_rpi_hifiberry_dacplusadc",
-+      .driver_name  = "HifiberryDacpAdc",
-+      .owner        = THIS_MODULE,
-+      .dai_link     = snd_rpi_hifiberry_dacplusadc_dai,
-+      .num_links    = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadc_dai),
-+};
-+
-+
-+static int snd_rpi_hifiberry_dacplusadc_probe(struct platform_device *pdev)
-+{
-+      int ret = 0;
-+
-+      snd_rpi_hifiberry_dacplusadc.dev = &pdev->dev;
-+      if (pdev->dev.of_node) {
-+              struct device_node *i2s_node;
-+              struct snd_soc_dai_link *dai;
-+
-+              dai = &snd_rpi_hifiberry_dacplusadc_dai[0];
-+              i2s_node = of_parse_phandle(pdev->dev.of_node,
-+                      "i2s-controller", 0);
-+              if (i2s_node) {
-+                      dai->cpu_of_node = i2s_node;
-+                      dai->platform_of_node = i2s_node;
-+                      dai->cpu_dai_name = NULL;
-+                      dai->platform_name = NULL;
-+              }
-+              dai = &snd_rpi_hifiberry_dacplusadc_dai[1];
-+              i2s_node = of_parse_phandle(pdev->dev.of_node, "dmic", 0);
-+              if (i2s_node) {
-+                      dai->cpu_of_node = i2s_node;
-+                      dai->platform_of_node = i2s_node;
-+              }
-+
-+      }
-+      digital_gain_0db_limit = !of_property_read_bool(
-+              pdev->dev.of_node, "hifiberry,24db_digital_gain");
-+      slave = of_property_read_bool(pdev->dev.of_node,
-+                                      "hifiberry-dacplusadc,slave");
-+
-+      ret = devm_snd_soc_register_card(&pdev->dev,
-+                                               &snd_rpi_hifiberry_dacplusadc);
-+      if (ret && ret != -EPROBE_DEFER)
-+              dev_err(&pdev->dev,
-+                      "snd_soc_register_card() failed: %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static const struct of_device_id snd_rpi_hifiberry_dacplusadc_of_match[] = {
-+      { .compatible = "hifiberry,hifiberry-dacplusadc", },
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadc_of_match);
-+
-+static struct platform_driver snd_rpi_hifiberry_dacplusadc_driver = {
-+      .driver = {
-+              .name   = "snd-rpi-hifiberry-dacplusadc",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = snd_rpi_hifiberry_dacplusadc_of_match,
-+      },
-+      .probe          = snd_rpi_hifiberry_dacplusadc_probe,
-+};
-+
-+static int __init hifiberry_dacplusadc_init(void)
-+{
-+      int ret;
-+
-+      dmic_codec_dev = platform_device_register_simple("dmic-codec", -1, NULL,
-+                                                       0);
-+      if (IS_ERR(dmic_codec_dev)) {
-+              pr_err("%s: dmic-codec device registration failed\n", __func__);
-+              return PTR_ERR(dmic_codec_dev);
-+      }
-+
-+      ret = platform_driver_register(&snd_rpi_hifiberry_dacplusadc_driver);
-+      if (ret) {
-+              pr_err("%s: platform driver registration failed\n", __func__);
-+              platform_device_unregister(dmic_codec_dev);
-+      }
-+
-+      return ret;
-+}
-+module_init(hifiberry_dacplusadc_init);
-+
-+static void __exit hifiberry_dacplusadc_exit(void)
-+{
-+      platform_driver_unregister(&snd_rpi_hifiberry_dacplusadc_driver);
-+      platform_device_unregister(dmic_codec_dev);
-+}
-+module_exit(hifiberry_dacplusadc_exit);
-+
-+MODULE_AUTHOR("Joerg Schambacher <joscha@schambacher.com>");
-+MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
-+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0266-overlays-Add-ssd1306-overlay-for-OLED-display.patch b/target/linux/brcm2708/patches-4.19/950-0266-overlays-Add-ssd1306-overlay-for-OLED-display.patch
new file mode 100644 (file)
index 0000000..967cc76
--- /dev/null
@@ -0,0 +1,104 @@
+From d8eac0d3e4f6c6f9e5f789c8e2288699b2afebcb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 21:17:27 +0000
+Subject: [PATCH] overlays: Add ssd1306 overlay for OLED display
+
+See: https://github.com/raspberrypi/firmware/issues/1098
+
+Signed-off-by: mincepi <mincepi@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             | 31 ++++++++++++++++
+ .../arm/boot/dts/overlays/ssd1306-overlay.dts | 36 +++++++++++++++++++
+ 3 files changed, 68 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ssd1306-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       spi2-1cs.dtbo \
+       spi2-2cs.dtbo \
+       spi2-3cs.dtbo \
++      ssd1306.dtbo \
+       superaudioboard.dtbo \
+       sx150x.dtbo \
+       tc358743.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1950,6 +1950,37 @@ Params: cs0_pin                 GPIO pin
+                                 is 'okay' or enabled).
++Name:   ssd1306
++Info:   Overlay for activation of SSD1306 over I2C OLED display framebuffer.
++Load:   dtoverlay=ssd1306,<param>=<val>
++Params: address                 Location in display memory of first character.
++                                (default=0)
++        width                   Width of display. (default=128)
++        height                  Height of display. (default=64)
++        offset                  virtual channel a. (default=0)
++        normal                  Has no effect on displays tested. (default=not
++                                set)
++        sequential              Set this if every other scan line is missing.
++                                (default=not set)
++        remapped                Set this if display is garbled. (default=not
++                                set)
++        inverted                Set this if display is inverted and mirrored.
++                                (default=not set)
++
++        Examples:
++        Typical usage for 128x64 display: dtoverlay=ssd1306,inverted
++
++        Typical usage for 128x32 display: dtoverlay=ssd1306,inverted,sequential
++
++        i2c_baudrate=400000 will speed up the display.
++
++        i2c_baudrate=1000000 seems to work even though it's not officially
++        supported by the hardware, and is faster still.
++
++        For more information refer to the device datasheet at:
++        https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
++
++
+ Name:   superaudioboard
+ Info:   Configures the SuperAudioBoard sound card
+ Load:   dtoverlay=superaudioboard,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
+@@ -0,0 +1,36 @@
++// Overlay for SSD1306 128x64 and 128x32 OLED displays
++/dts-v1/;
++/plugin/;
++
++/ {
++    compatible = "brcm,bcm2718";
++
++    fragment@0 {
++      target = <&i2c1>;
++      __overlay__ {
++          status = "okay";
++
++          #address-cells = <1>;
++          #size-cells = <0>;
++
++          ssd1306: oled@3c{
++              compatible = "solomon,ssd1306fb-i2c";
++              reg = <0x3c>;
++              solomon,width = <128>;
++              solomon,height = <64>;
++              solomon,page-offset = <0>;
++          };
++      };
++    };
++
++    __overrides__ {
++      address = <&ssd1306>,"reg:0";
++      width = <&ssd1306>,"solomon,width:0";
++      height = <&ssd1306>,"solomon,height:0";
++      offset = <&ssd1306>,"solomon,page-offset:0";
++      normal = <&ssd1306>,"solomon,segment-no-remap?";
++      sequential = <&ssd1306>,"solomon,com-seq?";
++      remapped = <&ssd1306>,"solomon,com-lrremap?";
++      inverted = <&ssd1306>,"solomon,com-invdir?";
++    };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0267-overlays-mcp23017-Support-the-MCP23008.patch b/target/linux/brcm2708/patches-4.19/950-0267-overlays-mcp23017-Support-the-MCP23008.patch
new file mode 100644 (file)
index 0000000..44f295a
--- /dev/null
@@ -0,0 +1,49 @@
+From c85a1ccbc6b1cab51a5fe5b916bcaf40bcd9096c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 12:19:57 +0000
+Subject: [PATCH] overlays: mcp23017: Support the MCP23008
+
+Add an 'mcp23008' parameter to enable support for the MCP23008 device.
+
+See: https://github.com/raspberrypi/linux/issues/2818
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README               |  2 ++
+ arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 10 +++++++++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1212,6 +1212,8 @@ Params: gpiopin                 Gpio pin
+         addr                    I2C address of the MCP23017 (default: 0x20)
++        mcp23008                Configure an MCP23008 instead.
++
+ Name:   mcp23s17
+ Info:   Configures the MCP23S08/17 SPI GPIO expanders.
+--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
+@@ -44,11 +44,19 @@
+                       };
+               };
+       };
+-      
++
++      fragment@3 {
++              target = <&mcp23017>;
++              __dormant__ {
++                      compatible = "microchip,mcp23008";
++              };
++      };
++
+       __overrides__ {
+               gpiopin = <&mcp23017_pins>,"brcm,pins:0",
+                               <&mcp23017>,"interrupts:0";
+               addr = <&mcp23017>,"reg:0";
++              mcp23008 = <0>,"=3";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0267-pwm-Send-a-uevent-on-the-pwmchip-device-upon-channel.patch b/target/linux/brcm2708/patches-4.19/950-0267-pwm-Send-a-uevent-on-the-pwmchip-device-upon-channel.patch
deleted file mode 100644 (file)
index 8136e3f..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-From 20a5b38305df30e25b4429e0e34e35235dd57228 Mon Sep 17 00:00:00 2001
-From: Fabrice Gasnier <fabrice.gasnier@st.com>
-Date: Mon, 1 Oct 2018 15:23:57 +0200
-Subject: [PATCH] pwm: Send a uevent on the pwmchip device upon channel
- sysfs (un)export
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 552c02e3e7cfe2744b59de285aaea70021ae95c9 upstream.
-
-This patch sends a uevent (KOBJ_CHANGE) on the pwmchipN device,
-everytime a pwmX channel has been exported/unexported via sysfs. This
-allows udev to implement rules on such events, like:
-
-SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
-        chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
-        chown -R root:gpio
-/sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770
-/sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
-'"
-
-This is a replacement patch for commit 7e5d1fd75c3d ("pwm: Set class for
-exported channels in sysfs"), see [1].
-
-basic testing:
-$ udevadm monitor --environment &
-$ echo 0 > /sys/class/pwm/pwmchip0/export
-KERNEL[197.321736] change   /devices/.../pwm/pwmchip0 (pwm)
-ACTION=change
-DEVPATH=/devices/.../pwm/pwmchip0
-EXPORT=pwm0
-SEQNUM=2045
-SUBSYSTEM=pwm
-
-[1] https://lkml.org/lkml/2018/9/25/713
-
-Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
-Tested-by: Gottfried Haider <gottfried.haider@gmail.com>
-Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
-Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
----
- drivers/pwm/sysfs.c | 11 +++++++++++
- 1 file changed, 11 insertions(+)
-
---- a/drivers/pwm/sysfs.c
-+++ b/drivers/pwm/sysfs.c
-@@ -249,6 +249,7 @@ static void pwm_export_release(struct de
- static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
- {
-       struct pwm_export *export;
-+      char *pwm_prop[2];
-       int ret;
-       if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags))
-@@ -276,6 +277,10 @@ static int pwm_export_child(struct devic
-               export = NULL;
-               return ret;
-       }
-+      pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm);
-+      pwm_prop[1] = NULL;
-+      kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
-+      kfree(pwm_prop[0]);
-       return 0;
- }
-@@ -288,6 +293,7 @@ static int pwm_unexport_match(struct dev
- static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
- {
-       struct device *child;
-+      char *pwm_prop[2];
-       if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags))
-               return -ENODEV;
-@@ -296,6 +302,11 @@ static int pwm_unexport_child(struct dev
-       if (!child)
-               return -ENODEV;
-+      pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm);
-+      pwm_prop[1] = NULL;
-+      kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
-+      kfree(pwm_prop[0]);
-+
-       /* for device_find_child() */
-       put_device(child);
-       device_unregister(child);
diff --git a/target/linux/brcm2708/patches-4.19/950-0268-overlays-Add-mcp342x-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0268-overlays-Add-mcp342x-overlay.patch
new file mode 100644 (file)
index 0000000..d104c65
--- /dev/null
@@ -0,0 +1,148 @@
+From b71f1fd962c66ba3fa46483f193cc2263146c5bf Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 12:23:55 +0000
+Subject: [PATCH] overlays: Add mcp342x overlay
+
+Support the MCP342x family of ADCs from Microchip.
+
+See: https://github.com/raspberrypi/linux/issues/2819
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             | 16 ++++
+ .../arm/boot/dts/overlays/mcp342x-overlay.dts | 93 +++++++++++++++++++
+ 3 files changed, 110 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -79,6 +79,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       mcp2515-can1.dtbo \
+       mcp3008.dtbo \
+       mcp3202.dtbo \
++      mcp342x.dtbo \
+       media-center.dtbo \
+       midi-uart0.dtbo \
+       midi-uart1.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1277,6 +1277,22 @@ Params: spi<n>-<m>-present      boolean,
+         spi<n>-<m>-speed        integer, set the spi bus speed for this device
++Name:   mcp342x
++Info:   Overlay for activation of Microchip MCP3421-3428 ADCs over I2C
++Load:   dtoverlay=mcp342x,<param>=<val>
++Params: addr                    I2C bus address of device, for devices with
++                                addresses that are configurable, e.g. by
++                                hardware links (default=0x68)
++        mcp3421                 The device is an MCP3421
++        mcp3422                 The device is an MCP3422
++        mcp3423                 The device is an MCP3423
++        mcp3424                 The device is an MCP3424
++        mcp3425                 The device is an MCP3425
++        mcp3426                 The device is an MCP3426
++        mcp3427                 The device is an MCP3427
++        mcp3428                 The device is an MCP3428
++
++
+ Name:   media-center
+ Info:   Media Center HAT - 2.83" Touch Display + extras by Pi Supply
+ Load:   dtoverlay=media-center,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+@@ -0,0 +1,93 @@
++// Overlay for MCP3421-8 ADCs from Microchip Semiconductor
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++      fragment@0 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      mcp342x: mcp@68 {
++                              reg = <0x68>;
++
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3421";
++              };
++      };
++
++      fragment@2 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3422";
++              };
++      };
++
++      fragment@3 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3423";
++              };
++      };
++
++      fragment@4 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3424";
++              };
++      };
++
++      fragment@5 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3425";
++              };
++      };
++
++      fragment@6 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3426";
++              };
++      };
++
++      fragment@7 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3427";
++              };
++      };
++
++      fragment@8 {
++              target = <&mcp342x>;
++              __dormant__ {
++                      compatible = "microchip,mcp3428";
++              };
++      };
++
++      __overrides__ {
++              addr = <&mcp342x>,"reg:0";
++              mcp3421 = <0>,"=1";
++              mcp3422 = <0>,"=2";
++              mcp3423 = <0>,"=3";
++              mcp3424 = <0>,"=4";
++              mcp3425 = <0>,"=5";
++              mcp3426 = <0>,"=6";
++              mcp3427 = <0>,"=7";
++              mcp3428 = <0>,"=8";
++      };
++};
++
diff --git a/target/linux/brcm2708/patches-4.19/950-0268-overlays-Add-ssd1306-overlay-for-OLED-display.patch b/target/linux/brcm2708/patches-4.19/950-0268-overlays-Add-ssd1306-overlay-for-OLED-display.patch
deleted file mode 100644 (file)
index 967cc76..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-From d8eac0d3e4f6c6f9e5f789c8e2288699b2afebcb Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 21 Jan 2019 21:17:27 +0000
-Subject: [PATCH] overlays: Add ssd1306 overlay for OLED display
-
-See: https://github.com/raspberrypi/firmware/issues/1098
-
-Signed-off-by: mincepi <mincepi@gmail.com>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             | 31 ++++++++++++++++
- .../arm/boot/dts/overlays/ssd1306-overlay.dts | 36 +++++++++++++++++++
- 3 files changed, 68 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       spi2-1cs.dtbo \
-       spi2-2cs.dtbo \
-       spi2-3cs.dtbo \
-+      ssd1306.dtbo \
-       superaudioboard.dtbo \
-       sx150x.dtbo \
-       tc358743.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1950,6 +1950,37 @@ Params: cs0_pin                 GPIO pin
-                                 is 'okay' or enabled).
-+Name:   ssd1306
-+Info:   Overlay for activation of SSD1306 over I2C OLED display framebuffer.
-+Load:   dtoverlay=ssd1306,<param>=<val>
-+Params: address                 Location in display memory of first character.
-+                                (default=0)
-+        width                   Width of display. (default=128)
-+        height                  Height of display. (default=64)
-+        offset                  virtual channel a. (default=0)
-+        normal                  Has no effect on displays tested. (default=not
-+                                set)
-+        sequential              Set this if every other scan line is missing.
-+                                (default=not set)
-+        remapped                Set this if display is garbled. (default=not
-+                                set)
-+        inverted                Set this if display is inverted and mirrored.
-+                                (default=not set)
-+
-+        Examples:
-+        Typical usage for 128x64 display: dtoverlay=ssd1306,inverted
-+
-+        Typical usage for 128x32 display: dtoverlay=ssd1306,inverted,sequential
-+
-+        i2c_baudrate=400000 will speed up the display.
-+
-+        i2c_baudrate=1000000 seems to work even though it's not officially
-+        supported by the hardware, and is faster still.
-+
-+        For more information refer to the device datasheet at:
-+        https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
-+
-+
- Name:   superaudioboard
- Info:   Configures the SuperAudioBoard sound card
- Load:   dtoverlay=superaudioboard,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-@@ -0,0 +1,36 @@
-+// Overlay for SSD1306 128x64 and 128x32 OLED displays
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+    compatible = "brcm,bcm2718";
-+
-+    fragment@0 {
-+      target = <&i2c1>;
-+      __overlay__ {
-+          status = "okay";
-+
-+          #address-cells = <1>;
-+          #size-cells = <0>;
-+
-+          ssd1306: oled@3c{
-+              compatible = "solomon,ssd1306fb-i2c";
-+              reg = <0x3c>;
-+              solomon,width = <128>;
-+              solomon,height = <64>;
-+              solomon,page-offset = <0>;
-+          };
-+      };
-+    };
-+
-+    __overrides__ {
-+      address = <&ssd1306>,"reg:0";
-+      width = <&ssd1306>,"solomon,width:0";
-+      height = <&ssd1306>,"solomon,height:0";
-+      offset = <&ssd1306>,"solomon,page-offset:0";
-+      normal = <&ssd1306>,"solomon,segment-no-remap?";
-+      sequential = <&ssd1306>,"solomon,com-seq?";
-+      remapped = <&ssd1306>,"solomon,com-lrremap?";
-+      inverted = <&ssd1306>,"solomon,com-invdir?";
-+    };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0269-char-vcio-Add-compat-ioctl-handling.patch b/target/linux/brcm2708/patches-4.19/950-0269-char-vcio-Add-compat-ioctl-handling.patch
new file mode 100644 (file)
index 0000000..a9b5572
--- /dev/null
@@ -0,0 +1,58 @@
+From 70194b474d22974cd46356e5b3d3b0582abd02da Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 13:56:30 +0000
+Subject: [PATCH] char: vcio: Add compat ioctl handling
+
+There was no compat ioctl handler, so 32 bit userspace on a
+64 bit kernel failed as IOCTL_MBOX_PROPERTY used the size
+of char*.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vcio.c | 22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/broadcom/vcio.c
++++ b/drivers/char/broadcom/vcio.c
+@@ -24,6 +24,9 @@
+ #define VCIO_IOC_MAGIC 100
+ #define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
++#ifdef CONFIG_COMPAT
++#define IOCTL_MBOX_PROPERTY32 _IOWR(VCIO_IOC_MAGIC, 0, compat_uptr_t)
++#endif
+ static struct {
+       dev_t devt;
+@@ -87,13 +90,30 @@ static long vcio_device_ioctl(struct fil
+       case IOCTL_MBOX_PROPERTY:
+               return vcio_user_property_list((void *)ioctl_param);
+       default:
+-              pr_err("unknown ioctl: %d\n", ioctl_num);
++              pr_err("unknown ioctl: %x\n", ioctl_num);
+               return -EINVAL;
+       }
+ }
++#ifdef CONFIG_COMPAT
++static long vcio_device_compat_ioctl(struct file *file, unsigned int ioctl_num,
++                                   unsigned long ioctl_param)
++{
++      switch (ioctl_num) {
++      case IOCTL_MBOX_PROPERTY32:
++              return vcio_user_property_list(compat_ptr(ioctl_param));
++      default:
++              pr_err("unknown ioctl: %x\n", ioctl_num);
++              return -EINVAL;
++      }
++}
++#endif
++
+ const struct file_operations vcio_fops = {
+       .unlocked_ioctl = vcio_device_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl = vcio_device_compat_ioctl,
++#endif
+       .open = vcio_device_open,
+       .release = vcio_device_release,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0269-overlays-mcp23017-Support-the-MCP23008.patch b/target/linux/brcm2708/patches-4.19/950-0269-overlays-mcp23017-Support-the-MCP23008.patch
deleted file mode 100644 (file)
index 44f295a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From c85a1ccbc6b1cab51a5fe5b916bcaf40bcd9096c Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 21 Jan 2019 12:19:57 +0000
-Subject: [PATCH] overlays: mcp23017: Support the MCP23008
-
-Add an 'mcp23008' parameter to enable support for the MCP23008 device.
-
-See: https://github.com/raspberrypi/linux/issues/2818
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README               |  2 ++
- arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 10 +++++++++-
- 2 files changed, 11 insertions(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1212,6 +1212,8 @@ Params: gpiopin                 Gpio pin
-         addr                    I2C address of the MCP23017 (default: 0x20)
-+        mcp23008                Configure an MCP23008 instead.
-+
- Name:   mcp23s17
- Info:   Configures the MCP23S08/17 SPI GPIO expanders.
---- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-@@ -44,11 +44,19 @@
-                       };
-               };
-       };
--      
-+
-+      fragment@3 {
-+              target = <&mcp23017>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp23008";
-+              };
-+      };
-+
-       __overrides__ {
-               gpiopin = <&mcp23017_pins>,"brcm,pins:0",
-                               <&mcp23017>,"interrupts:0";
-               addr = <&mcp23017>,"reg:0";
-+              mcp23008 = <0>,"=3";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0270-char-vcio-Fail-probe-if-rpi_firmware-is-not-found.patch b/target/linux/brcm2708/patches-4.19/950-0270-char-vcio-Fail-probe-if-rpi_firmware-is-not-found.patch
new file mode 100644 (file)
index 0000000..0ec06ca
--- /dev/null
@@ -0,0 +1,28 @@
+From 6880e5c73b75be683299debf391eba4f521cc20f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 14:03:28 +0000
+Subject: [PATCH] char: vcio: Fail probe if rpi_firmware is not found.
+
+Device Tree is now the only supported config mechanism, therefore
+uncomment the block of code that fails the probe if the
+firmware node can't be found.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vcio.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/char/broadcom/vcio.c
++++ b/drivers/char/broadcom/vcio.c
+@@ -126,10 +126,9 @@ static int __init vcio_init(void)
+       np = of_find_compatible_node(NULL, NULL,
+                                    "raspberrypi,bcm2835-firmware");
+-/* Uncomment this when we only boot with Device Tree
+       if (!of_device_is_available(np))
+               return -ENODEV;
+-*/
++
+       vcio.fw = rpi_firmware_get(np);
+       if (!vcio.fw)
+               return -ENODEV;
diff --git a/target/linux/brcm2708/patches-4.19/950-0270-overlays-Add-mcp342x-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0270-overlays-Add-mcp342x-overlay.patch
deleted file mode 100644 (file)
index d104c65..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-From b71f1fd962c66ba3fa46483f193cc2263146c5bf Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 21 Jan 2019 12:23:55 +0000
-Subject: [PATCH] overlays: Add mcp342x overlay
-
-Support the MCP342x family of ADCs from Microchip.
-
-See: https://github.com/raspberrypi/linux/issues/2819
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             | 16 ++++
- .../arm/boot/dts/overlays/mcp342x-overlay.dts | 93 +++++++++++++++++++
- 3 files changed, 110 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -79,6 +79,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       mcp2515-can1.dtbo \
-       mcp3008.dtbo \
-       mcp3202.dtbo \
-+      mcp342x.dtbo \
-       media-center.dtbo \
-       midi-uart0.dtbo \
-       midi-uart1.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1277,6 +1277,22 @@ Params: spi<n>-<m>-present      boolean,
-         spi<n>-<m>-speed        integer, set the spi bus speed for this device
-+Name:   mcp342x
-+Info:   Overlay for activation of Microchip MCP3421-3428 ADCs over I2C
-+Load:   dtoverlay=mcp342x,<param>=<val>
-+Params: addr                    I2C bus address of device, for devices with
-+                                addresses that are configurable, e.g. by
-+                                hardware links (default=0x68)
-+        mcp3421                 The device is an MCP3421
-+        mcp3422                 The device is an MCP3422
-+        mcp3423                 The device is an MCP3423
-+        mcp3424                 The device is an MCP3424
-+        mcp3425                 The device is an MCP3425
-+        mcp3426                 The device is an MCP3426
-+        mcp3427                 The device is an MCP3427
-+        mcp3428                 The device is an MCP3428
-+
-+
- Name:   media-center
- Info:   Media Center HAT - 2.83" Touch Display + extras by Pi Supply
- Load:   dtoverlay=media-center,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-@@ -0,0 +1,93 @@
-+// Overlay for MCP3421-8 ADCs from Microchip Semiconductor
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+      fragment@0 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      mcp342x: mcp@68 {
-+                              reg = <0x68>;
-+
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3421";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3422";
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3423";
-+              };
-+      };
-+
-+      fragment@4 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3424";
-+              };
-+      };
-+
-+      fragment@5 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3425";
-+              };
-+      };
-+
-+      fragment@6 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3426";
-+              };
-+      };
-+
-+      fragment@7 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3427";
-+              };
-+      };
-+
-+      fragment@8 {
-+              target = <&mcp342x>;
-+              __dormant__ {
-+                      compatible = "microchip,mcp3428";
-+              };
-+      };
-+
-+      __overrides__ {
-+              addr = <&mcp342x>,"reg:0";
-+              mcp3421 = <0>,"=1";
-+              mcp3422 = <0>,"=2";
-+              mcp3423 = <0>,"=3";
-+              mcp3424 = <0>,"=4";
-+              mcp3425 = <0>,"=5";
-+              mcp3426 = <0>,"=6";
-+              mcp3427 = <0>,"=7";
-+              mcp3428 = <0>,"=8";
-+      };
-+};
-+
diff --git a/target/linux/brcm2708/patches-4.19/950-0271-char-vcio-Add-compat-ioctl-handling.patch b/target/linux/brcm2708/patches-4.19/950-0271-char-vcio-Add-compat-ioctl-handling.patch
deleted file mode 100644 (file)
index a9b5572..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 70194b474d22974cd46356e5b3d3b0582abd02da Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 13:56:30 +0000
-Subject: [PATCH] char: vcio: Add compat ioctl handling
-
-There was no compat ioctl handler, so 32 bit userspace on a
-64 bit kernel failed as IOCTL_MBOX_PROPERTY used the size
-of char*.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vcio.c | 22 +++++++++++++++++++++-
- 1 file changed, 21 insertions(+), 1 deletion(-)
-
---- a/drivers/char/broadcom/vcio.c
-+++ b/drivers/char/broadcom/vcio.c
-@@ -24,6 +24,9 @@
- #define VCIO_IOC_MAGIC 100
- #define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
-+#ifdef CONFIG_COMPAT
-+#define IOCTL_MBOX_PROPERTY32 _IOWR(VCIO_IOC_MAGIC, 0, compat_uptr_t)
-+#endif
- static struct {
-       dev_t devt;
-@@ -87,13 +90,30 @@ static long vcio_device_ioctl(struct fil
-       case IOCTL_MBOX_PROPERTY:
-               return vcio_user_property_list((void *)ioctl_param);
-       default:
--              pr_err("unknown ioctl: %d\n", ioctl_num);
-+              pr_err("unknown ioctl: %x\n", ioctl_num);
-               return -EINVAL;
-       }
- }
-+#ifdef CONFIG_COMPAT
-+static long vcio_device_compat_ioctl(struct file *file, unsigned int ioctl_num,
-+                                   unsigned long ioctl_param)
-+{
-+      switch (ioctl_num) {
-+      case IOCTL_MBOX_PROPERTY32:
-+              return vcio_user_property_list(compat_ptr(ioctl_param));
-+      default:
-+              pr_err("unknown ioctl: %x\n", ioctl_num);
-+              return -EINVAL;
-+      }
-+}
-+#endif
-+
- const struct file_operations vcio_fops = {
-       .unlocked_ioctl = vcio_device_ioctl,
-+#ifdef CONFIG_COMPAT
-+      .compat_ioctl = vcio_device_compat_ioctl,
-+#endif
-       .open = vcio_device_open,
-       .release = vcio_device_release,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0271-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch b/target/linux/brcm2708/patches-4.19/950-0271-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch
new file mode 100644 (file)
index 0000000..2e20c64
--- /dev/null
@@ -0,0 +1,68 @@
+From 18511b66fee5967ed5631e7cbe2c263f07e956f9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 22 Jan 2019 12:04:09 +0000
+Subject: [PATCH] staging: mmal-vchiq: Fix client_component for 64 bit
+ kernel
+
+The MMAL client_component field is used with the event
+mechanism to allow the client to identify the component for
+which the event is generated.
+The field is only 32bits in size, therefore we can't use a
+pointer to the component in a 64 bit kernel.
+
+Component handles are already held in an array per VCHI
+instance, so use the array index as the client_component handle
+to avoid having to create a new IDR for this purpose.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c    | 12 +++++++++---
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h    |  1 +
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -473,9 +473,9 @@ buffer_from_host(struct vchiq_mmal_insta
+ static void event_to_host_cb(struct vchiq_mmal_instance *instance,
+                            struct mmal_msg *msg, u32 msg_len)
+ {
+-      /* FIXME: Not going to work on 64 bit */
++      int comp_idx = msg->u.event_to_host.client_component;
+       struct vchiq_mmal_component *component =
+-              (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
++                                      &instance->component[comp_idx];
+       struct vchiq_mmal_port *port = NULL;
+       struct mmal_msg_context *msg_context;
+       u32 port_num = msg->u.event_to_host.port_num;
+@@ -1074,7 +1074,7 @@ static int create_component(struct vchiq
+       /* build component create message */
+       m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
+-      m.u.component_create.client_component = (u32)(unsigned long)component;
++      m.u.component_create.client_component = component->client_component;
+       strncpy(m.u.component_create.name, name,
+               sizeof(m.u.component_create.name));
+@@ -1869,6 +1869,12 @@ int vchiq_mmal_component_init(struct vch
+               goto unlock;
+       }
++      /* We need a handle to reference back to our component structure.
++       * Use the array index in instance->component rather than rolling
++       * another IDR.
++       */
++      component->client_component = idx;
++
+       ret = create_component(instance, component, name);
+       if (ret < 0) {
+               pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -97,6 +97,7 @@ struct vchiq_mmal_component {
+       struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
+       struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
+       struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
++      u32 client_component;   /* Used to ref back to client struct */
+ };
+ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
diff --git a/target/linux/brcm2708/patches-4.19/950-0272-char-vcio-Fail-probe-if-rpi_firmware-is-not-found.patch b/target/linux/brcm2708/patches-4.19/950-0272-char-vcio-Fail-probe-if-rpi_firmware-is-not-found.patch
deleted file mode 100644 (file)
index 0ec06ca..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 6880e5c73b75be683299debf391eba4f521cc20f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 14:03:28 +0000
-Subject: [PATCH] char: vcio: Fail probe if rpi_firmware is not found.
-
-Device Tree is now the only supported config mechanism, therefore
-uncomment the block of code that fails the probe if the
-firmware node can't be found.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vcio.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/char/broadcom/vcio.c
-+++ b/drivers/char/broadcom/vcio.c
-@@ -126,10 +126,9 @@ static int __init vcio_init(void)
-       np = of_find_compatible_node(NULL, NULL,
-                                    "raspberrypi,bcm2835-firmware");
--/* Uncomment this when we only boot with Device Tree
-       if (!of_device_is_available(np))
-               return -ENODEV;
--*/
-+
-       vcio.fw = rpi_firmware_get(np);
-       if (!vcio.fw)
-               return -ENODEV;
diff --git a/target/linux/brcm2708/patches-4.19/950-0272-staging-bcm2835-camera-Add-sanity-checks-for-queue_s.patch b/target/linux/brcm2708/patches-4.19/950-0272-staging-bcm2835-camera-Add-sanity-checks-for-queue_s.patch
new file mode 100644 (file)
index 0000000..c4e78a1
--- /dev/null
@@ -0,0 +1,44 @@
+From 6b3fde1207785584dbd1fdf65110cf60bd29b409 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 15 Jan 2019 15:35:24 +0000
+Subject: [PATCH] staging: bcm2835-camera: Add sanity checks for
+ queue_setup/CREATE_BUFS
+
+Fixes a v4l2-compliance failure when passed a buffer that is
+too small.
+queue_setup wasn't handling the case where !(*nplanes), as
+used from CREATE_BUFS and requiring the driver to sanity
+check the provided buffer parameters. It was assuming that
+it was always being used in the REQBUFS case where it provides
+the buffer properties.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c              | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -242,6 +242,22 @@ static int queue_setup(struct vb2_queue
+               return -EINVAL;
+       }
++      /* Handle CREATE_BUFS situation - *nplanes != 0 */
++      if (*nplanes) {
++              if (*nplanes != 1 ||
++                  sizes[0] < dev->capture.port->current_buffer.size) {
++                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++                               "%s: dev:%p Invalid buffer request from CREATE_BUFS, size %u < %u, nplanes %u != 1\n",
++                               __func__, dev, sizes[0],
++                               dev->capture.port->current_buffer.size,
++                               *nplanes);
++                      return -EINVAL;
++              } else {
++                      return 0;
++              }
++      }
++
++      /* Handle REQBUFS situation */
+       size = dev->capture.port->current_buffer.size;
+       if (size == 0) {
+               v4l2_err(&dev->v4l2_dev,
diff --git a/target/linux/brcm2708/patches-4.19/950-0273-staging-bcm2835-camera-Set-the-field-value-within-ea.patch b/target/linux/brcm2708/patches-4.19/950-0273-staging-bcm2835-camera-Set-the-field-value-within-ea.patch
new file mode 100644 (file)
index 0000000..e562e1c
--- /dev/null
@@ -0,0 +1,27 @@
+From 7f67e8ed8ae17ddca0748975de0c0efad6a5e6bb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 15 Jan 2019 16:32:33 +0000
+Subject: [PATCH] staging: bcm2835-camera: Set the field value within
+ each buffer
+
+Fixes a v4l2-compliance failure
+v4l2-test-buffers.cpp(415): g_field() == V4L2_FIELD_ANY
+
+The driver only ever produces progresive frames, so field should
+always be set to V4L2_FIELD_NONE.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -443,6 +443,7 @@ static void buffer_cb(struct vchiq_mmal_
+       }
+       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
+       buf->vb.sequence = dev->capture.sequence++;
++      buf->vb.field = V4L2_FIELD_NONE;
+       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
+       if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
diff --git a/target/linux/brcm2708/patches-4.19/950-0273-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch b/target/linux/brcm2708/patches-4.19/950-0273-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch
deleted file mode 100644 (file)
index 2e20c64..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-From 18511b66fee5967ed5631e7cbe2c263f07e956f9 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 22 Jan 2019 12:04:09 +0000
-Subject: [PATCH] staging: mmal-vchiq: Fix client_component for 64 bit
- kernel
-
-The MMAL client_component field is used with the event
-mechanism to allow the client to identify the component for
-which the event is generated.
-The field is only 32bits in size, therefore we can't use a
-pointer to the component in a 64 bit kernel.
-
-Component handles are already held in an array per VCHI
-instance, so use the array index as the client_component handle
-to avoid having to create a new IDR for this purpose.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c    | 12 +++++++++---
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h    |  1 +
- 2 files changed, 10 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -473,9 +473,9 @@ buffer_from_host(struct vchiq_mmal_insta
- static void event_to_host_cb(struct vchiq_mmal_instance *instance,
-                            struct mmal_msg *msg, u32 msg_len)
- {
--      /* FIXME: Not going to work on 64 bit */
-+      int comp_idx = msg->u.event_to_host.client_component;
-       struct vchiq_mmal_component *component =
--              (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
-+                                      &instance->component[comp_idx];
-       struct vchiq_mmal_port *port = NULL;
-       struct mmal_msg_context *msg_context;
-       u32 port_num = msg->u.event_to_host.port_num;
-@@ -1074,7 +1074,7 @@ static int create_component(struct vchiq
-       /* build component create message */
-       m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
--      m.u.component_create.client_component = (u32)(unsigned long)component;
-+      m.u.component_create.client_component = component->client_component;
-       strncpy(m.u.component_create.name, name,
-               sizeof(m.u.component_create.name));
-@@ -1869,6 +1869,12 @@ int vchiq_mmal_component_init(struct vch
-               goto unlock;
-       }
-+      /* We need a handle to reference back to our component structure.
-+       * Use the array index in instance->component rather than rolling
-+       * another IDR.
-+       */
-+      component->client_component = idx;
-+
-       ret = create_component(instance, component, name);
-       if (ret < 0) {
-               pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -97,6 +97,7 @@ struct vchiq_mmal_component {
-       struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
-       struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
-       struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
-+      u32 client_component;   /* Used to ref back to client struct */
- };
- int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
diff --git a/target/linux/brcm2708/patches-4.19/950-0274-char-vc_mem-Fix-up-compat-ioctls-for-64bit-kernel.patch b/target/linux/brcm2708/patches-4.19/950-0274-char-vc_mem-Fix-up-compat-ioctls-for-64bit-kernel.patch
new file mode 100644 (file)
index 0000000..b0beb6d
--- /dev/null
@@ -0,0 +1,111 @@
+From 966ff2b4c758eb8c8c04f26422cd183e6aa8eda5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 23 Jan 2019 18:25:50 +0000
+Subject: [PATCH] char: vc_mem: Fix up compat ioctls for 64bit kernel
+
+compat_ioctl wasn't defined, so 32bit user/64bit kernel
+always failed.
+VC_MEM_IOC_MEM_PHYS_ADDR was defined with parameter size
+unsigned long, so the ioctl cmd changes between sizes.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vc_mem.c  | 40 +++++++++++++++++++++++++++++----
+ include/linux/broadcom/vc_mem.h |  4 ++++
+ 2 files changed, 40 insertions(+), 4 deletions(-)
+
+--- a/drivers/char/broadcom/vc_mem.c
++++ b/drivers/char/broadcom/vc_mem.c
+@@ -148,7 +148,7 @@ vc_mem_ioctl(struct file *file, unsigned
+       (void) cmd;
+       (void) arg;
+-      pr_debug("%s: called file = 0x%p\n", __func__, file);
++      pr_debug("%s: called file = 0x%p, cmd %08x\n", __func__, file, cmd);
+       switch (cmd) {
+       case VC_MEM_IOC_MEM_PHYS_ADDR:
+@@ -167,7 +167,7 @@ vc_mem_ioctl(struct file *file, unsigned
+                       // Get the videocore memory size first
+                       vc_mem_get_size();
+-                      pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
++                      pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
+                               mm_vc_mem_size);
+                       if (copy_to_user((void *) arg, &mm_vc_mem_size,
+@@ -181,7 +181,7 @@ vc_mem_ioctl(struct file *file, unsigned
+                       // Get the videocore memory base
+                       vc_mem_get_base();
+-                      pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
++                      pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
+                               mm_vc_mem_base);
+                       if (copy_to_user((void *) arg, &mm_vc_mem_base,
+@@ -195,7 +195,7 @@ vc_mem_ioctl(struct file *file, unsigned
+                       // Get the videocore memory base
+                       vc_mem_get_base();
+-                      pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
++                      pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
+                               mm_vc_mem_base);
+                       if (copy_to_user((void *) arg, &mm_vc_mem_base,
+@@ -214,6 +214,35 @@ vc_mem_ioctl(struct file *file, unsigned
+       return rc;
+ }
++#ifdef CONFIG_COMPAT
++static long
++vc_mem_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++      int rc = 0;
++
++      switch (cmd) {
++      case VC_MEM_IOC_MEM_PHYS_ADDR32:
++              pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR32=0x%p\n",
++                       __func__, (void *)mm_vc_mem_phys_addr);
++
++              /* This isn't correct, but will cover us for now as
++               * VideoCore is 32bit only.
++               */
++              if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
++                               sizeof(compat_ulong_t)))
++                      rc = -EFAULT;
++
++              break;
++
++      default:
++              rc = vc_mem_ioctl(file, cmd, arg);
++              break;
++      }
++
++      return rc;
++}
++#endif
++
+ /****************************************************************************
+ *
+ *   vc_mem_mmap
+@@ -259,6 +288,9 @@ static const struct file_operations vc_m
+       .open = vc_mem_open,
+       .release = vc_mem_release,
+       .unlocked_ioctl = vc_mem_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl = vc_mem_compat_ioctl,
++#endif
+       .mmap = vc_mem_mmap,
+ };
+--- a/include/linux/broadcom/vc_mem.h
++++ b/include/linux/broadcom/vc_mem.h
+@@ -32,4 +32,8 @@ extern unsigned int  mm_vc_mem_size;
+ extern int vc_mem_get_current_size( void );
+ #endif
++#ifdef CONFIG_COMPAT
++#define VC_MEM_IOC_MEM_PHYS_ADDR32  _IOR(VC_MEM_IOC_MAGIC, 0, compat_ulong_t)
++#endif
++
+ #endif  /* _VC_MEM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0274-staging-bcm2835-camera-Add-sanity-checks-for-queue_s.patch b/target/linux/brcm2708/patches-4.19/950-0274-staging-bcm2835-camera-Add-sanity-checks-for-queue_s.patch
deleted file mode 100644 (file)
index c4e78a1..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 6b3fde1207785584dbd1fdf65110cf60bd29b409 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 15 Jan 2019 15:35:24 +0000
-Subject: [PATCH] staging: bcm2835-camera: Add sanity checks for
- queue_setup/CREATE_BUFS
-
-Fixes a v4l2-compliance failure when passed a buffer that is
-too small.
-queue_setup wasn't handling the case where !(*nplanes), as
-used from CREATE_BUFS and requiring the driver to sanity
-check the provided buffer parameters. It was assuming that
-it was always being used in the REQBUFS case where it provides
-the buffer properties.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c              | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -242,6 +242,22 @@ static int queue_setup(struct vb2_queue
-               return -EINVAL;
-       }
-+      /* Handle CREATE_BUFS situation - *nplanes != 0 */
-+      if (*nplanes) {
-+              if (*nplanes != 1 ||
-+                  sizes[0] < dev->capture.port->current_buffer.size) {
-+                      v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+                               "%s: dev:%p Invalid buffer request from CREATE_BUFS, size %u < %u, nplanes %u != 1\n",
-+                               __func__, dev, sizes[0],
-+                               dev->capture.port->current_buffer.size,
-+                               *nplanes);
-+                      return -EINVAL;
-+              } else {
-+                      return 0;
-+              }
-+      }
-+
-+      /* Handle REQBUFS situation */
-       size = dev->capture.port->current_buffer.size;
-       if (size == 0) {
-               v4l2_err(&dev->v4l2_dev,
diff --git a/target/linux/brcm2708/patches-4.19/950-0275-char-vc_mem-Fix-all-coding-style-issues.patch b/target/linux/brcm2708/patches-4.19/950-0275-char-vc_mem-Fix-all-coding-style-issues.patch
new file mode 100644 (file)
index 0000000..e0b6adf
--- /dev/null
@@ -0,0 +1,428 @@
+From 8d64f178c3568d212f3ddf05ea1ad7f103beeb86 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 23 Jan 2019 18:37:29 +0000
+Subject: [PATCH] char: vc_mem: Fix all coding style issues.
+
+Cleans up all checkpatch errors in vc_mem.c and vc_mem.h
+No functional change to the code.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vc_mem.c  | 177 +++++++++++---------------------
+ include/linux/broadcom/vc_mem.h |  38 +++----
+ 2 files changed, 77 insertions(+), 138 deletions(-)
+
+--- a/drivers/char/broadcom/vc_mem.c
++++ b/drivers/char/broadcom/vc_mem.c
+@@ -1,16 +1,16 @@
+-/*****************************************************************************
+-* Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
+-*
+-* Unless you and Broadcom execute a separate written software license
+-* agreement governing use of this software, this software is licensed to you
+-* under the terms of the GNU General Public License version 2, available at
+-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+-*
+-* Notwithstanding the above, under no circumstances may you combine this
+-* software in any way with any other Broadcom software provided under a
+-* license other than the GPL, without Broadcom's express prior written
+-* consent.
+-*****************************************************************************/
++/*
++ * Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
++ *
++ * Unless you and Broadcom execute a separate written software license
++ * agreement governing use of this software, this software is licensed to you
++ * under the terms of the GNU General Public License version 2, available at
++ * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++ *
++ * Notwithstanding the above, under no circumstances may you combine this
++ * software in any way with any other Broadcom software provided under a
++ * license other than the GPL, without Broadcom's express prior written
++ * consent.
++ */
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -26,11 +26,11 @@
+ #define DRIVER_NAME  "vc-mem"
+-// Device (/dev) related variables
+-static dev_t vc_mem_devnum = 0;
+-static struct class *vc_mem_class = NULL;
++/* Device (/dev) related variables */
++static dev_t vc_mem_devnum;
++static struct class *vc_mem_class;
+ static struct cdev vc_mem_cdev;
+-static int vc_mem_inited = 0;
++static int vc_mem_inited;
+ #ifdef CONFIG_DEBUG_FS
+ static struct dentry *vc_mem_debugfs_entry;
+@@ -50,96 +50,55 @@ static struct dentry *vc_mem_debugfs_ent
+  * bootloader (and/or kernel). When that happens, the values of these variables
+  * would be calculated and assigned in the init function.
+  */
+-// in the 2835 VC in mapped above ARM, but ARM has full access to VC space
+-unsigned long mm_vc_mem_phys_addr = 0x00000000;
+-unsigned int mm_vc_mem_size = 0;
+-unsigned int mm_vc_mem_base = 0;
+-
++/* In the 2835 VC in mapped above ARM, but ARM has full access to VC space */
++unsigned long mm_vc_mem_phys_addr;
+ EXPORT_SYMBOL(mm_vc_mem_phys_addr);
++unsigned int mm_vc_mem_size;
+ EXPORT_SYMBOL(mm_vc_mem_size);
++unsigned int mm_vc_mem_base;
+ EXPORT_SYMBOL(mm_vc_mem_base);
+-static uint phys_addr = 0;
+-static uint mem_size = 0;
+-static uint mem_base = 0;
+-
+-
+-/****************************************************************************
+-*
+-*   vc_mem_open
+-*
+-***************************************************************************/
++static uint phys_addr;
++static uint mem_size;
++static uint mem_base;
+ static int
+ vc_mem_open(struct inode *inode, struct file *file)
+ {
+-      (void) inode;
+-      (void) file;
++      (void)inode;
+       pr_debug("%s: called file = 0x%p\n", __func__, file);
+       return 0;
+ }
+-/****************************************************************************
+-*
+-*   vc_mem_release
+-*
+-***************************************************************************/
+-
+ static int
+ vc_mem_release(struct inode *inode, struct file *file)
+ {
+-      (void) inode;
+-      (void) file;
++      (void)inode;
+       pr_debug("%s: called file = 0x%p\n", __func__, file);
+       return 0;
+ }
+-/****************************************************************************
+-*
+-*   vc_mem_get_size
+-*
+-***************************************************************************/
+-
+ static void
+ vc_mem_get_size(void)
+ {
+ }
+-/****************************************************************************
+-*
+-*   vc_mem_get_base
+-*
+-***************************************************************************/
+-
+ static void
+ vc_mem_get_base(void)
+ {
+ }
+-/****************************************************************************
+-*
+-*   vc_mem_get_current_size
+-*
+-***************************************************************************/
+-
+ int
+ vc_mem_get_current_size(void)
+ {
+       return mm_vc_mem_size;
+ }
+-
+ EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
+-/****************************************************************************
+-*
+-*   vc_mem_ioctl
+-*
+-***************************************************************************/
+-
+ static long
+ vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+@@ -154,52 +113,52 @@ vc_mem_ioctl(struct file *file, unsigned
+       case VC_MEM_IOC_MEM_PHYS_ADDR:
+               {
+                       pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
+-                              __func__, (void *) mm_vc_mem_phys_addr);
++                              __func__, (void *)mm_vc_mem_phys_addr);
+-                      if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
+-                                       sizeof (mm_vc_mem_phys_addr)) != 0) {
++                      if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
++                                       sizeof(mm_vc_mem_phys_addr))) {
+                               rc = -EFAULT;
+                       }
+                       break;
+               }
+       case VC_MEM_IOC_MEM_SIZE:
+               {
+-                      // Get the videocore memory size first
++                      /* Get the videocore memory size first */
+                       vc_mem_get_size();
+                       pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
+-                              mm_vc_mem_size);
++                               mm_vc_mem_size);
+-                      if (copy_to_user((void *) arg, &mm_vc_mem_size,
+-                                       sizeof (mm_vc_mem_size)) != 0) {
++                      if (copy_to_user((void *)arg, &mm_vc_mem_size,
++                                       sizeof(mm_vc_mem_size))) {
+                               rc = -EFAULT;
+                       }
+                       break;
+               }
+       case VC_MEM_IOC_MEM_BASE:
+               {
+-                      // Get the videocore memory base
++                      /* Get the videocore memory base */
+                       vc_mem_get_base();
+                       pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
+-                              mm_vc_mem_base);
++                               mm_vc_mem_base);
+-                      if (copy_to_user((void *) arg, &mm_vc_mem_base,
+-                                       sizeof (mm_vc_mem_base)) != 0) {
++                      if (copy_to_user((void *)arg, &mm_vc_mem_base,
++                                       sizeof(mm_vc_mem_base))) {
+                               rc = -EFAULT;
+                       }
+                       break;
+               }
+       case VC_MEM_IOC_MEM_LOAD:
+               {
+-                      // Get the videocore memory base
++                      /* Get the videocore memory base */
+                       vc_mem_get_base();
+                       pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
+                               mm_vc_mem_base);
+-                      if (copy_to_user((void *) arg, &mm_vc_mem_base,
+-                                       sizeof (mm_vc_mem_base)) != 0) {
++                      if (copy_to_user((void *)arg, &mm_vc_mem_base,
++                                       sizeof(mm_vc_mem_base))) {
+                               rc = -EFAULT;
+                       }
+                       break;
+@@ -243,12 +202,6 @@ vc_mem_compat_ioctl(struct file *file, u
+ }
+ #endif
+-/****************************************************************************
+-*
+-*   vc_mem_mmap
+-*
+-***************************************************************************/
+-
+ static int
+ vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+@@ -257,32 +210,26 @@ vc_mem_mmap(struct file *filp, struct vm
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
+-              __func__, (long) vma->vm_start, (long) vma->vm_end,
+-              (long) vma->vm_pgoff);
++               __func__, (long)vma->vm_start, (long)vma->vm_end,
++               (long)vma->vm_pgoff);
+       if (offset + length > mm_vc_mem_size) {
+               pr_err("%s: length %ld is too big\n", __func__, length);
+               return -EINVAL;
+       }
+-      // Do not cache the memory map
++      /* Do not cache the memory map */
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       rc = remap_pfn_range(vma, vma->vm_start,
+                            (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
+                            vma->vm_pgoff, length, vma->vm_page_prot);
+-      if (rc != 0) {
++      if (rc)
+               pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
+-      }
+       return rc;
+ }
+-/****************************************************************************
+-*
+-*   File Operations for the driver.
+-*
+-***************************************************************************/
+-
++/* File Operations for the driver. */
+ static const struct file_operations vc_mem_fops = {
+       .owner = THIS_MODULE,
+       .open = vc_mem_open,
+@@ -316,7 +263,7 @@ static int vc_mem_debugfs_init(
+                               vc_mem_debugfs_entry,
+                               (u32 *)&mm_vc_mem_phys_addr)) {
+               dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
+-                      __func__);
++                       __func__);
+               goto fail;
+       }
+@@ -325,7 +272,7 @@ static int vc_mem_debugfs_init(
+                               vc_mem_debugfs_entry,
+                               (u32 *)&mm_vc_mem_size)) {
+               dev_warn(dev, "%s:could not create vc_mem_size entry\n",
+-                      __func__);
++                       __func__);
+               goto fail;
+       }
+@@ -347,12 +294,7 @@ fail:
+ #endif /* CONFIG_DEBUG_FS */
+-
+-/****************************************************************************
+-*
+-*   vc_mem_init
+-*
+-***************************************************************************/
++/* Module load/unload functions */
+ static int __init
+ vc_mem_init(void)
+@@ -369,16 +311,19 @@ vc_mem_init(void)
+       vc_mem_get_size();
+       pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
+-              mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
++              mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size,
++              mm_vc_mem_size / (1024 * 1024));
+-      if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
++      rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME);
++      if (rc < 0) {
+               pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
+                      __func__, rc);
+               goto out_err;
+       }
+       cdev_init(&vc_mem_cdev, &vc_mem_fops);
+-      if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
++      rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1);
++      if (rc) {
+               pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
+               goto out_unregister;
+       }
+@@ -408,26 +353,20 @@ vc_mem_init(void)
+       device_destroy(vc_mem_class, vc_mem_devnum);
+-      out_class_destroy:
++out_class_destroy:
+       class_destroy(vc_mem_class);
+       vc_mem_class = NULL;
+-      out_cdev_del:
++out_cdev_del:
+       cdev_del(&vc_mem_cdev);
+-      out_unregister:
++out_unregister:
+       unregister_chrdev_region(vc_mem_devnum, 1);
+-      out_err:
++out_err:
+       return -1;
+ }
+-/****************************************************************************
+-*
+-*   vc_mem_exit
+-*
+-***************************************************************************/
+-
+ static void __exit
+ vc_mem_exit(void)
+ {
+--- a/include/linux/broadcom/vc_mem.h
++++ b/include/linux/broadcom/vc_mem.h
+@@ -1,16 +1,16 @@
+-/*****************************************************************************
+-* Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
+-*
+-* Unless you and Broadcom execute a separate written software license
+-* agreement governing use of this software, this software is licensed to you
+-* under the terms of the GNU General Public License version 2, available at
+-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+-*
+-* Notwithstanding the above, under no circumstances may you combine this
+-* software in any way with any other Broadcom software provided under a
+-* license other than the GPL, without Broadcom's express prior written
+-* consent.
+-*****************************************************************************/
++/*
++ * Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
++ *
++ * Unless you and Broadcom execute a separate written software license
++ * agreement governing use of this software, this software is licensed to you
++ * under the terms of the GNU General Public License version 2, available at
++ * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++ *
++ * Notwithstanding the above, under no circumstances may you combine this
++ * software in any way with any other Broadcom software provided under a
++ * license other than the GPL, without Broadcom's express prior written
++ * consent.
++ */
+ #ifndef _VC_MEM_H
+ #define _VC_MEM_H
+@@ -19,17 +19,17 @@
+ #define VC_MEM_IOC_MAGIC  'v'
+-#define VC_MEM_IOC_MEM_PHYS_ADDR    _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
+-#define VC_MEM_IOC_MEM_SIZE         _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
+-#define VC_MEM_IOC_MEM_BASE         _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
+-#define VC_MEM_IOC_MEM_LOAD         _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )
++#define VC_MEM_IOC_MEM_PHYS_ADDR    _IOR(VC_MEM_IOC_MAGIC, 0, unsigned long)
++#define VC_MEM_IOC_MEM_SIZE         _IOR(VC_MEM_IOC_MAGIC, 1, unsigned int)
++#define VC_MEM_IOC_MEM_BASE         _IOR(VC_MEM_IOC_MAGIC, 2, unsigned int)
++#define VC_MEM_IOC_MEM_LOAD         _IOR(VC_MEM_IOC_MAGIC, 3, unsigned int)
+-#if defined( __KERNEL__ )
++#ifdef __KERNEL__
+ #define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
+ extern unsigned long mm_vc_mem_phys_addr;
+ extern unsigned int  mm_vc_mem_size;
+-extern int vc_mem_get_current_size( void );
++extern int vc_mem_get_current_size(void);
+ #endif
+ #ifdef CONFIG_COMPAT
diff --git a/target/linux/brcm2708/patches-4.19/950-0275-staging-bcm2835-camera-Set-the-field-value-within-ea.patch b/target/linux/brcm2708/patches-4.19/950-0275-staging-bcm2835-camera-Set-the-field-value-within-ea.patch
deleted file mode 100644 (file)
index e562e1c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 7f67e8ed8ae17ddca0748975de0c0efad6a5e6bb Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 15 Jan 2019 16:32:33 +0000
-Subject: [PATCH] staging: bcm2835-camera: Set the field value within
- each buffer
-
-Fixes a v4l2-compliance failure
-v4l2-test-buffers.cpp(415): g_field() == V4L2_FIELD_ANY
-
-The driver only ever produces progresive frames, so field should
-always be set to V4L2_FIELD_NONE.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -443,6 +443,7 @@ static void buffer_cb(struct vchiq_mmal_
-       }
-       dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-       buf->vb.sequence = dev->capture.sequence++;
-+      buf->vb.field = V4L2_FIELD_NONE;
-       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
-       if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
diff --git a/target/linux/brcm2708/patches-4.19/950-0276-char-vc_mem-Fix-up-compat-ioctls-for-64bit-kernel.patch b/target/linux/brcm2708/patches-4.19/950-0276-char-vc_mem-Fix-up-compat-ioctls-for-64bit-kernel.patch
deleted file mode 100644 (file)
index b0beb6d..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-From 966ff2b4c758eb8c8c04f26422cd183e6aa8eda5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 23 Jan 2019 18:25:50 +0000
-Subject: [PATCH] char: vc_mem: Fix up compat ioctls for 64bit kernel
-
-compat_ioctl wasn't defined, so 32bit user/64bit kernel
-always failed.
-VC_MEM_IOC_MEM_PHYS_ADDR was defined with parameter size
-unsigned long, so the ioctl cmd changes between sizes.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vc_mem.c  | 40 +++++++++++++++++++++++++++++----
- include/linux/broadcom/vc_mem.h |  4 ++++
- 2 files changed, 40 insertions(+), 4 deletions(-)
-
---- a/drivers/char/broadcom/vc_mem.c
-+++ b/drivers/char/broadcom/vc_mem.c
-@@ -148,7 +148,7 @@ vc_mem_ioctl(struct file *file, unsigned
-       (void) cmd;
-       (void) arg;
--      pr_debug("%s: called file = 0x%p\n", __func__, file);
-+      pr_debug("%s: called file = 0x%p, cmd %08x\n", __func__, file, cmd);
-       switch (cmd) {
-       case VC_MEM_IOC_MEM_PHYS_ADDR:
-@@ -167,7 +167,7 @@ vc_mem_ioctl(struct file *file, unsigned
-                       // Get the videocore memory size first
-                       vc_mem_get_size();
--                      pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
-+                      pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
-                               mm_vc_mem_size);
-                       if (copy_to_user((void *) arg, &mm_vc_mem_size,
-@@ -181,7 +181,7 @@ vc_mem_ioctl(struct file *file, unsigned
-                       // Get the videocore memory base
-                       vc_mem_get_base();
--                      pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
-+                      pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
-                               mm_vc_mem_base);
-                       if (copy_to_user((void *) arg, &mm_vc_mem_base,
-@@ -195,7 +195,7 @@ vc_mem_ioctl(struct file *file, unsigned
-                       // Get the videocore memory base
-                       vc_mem_get_base();
--                      pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
-+                      pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
-                               mm_vc_mem_base);
-                       if (copy_to_user((void *) arg, &mm_vc_mem_base,
-@@ -214,6 +214,35 @@ vc_mem_ioctl(struct file *file, unsigned
-       return rc;
- }
-+#ifdef CONFIG_COMPAT
-+static long
-+vc_mem_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+      int rc = 0;
-+
-+      switch (cmd) {
-+      case VC_MEM_IOC_MEM_PHYS_ADDR32:
-+              pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR32=0x%p\n",
-+                       __func__, (void *)mm_vc_mem_phys_addr);
-+
-+              /* This isn't correct, but will cover us for now as
-+               * VideoCore is 32bit only.
-+               */
-+              if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
-+                               sizeof(compat_ulong_t)))
-+                      rc = -EFAULT;
-+
-+              break;
-+
-+      default:
-+              rc = vc_mem_ioctl(file, cmd, arg);
-+              break;
-+      }
-+
-+      return rc;
-+}
-+#endif
-+
- /****************************************************************************
- *
- *   vc_mem_mmap
-@@ -259,6 +288,9 @@ static const struct file_operations vc_m
-       .open = vc_mem_open,
-       .release = vc_mem_release,
-       .unlocked_ioctl = vc_mem_ioctl,
-+#ifdef CONFIG_COMPAT
-+      .compat_ioctl = vc_mem_compat_ioctl,
-+#endif
-       .mmap = vc_mem_mmap,
- };
---- a/include/linux/broadcom/vc_mem.h
-+++ b/include/linux/broadcom/vc_mem.h
-@@ -32,4 +32,8 @@ extern unsigned int  mm_vc_mem_size;
- extern int vc_mem_get_current_size( void );
- #endif
-+#ifdef CONFIG_COMPAT
-+#define VC_MEM_IOC_MEM_PHYS_ADDR32  _IOR(VC_MEM_IOC_MAGIC, 0, compat_ulong_t)
-+#endif
-+
- #endif  /* _VC_MEM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0276-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch b/target/linux/brcm2708/patches-4.19/950-0276-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch
new file mode 100644 (file)
index 0000000..ee4fbbd
--- /dev/null
@@ -0,0 +1,24 @@
+From 83a7175c91133a3e7a746693847b447bf6297094 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 15:09:28 +0000
+Subject: [PATCH] clk: clk-bcm2835: Use %zd when printing size_t
+
+The debug text for how many clocks have been registered
+uses "%d" with a size_t. Correct it to "%zd".
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -2271,7 +2271,7 @@ static int bcm2835_clk_probe(struct plat
+               return ret;
+       /* note that we have registered all the clocks */
+-      dev_dbg(dev, "registered %d clocks\n", asize);
++      dev_dbg(dev, "registered %zd clocks\n", asize);
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0277-char-vc_mem-Fix-all-coding-style-issues.patch b/target/linux/brcm2708/patches-4.19/950-0277-char-vc_mem-Fix-all-coding-style-issues.patch
deleted file mode 100644 (file)
index e0b6adf..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-From 8d64f178c3568d212f3ddf05ea1ad7f103beeb86 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 23 Jan 2019 18:37:29 +0000
-Subject: [PATCH] char: vc_mem: Fix all coding style issues.
-
-Cleans up all checkpatch errors in vc_mem.c and vc_mem.h
-No functional change to the code.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vc_mem.c  | 177 +++++++++++---------------------
- include/linux/broadcom/vc_mem.h |  38 +++----
- 2 files changed, 77 insertions(+), 138 deletions(-)
-
---- a/drivers/char/broadcom/vc_mem.c
-+++ b/drivers/char/broadcom/vc_mem.c
-@@ -1,16 +1,16 @@
--/*****************************************************************************
--* Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
--*
--* Unless you and Broadcom execute a separate written software license
--* agreement governing use of this software, this software is licensed to you
--* under the terms of the GNU General Public License version 2, available at
--* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
--*
--* Notwithstanding the above, under no circumstances may you combine this
--* software in any way with any other Broadcom software provided under a
--* license other than the GPL, without Broadcom's express prior written
--* consent.
--*****************************************************************************/
-+/*
-+ * Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
-+ *
-+ * Unless you and Broadcom execute a separate written software license
-+ * agreement governing use of this software, this software is licensed to you
-+ * under the terms of the GNU General Public License version 2, available at
-+ * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+ *
-+ * Notwithstanding the above, under no circumstances may you combine this
-+ * software in any way with any other Broadcom software provided under a
-+ * license other than the GPL, without Broadcom's express prior written
-+ * consent.
-+ */
- #include <linux/kernel.h>
- #include <linux/module.h>
-@@ -26,11 +26,11 @@
- #define DRIVER_NAME  "vc-mem"
--// Device (/dev) related variables
--static dev_t vc_mem_devnum = 0;
--static struct class *vc_mem_class = NULL;
-+/* Device (/dev) related variables */
-+static dev_t vc_mem_devnum;
-+static struct class *vc_mem_class;
- static struct cdev vc_mem_cdev;
--static int vc_mem_inited = 0;
-+static int vc_mem_inited;
- #ifdef CONFIG_DEBUG_FS
- static struct dentry *vc_mem_debugfs_entry;
-@@ -50,96 +50,55 @@ static struct dentry *vc_mem_debugfs_ent
-  * bootloader (and/or kernel). When that happens, the values of these variables
-  * would be calculated and assigned in the init function.
-  */
--// in the 2835 VC in mapped above ARM, but ARM has full access to VC space
--unsigned long mm_vc_mem_phys_addr = 0x00000000;
--unsigned int mm_vc_mem_size = 0;
--unsigned int mm_vc_mem_base = 0;
--
-+/* In the 2835 VC in mapped above ARM, but ARM has full access to VC space */
-+unsigned long mm_vc_mem_phys_addr;
- EXPORT_SYMBOL(mm_vc_mem_phys_addr);
-+unsigned int mm_vc_mem_size;
- EXPORT_SYMBOL(mm_vc_mem_size);
-+unsigned int mm_vc_mem_base;
- EXPORT_SYMBOL(mm_vc_mem_base);
--static uint phys_addr = 0;
--static uint mem_size = 0;
--static uint mem_base = 0;
--
--
--/****************************************************************************
--*
--*   vc_mem_open
--*
--***************************************************************************/
-+static uint phys_addr;
-+static uint mem_size;
-+static uint mem_base;
- static int
- vc_mem_open(struct inode *inode, struct file *file)
- {
--      (void) inode;
--      (void) file;
-+      (void)inode;
-       pr_debug("%s: called file = 0x%p\n", __func__, file);
-       return 0;
- }
--/****************************************************************************
--*
--*   vc_mem_release
--*
--***************************************************************************/
--
- static int
- vc_mem_release(struct inode *inode, struct file *file)
- {
--      (void) inode;
--      (void) file;
-+      (void)inode;
-       pr_debug("%s: called file = 0x%p\n", __func__, file);
-       return 0;
- }
--/****************************************************************************
--*
--*   vc_mem_get_size
--*
--***************************************************************************/
--
- static void
- vc_mem_get_size(void)
- {
- }
--/****************************************************************************
--*
--*   vc_mem_get_base
--*
--***************************************************************************/
--
- static void
- vc_mem_get_base(void)
- {
- }
--/****************************************************************************
--*
--*   vc_mem_get_current_size
--*
--***************************************************************************/
--
- int
- vc_mem_get_current_size(void)
- {
-       return mm_vc_mem_size;
- }
--
- EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
--/****************************************************************************
--*
--*   vc_mem_ioctl
--*
--***************************************************************************/
--
- static long
- vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- {
-@@ -154,52 +113,52 @@ vc_mem_ioctl(struct file *file, unsigned
-       case VC_MEM_IOC_MEM_PHYS_ADDR:
-               {
-                       pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
--                              __func__, (void *) mm_vc_mem_phys_addr);
-+                              __func__, (void *)mm_vc_mem_phys_addr);
--                      if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
--                                       sizeof (mm_vc_mem_phys_addr)) != 0) {
-+                      if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
-+                                       sizeof(mm_vc_mem_phys_addr))) {
-                               rc = -EFAULT;
-                       }
-                       break;
-               }
-       case VC_MEM_IOC_MEM_SIZE:
-               {
--                      // Get the videocore memory size first
-+                      /* Get the videocore memory size first */
-                       vc_mem_get_size();
-                       pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
--                              mm_vc_mem_size);
-+                               mm_vc_mem_size);
--                      if (copy_to_user((void *) arg, &mm_vc_mem_size,
--                                       sizeof (mm_vc_mem_size)) != 0) {
-+                      if (copy_to_user((void *)arg, &mm_vc_mem_size,
-+                                       sizeof(mm_vc_mem_size))) {
-                               rc = -EFAULT;
-                       }
-                       break;
-               }
-       case VC_MEM_IOC_MEM_BASE:
-               {
--                      // Get the videocore memory base
-+                      /* Get the videocore memory base */
-                       vc_mem_get_base();
-                       pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
--                              mm_vc_mem_base);
-+                               mm_vc_mem_base);
--                      if (copy_to_user((void *) arg, &mm_vc_mem_base,
--                                       sizeof (mm_vc_mem_base)) != 0) {
-+                      if (copy_to_user((void *)arg, &mm_vc_mem_base,
-+                                       sizeof(mm_vc_mem_base))) {
-                               rc = -EFAULT;
-                       }
-                       break;
-               }
-       case VC_MEM_IOC_MEM_LOAD:
-               {
--                      // Get the videocore memory base
-+                      /* Get the videocore memory base */
-                       vc_mem_get_base();
-                       pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
-                               mm_vc_mem_base);
--                      if (copy_to_user((void *) arg, &mm_vc_mem_base,
--                                       sizeof (mm_vc_mem_base)) != 0) {
-+                      if (copy_to_user((void *)arg, &mm_vc_mem_base,
-+                                       sizeof(mm_vc_mem_base))) {
-                               rc = -EFAULT;
-                       }
-                       break;
-@@ -243,12 +202,6 @@ vc_mem_compat_ioctl(struct file *file, u
- }
- #endif
--/****************************************************************************
--*
--*   vc_mem_mmap
--*
--***************************************************************************/
--
- static int
- vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)
- {
-@@ -257,32 +210,26 @@ vc_mem_mmap(struct file *filp, struct vm
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
--              __func__, (long) vma->vm_start, (long) vma->vm_end,
--              (long) vma->vm_pgoff);
-+               __func__, (long)vma->vm_start, (long)vma->vm_end,
-+               (long)vma->vm_pgoff);
-       if (offset + length > mm_vc_mem_size) {
-               pr_err("%s: length %ld is too big\n", __func__, length);
-               return -EINVAL;
-       }
--      // Do not cache the memory map
-+      /* Do not cache the memory map */
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       rc = remap_pfn_range(vma, vma->vm_start,
-                            (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
-                            vma->vm_pgoff, length, vma->vm_page_prot);
--      if (rc != 0) {
-+      if (rc)
-               pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
--      }
-       return rc;
- }
--/****************************************************************************
--*
--*   File Operations for the driver.
--*
--***************************************************************************/
--
-+/* File Operations for the driver. */
- static const struct file_operations vc_mem_fops = {
-       .owner = THIS_MODULE,
-       .open = vc_mem_open,
-@@ -316,7 +263,7 @@ static int vc_mem_debugfs_init(
-                               vc_mem_debugfs_entry,
-                               (u32 *)&mm_vc_mem_phys_addr)) {
-               dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
--                      __func__);
-+                       __func__);
-               goto fail;
-       }
-@@ -325,7 +272,7 @@ static int vc_mem_debugfs_init(
-                               vc_mem_debugfs_entry,
-                               (u32 *)&mm_vc_mem_size)) {
-               dev_warn(dev, "%s:could not create vc_mem_size entry\n",
--                      __func__);
-+                       __func__);
-               goto fail;
-       }
-@@ -347,12 +294,7 @@ fail:
- #endif /* CONFIG_DEBUG_FS */
--
--/****************************************************************************
--*
--*   vc_mem_init
--*
--***************************************************************************/
-+/* Module load/unload functions */
- static int __init
- vc_mem_init(void)
-@@ -369,16 +311,19 @@ vc_mem_init(void)
-       vc_mem_get_size();
-       pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
--              mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
-+              mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size,
-+              mm_vc_mem_size / (1024 * 1024));
--      if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
-+      rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME);
-+      if (rc < 0) {
-               pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
-                      __func__, rc);
-               goto out_err;
-       }
-       cdev_init(&vc_mem_cdev, &vc_mem_fops);
--      if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
-+      rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1);
-+      if (rc) {
-               pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
-               goto out_unregister;
-       }
-@@ -408,26 +353,20 @@ vc_mem_init(void)
-       device_destroy(vc_mem_class, vc_mem_devnum);
--      out_class_destroy:
-+out_class_destroy:
-       class_destroy(vc_mem_class);
-       vc_mem_class = NULL;
--      out_cdev_del:
-+out_cdev_del:
-       cdev_del(&vc_mem_cdev);
--      out_unregister:
-+out_unregister:
-       unregister_chrdev_region(vc_mem_devnum, 1);
--      out_err:
-+out_err:
-       return -1;
- }
--/****************************************************************************
--*
--*   vc_mem_exit
--*
--***************************************************************************/
--
- static void __exit
- vc_mem_exit(void)
- {
---- a/include/linux/broadcom/vc_mem.h
-+++ b/include/linux/broadcom/vc_mem.h
-@@ -1,16 +1,16 @@
--/*****************************************************************************
--* Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
--*
--* Unless you and Broadcom execute a separate written software license
--* agreement governing use of this software, this software is licensed to you
--* under the terms of the GNU General Public License version 2, available at
--* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
--*
--* Notwithstanding the above, under no circumstances may you combine this
--* software in any way with any other Broadcom software provided under a
--* license other than the GPL, without Broadcom's express prior written
--* consent.
--*****************************************************************************/
-+/*
-+ * Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.
-+ *
-+ * Unless you and Broadcom execute a separate written software license
-+ * agreement governing use of this software, this software is licensed to you
-+ * under the terms of the GNU General Public License version 2, available at
-+ * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+ *
-+ * Notwithstanding the above, under no circumstances may you combine this
-+ * software in any way with any other Broadcom software provided under a
-+ * license other than the GPL, without Broadcom's express prior written
-+ * consent.
-+ */
- #ifndef _VC_MEM_H
- #define _VC_MEM_H
-@@ -19,17 +19,17 @@
- #define VC_MEM_IOC_MAGIC  'v'
--#define VC_MEM_IOC_MEM_PHYS_ADDR    _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
--#define VC_MEM_IOC_MEM_SIZE         _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
--#define VC_MEM_IOC_MEM_BASE         _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
--#define VC_MEM_IOC_MEM_LOAD         _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )
-+#define VC_MEM_IOC_MEM_PHYS_ADDR    _IOR(VC_MEM_IOC_MAGIC, 0, unsigned long)
-+#define VC_MEM_IOC_MEM_SIZE         _IOR(VC_MEM_IOC_MAGIC, 1, unsigned int)
-+#define VC_MEM_IOC_MEM_BASE         _IOR(VC_MEM_IOC_MAGIC, 2, unsigned int)
-+#define VC_MEM_IOC_MEM_LOAD         _IOR(VC_MEM_IOC_MAGIC, 3, unsigned int)
--#if defined( __KERNEL__ )
-+#ifdef __KERNEL__
- #define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
- extern unsigned long mm_vc_mem_phys_addr;
- extern unsigned int  mm_vc_mem_size;
--extern int vc_mem_get_current_size( void );
-+extern int vc_mem_get_current_size(void);
- #endif
- #ifdef CONFIG_COMPAT
diff --git a/target/linux/brcm2708/patches-4.19/950-0277-mfd-Add-rpi_sense_core-of-compatible-string.patch b/target/linux/brcm2708/patches-4.19/950-0277-mfd-Add-rpi_sense_core-of-compatible-string.patch
new file mode 100644 (file)
index 0000000..0647b05
--- /dev/null
@@ -0,0 +1,26 @@
+From 3e1371cc80a8153885cf87b06053ab2a2f1a1e66 Mon Sep 17 00:00:00 2001
+From: Serge Schneider <serge@raspberrypi.org>
+Date: Tue, 29 Jan 2019 12:05:49 +0000
+Subject: [PATCH] mfd: Add rpi_sense_core of compatible string
+
+---
+ drivers/mfd/rpisense-core.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/mfd/rpisense-core.c
++++ b/drivers/mfd/rpisense-core.c
+@@ -138,6 +138,14 @@ static const struct i2c_device_id rpisen
+ };
+ MODULE_DEVICE_TABLE(i2c, rpisense_i2c_id);
++#ifdef CONFIG_OF
++static const struct of_device_id rpisense_core_id[] = {
++      { .compatible = "rpi,rpi-sense" },
++      { },
++};
++MODULE_DEVICE_TABLE(of, rpisense_core_id);
++#endif
++
+ static struct i2c_driver rpisense_driver = {
+       .driver = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0278-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch b/target/linux/brcm2708/patches-4.19/950-0278-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch
deleted file mode 100644 (file)
index ee4fbbd..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 83a7175c91133a3e7a746693847b447bf6297094 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 15:09:28 +0000
-Subject: [PATCH] clk: clk-bcm2835: Use %zd when printing size_t
-
-The debug text for how many clocks have been registered
-uses "%d" with a size_t. Correct it to "%zd".
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -2271,7 +2271,7 @@ static int bcm2835_clk_probe(struct plat
-               return ret;
-       /* note that we have registered all the clocks */
--      dev_dbg(dev, "registered %d clocks\n", asize);
-+      dev_dbg(dev, "registered %zd clocks\n", asize);
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0278-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch b/target/linux/brcm2708/patches-4.19/950-0278-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch
new file mode 100644 (file)
index 0000000..cadf49e
--- /dev/null
@@ -0,0 +1,66 @@
+From 32e0a9e2549c43d9abc03427ba6f3b7b8c2e1407 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 28 Jan 2019 14:40:16 +0000
+Subject: [PATCH] gpu: vc4_firmware_kms: Fix up 64 bit compile
+ warnings.
+
+Resolve two build warnings with regard using incorrectly
+sized parameters in logging messages on 64 bit builds.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -160,14 +160,14 @@ static void vc4_primary_plane_atomic_upd
+               WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]);
+       }
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%08x/%d\n",
++      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
+                        plane->base.id, plane->name,
+                        state->crtc_w,
+                        state->crtc_h,
+                        bpp,
+                        state->crtc_x,
+                        state->crtc_y,
+-                       bo->paddr + fb->offsets[0],
++                       &fbinfo->base,
+                        fb->pitches[0]);
+       ret = rpi_firmware_transaction(vc4->firmware,
+@@ -197,6 +197,7 @@ static void vc4_cursor_plane_atomic_upda
+       struct drm_plane_state *state = plane->state;
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
++      dma_addr_t addr = bo->paddr + fb->offsets[0];
+       int ret;
+       u32 packet_state[] = {
+               state->crtc->state->active,
+@@ -206,13 +207,13 @@ static void vc4_cursor_plane_atomic_upda
+       };
+       WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%08x/%d)",
++      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
+                        plane->base.id, plane->name,
+                        state->crtc_w,
+                        state->crtc_h,
+                        state->crtc_x,
+                        state->crtc_y,
+-                       bo->paddr + fb->offsets[0],
++                       &addr,
+                        fb->pitches[0]);
+       /* add on the top/left offsets when overscan is active */
+@@ -238,7 +239,7 @@ static void vc4_cursor_plane_atomic_upda
+           fb != old_state->fb) {
+               u32 packet_info[] = { state->crtc_w, state->crtc_h,
+                                     0, /* unused */
+-                                    bo->paddr + fb->offsets[0],
++                                    addr,
+                                     0, 0, /* hotx, hoty */};
+               ret = rpi_firmware_property(vc4->firmware,
diff --git a/target/linux/brcm2708/patches-4.19/950-0279-input-rpi-ft5406-Clear-build-warning-on-64-bit-build.patch b/target/linux/brcm2708/patches-4.19/950-0279-input-rpi-ft5406-Clear-build-warning-on-64-bit-build.patch
new file mode 100644 (file)
index 0000000..d014697
--- /dev/null
@@ -0,0 +1,26 @@
+From 61ce13e4ab846aa035037217c5eec6aff229e539 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 28 Jan 2019 14:42:34 +0000
+Subject: [PATCH] input: rpi-ft5406: Clear build warning on 64 bit
+ builds.
+
+Resolve 64 bit build warning over using %x with a dma_addr_t.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/input/touchscreen/rpi-ft5406.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/input/touchscreen/rpi-ft5406.c
++++ b/drivers/input/touchscreen/rpi-ft5406.c
+@@ -218,8 +218,8 @@ static int ft5406_probe(struct platform_
+       if (!ts->ts_base) {
+               dev_warn(dev,
+-              "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n",
+-              err, touchbuf, ts->ts_base, ts->bus_addr);
++              "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%pad)\n",
++              err, touchbuf, ts->ts_base, &ts->bus_addr);
+               err = rpi_firmware_property(
+                               fw,
diff --git a/target/linux/brcm2708/patches-4.19/950-0279-mfd-Add-rpi_sense_core-of-compatible-string.patch b/target/linux/brcm2708/patches-4.19/950-0279-mfd-Add-rpi_sense_core-of-compatible-string.patch
deleted file mode 100644 (file)
index 0647b05..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 3e1371cc80a8153885cf87b06053ab2a2f1a1e66 Mon Sep 17 00:00:00 2001
-From: Serge Schneider <serge@raspberrypi.org>
-Date: Tue, 29 Jan 2019 12:05:49 +0000
-Subject: [PATCH] mfd: Add rpi_sense_core of compatible string
-
----
- drivers/mfd/rpisense-core.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/mfd/rpisense-core.c
-+++ b/drivers/mfd/rpisense-core.c
-@@ -138,6 +138,14 @@ static const struct i2c_device_id rpisen
- };
- MODULE_DEVICE_TABLE(i2c, rpisense_i2c_id);
-+#ifdef CONFIG_OF
-+static const struct of_device_id rpisense_core_id[] = {
-+      { .compatible = "rpi,rpi-sense" },
-+      { },
-+};
-+MODULE_DEVICE_TABLE(of, rpisense_core_id);
-+#endif
-+
- static struct i2c_driver rpisense_driver = {
-       .driver = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0280-dtoverlays-Correct-DT-handling-camera-GPIOs.patch b/target/linux/brcm2708/patches-4.19/950-0280-dtoverlays-Correct-DT-handling-camera-GPIOs.patch
new file mode 100644 (file)
index 0000000..9d64710
--- /dev/null
@@ -0,0 +1,85 @@
+From 5c0dfdba54fdaeb813d8535283aa8f75080e1055 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Sep 2018 10:47:38 +0100
+Subject: [PATCH] dtoverlays: Correct DT handling camera GPIOs
+
+The firmware has support for updating overrides with the correct
+GPIO settings for the camera GPIOs, but the wrong device tree
+setup ended up being merged.
+Correct the DT configuration so that the firmware does set it
+up correctly.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm270x.dtsi                |  7 +++++++
+ arch/arm/boot/dts/overlays/README             | 10 +---------
+ arch/arm/boot/dts/overlays/ov5647-overlay.dts | 14 +++++++++++---
+ 3 files changed, 19 insertions(+), 12 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -152,6 +152,13 @@
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
++
++      __overrides__ {
++              cam0-pwdn-ctrl;
++              cam0-pwdn;
++              cam0-led-ctrl;
++              cam0-led;
++      };
+ };
+ &vc4 {
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1366,15 +1366,7 @@ Info:   Omnivision OV5647 camera module.
+         Uses Unicam 1, which is the standard camera connector on most Pi
+         variants.
+ Load:   dtoverlay=ov5647,<param>=<val>
+-Params: cam0-pwdn               GPIO used to control the sensor powerdown line.
+-
+-        cam0-led                GPIO used to control the sensor led
+-                                Both these fields should be automatically filled
+-                                in by the firmware to reflect the default GPIO
+-                                configuration of the particular Pi variant in
+-                                use.
+-
+-        i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
++Params: i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
+                                 Useful on Compute Modules.
+         i2c_pins_28_29          Use pins 28&29 for the I2C instead of 44&45.
+--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
+@@ -14,7 +14,7 @@
+                       status = "okay";
+                       ov5647: ov5647@36 {
+-                              compatible = "ov5647";
++                              compatible = "ovti,ov5647";
+                               reg = <0x36>;
+                               status = "okay";
+@@ -82,10 +82,18 @@
+               };
+       };
++      fragment@6 {
++              target-path="/__overrides__";
++              __overlay__ {
++                      cam0-pwdn-ctrl = <&ov5647>,"pwdn-gpios:0";
++                      cam0-pwdn      = <&ov5647>,"pwdn-gpios:4";
++                      cam0-led-ctrl  = <&ov5647>,"pwdn-gpios:12";
++                      cam0-led       = <&ov5647>,"pwdn-gpios:16";
++              };
++      };
++
+       __overrides__ {
+               i2c_pins_0_1 = <0>,"-2-3+4";
+               i2c_pins_28_29 = <0>,"+2-3-4";
+-              cam0-pwdn = <&ov5647>,"pwdn-gpios:4";
+-              cam0-led = <&ov5647>,"pwdn-gpios:16";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0280-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch b/target/linux/brcm2708/patches-4.19/950-0280-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch
deleted file mode 100644 (file)
index cadf49e..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-From 32e0a9e2549c43d9abc03427ba6f3b7b8c2e1407 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 28 Jan 2019 14:40:16 +0000
-Subject: [PATCH] gpu: vc4_firmware_kms: Fix up 64 bit compile
- warnings.
-
-Resolve two build warnings with regard using incorrectly
-sized parameters in logging messages on 64 bit builds.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 11 ++++++-----
- 1 file changed, 6 insertions(+), 5 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -160,14 +160,14 @@ static void vc4_primary_plane_atomic_upd
-               WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]);
-       }
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%08x/%d\n",
-+      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
-                        plane->base.id, plane->name,
-                        state->crtc_w,
-                        state->crtc_h,
-                        bpp,
-                        state->crtc_x,
-                        state->crtc_y,
--                       bo->paddr + fb->offsets[0],
-+                       &fbinfo->base,
-                        fb->pitches[0]);
-       ret = rpi_firmware_transaction(vc4->firmware,
-@@ -197,6 +197,7 @@ static void vc4_cursor_plane_atomic_upda
-       struct drm_plane_state *state = plane->state;
-       struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
-+      dma_addr_t addr = bo->paddr + fb->offsets[0];
-       int ret;
-       u32 packet_state[] = {
-               state->crtc->state->active,
-@@ -206,13 +207,13 @@ static void vc4_cursor_plane_atomic_upda
-       };
-       WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%08x/%d)",
-+      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
-                        plane->base.id, plane->name,
-                        state->crtc_w,
-                        state->crtc_h,
-                        state->crtc_x,
-                        state->crtc_y,
--                       bo->paddr + fb->offsets[0],
-+                       &addr,
-                        fb->pitches[0]);
-       /* add on the top/left offsets when overscan is active */
-@@ -238,7 +239,7 @@ static void vc4_cursor_plane_atomic_upda
-           fb != old_state->fb) {
-               u32 packet_info[] = { state->crtc_w, state->crtc_h,
-                                     0, /* unused */
--                                    bo->paddr + fb->offsets[0],
-+                                    addr,
-                                     0, 0, /* hotx, hoty */};
-               ret = rpi_firmware_property(vc4->firmware,
diff --git a/target/linux/brcm2708/patches-4.19/950-0281-input-rpi-ft5406-Clear-build-warning-on-64-bit-build.patch b/target/linux/brcm2708/patches-4.19/950-0281-input-rpi-ft5406-Clear-build-warning-on-64-bit-build.patch
deleted file mode 100644 (file)
index d014697..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 61ce13e4ab846aa035037217c5eec6aff229e539 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 28 Jan 2019 14:42:34 +0000
-Subject: [PATCH] input: rpi-ft5406: Clear build warning on 64 bit
- builds.
-
-Resolve 64 bit build warning over using %x with a dma_addr_t.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/input/touchscreen/rpi-ft5406.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/input/touchscreen/rpi-ft5406.c
-+++ b/drivers/input/touchscreen/rpi-ft5406.c
-@@ -218,8 +218,8 @@ static int ft5406_probe(struct platform_
-       if (!ts->ts_base) {
-               dev_warn(dev,
--              "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n",
--              err, touchbuf, ts->ts_base, ts->bus_addr);
-+              "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%pad)\n",
-+              err, touchbuf, ts->ts_base, &ts->bus_addr);
-               err = rpi_firmware_property(
-                               fw,
diff --git a/target/linux/brcm2708/patches-4.19/950-0281-media-ov5647-Use-gpiod_set_value_cansleep.patch b/target/linux/brcm2708/patches-4.19/950-0281-media-ov5647-Use-gpiod_set_value_cansleep.patch
new file mode 100644 (file)
index 0000000..e88afb0
--- /dev/null
@@ -0,0 +1,54 @@
+From 3be30ee1b3aafd7c6cc45bcea77f25c9613732f4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Sep 2018 11:08:51 +0100
+Subject: [PATCH] media: ov5647: Use gpiod_set_value_cansleep
+
+All calls to the gpio library are in contexts that can sleep,
+therefore there is no issue with having those GPIOs controlled
+by controllers which require sleeping (eg I2C GPIO expanders).
+
+Switch to using gpiod_set_value_cansleep instead of gpiod_set_value
+to avoid triggering the warning in gpiolib should the GPIO
+controller need to sleep.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/media/i2c/ov5647.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/media/i2c/ov5647.c
++++ b/drivers/media/i2c/ov5647.c
+@@ -373,7 +373,7 @@ static int ov5647_sensor_power(struct v4
+               dev_dbg(&client->dev, "OV5647 power on\n");
+               if (ov5647->pwdn) {
+-                      gpiod_set_value(ov5647->pwdn, 0);
++                      gpiod_set_value_cansleep(ov5647->pwdn, 0);
+                       msleep(PWDN_ACTIVE_DELAY_MS);
+               }
+@@ -415,7 +415,7 @@ static int ov5647_sensor_power(struct v4
+               clk_disable_unprepare(ov5647->xclk);
+-              gpiod_set_value(ov5647->pwdn, 1);
++              gpiod_set_value_cansleep(ov5647->pwdn, 1);
+       }
+       /* Update the power count. */
+@@ -649,13 +649,13 @@ static int ov5647_probe(struct i2c_clien
+               goto mutex_remove;
+       if (sensor->pwdn) {
+-              gpiod_set_value(sensor->pwdn, 0);
++              gpiod_set_value_cansleep(sensor->pwdn, 0);
+               msleep(PWDN_ACTIVE_DELAY_MS);
+       }
+       ret = ov5647_detect(sd);
+-      gpiod_set_value(sensor->pwdn, 1);
++      gpiod_set_value_cansleep(sensor->pwdn, 1);
+       if (ret < 0)
+               goto error;
diff --git a/target/linux/brcm2708/patches-4.19/950-0282-dtoverlays-Correct-DT-handling-camera-GPIOs.patch b/target/linux/brcm2708/patches-4.19/950-0282-dtoverlays-Correct-DT-handling-camera-GPIOs.patch
deleted file mode 100644 (file)
index 9d64710..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-From 5c0dfdba54fdaeb813d8535283aa8f75080e1055 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Sep 2018 10:47:38 +0100
-Subject: [PATCH] dtoverlays: Correct DT handling camera GPIOs
-
-The firmware has support for updating overrides with the correct
-GPIO settings for the camera GPIOs, but the wrong device tree
-setup ended up being merged.
-Correct the DT configuration so that the firmware does set it
-up correctly.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/boot/dts/bcm270x.dtsi                |  7 +++++++
- arch/arm/boot/dts/overlays/README             | 10 +---------
- arch/arm/boot/dts/overlays/ov5647-overlay.dts | 14 +++++++++++---
- 3 files changed, 19 insertions(+), 12 deletions(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -152,6 +152,13 @@
-               regulator-max-microvolt = <3300000>;
-               regulator-always-on;
-       };
-+
-+      __overrides__ {
-+              cam0-pwdn-ctrl;
-+              cam0-pwdn;
-+              cam0-led-ctrl;
-+              cam0-led;
-+      };
- };
- &vc4 {
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1366,15 +1366,7 @@ Info:   Omnivision OV5647 camera module.
-         Uses Unicam 1, which is the standard camera connector on most Pi
-         variants.
- Load:   dtoverlay=ov5647,<param>=<val>
--Params: cam0-pwdn               GPIO used to control the sensor powerdown line.
--
--        cam0-led                GPIO used to control the sensor led
--                                Both these fields should be automatically filled
--                                in by the firmware to reflect the default GPIO
--                                configuration of the particular Pi variant in
--                                use.
--
--        i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
-+Params: i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
-                                 Useful on Compute Modules.
-         i2c_pins_28_29          Use pins 28&29 for the I2C instead of 44&45.
---- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-@@ -14,7 +14,7 @@
-                       status = "okay";
-                       ov5647: ov5647@36 {
--                              compatible = "ov5647";
-+                              compatible = "ovti,ov5647";
-                               reg = <0x36>;
-                               status = "okay";
-@@ -82,10 +82,18 @@
-               };
-       };
-+      fragment@6 {
-+              target-path="/__overrides__";
-+              __overlay__ {
-+                      cam0-pwdn-ctrl = <&ov5647>,"pwdn-gpios:0";
-+                      cam0-pwdn      = <&ov5647>,"pwdn-gpios:4";
-+                      cam0-led-ctrl  = <&ov5647>,"pwdn-gpios:12";
-+                      cam0-led       = <&ov5647>,"pwdn-gpios:16";
-+              };
-+      };
-+
-       __overrides__ {
-               i2c_pins_0_1 = <0>,"-2-3+4";
-               i2c_pins_28_29 = <0>,"+2-3-4";
--              cam0-pwdn = <&ov5647>,"pwdn-gpios:4";
--              cam0-led = <&ov5647>,"pwdn-gpios:16";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0282-media-bcm2835-unicam-Power-on-subdev-on-open-release.patch b/target/linux/brcm2708/patches-4.19/950-0282-media-bcm2835-unicam-Power-on-subdev-on-open-release.patch
new file mode 100644 (file)
index 0000000..0946b77
--- /dev/null
@@ -0,0 +1,121 @@
+From bf1805e0c8c4fc05e2a13b0a03b510ff4e523418 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 15:56:10 +0000
+Subject: [PATCH] media:bcm2835-unicam: Power on subdev on
+ open/release, not streaming
+
+The driver was powering on the source subdevice as part of STREAMON,
+and powering it off in STREAMOFF. This isn't so great if there is a
+significant amount of setup required for your device.
+
+Copy the approach taken in the Atmel ISC driver where s_power(1) is called
+on first file handle open, and s_power(0) is called on the last release.
+
+See https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=232437
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 68 +++++++++++++++----
+ 1 file changed, 54 insertions(+), 14 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1237,11 +1237,6 @@ static int unicam_start_streaming(struct
+               unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
+               goto err_pm_put;
+       }
+-      ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
+-      if (ret < 0 && ret != -ENOIOCTLCMD) {
+-              unicam_err(dev, "power on failed in subdev\n");
+-              goto err_clock_unprepare;
+-      }
+       dev->streaming = 1;
+       unicam_start_rx(dev, addr);
+@@ -1256,8 +1251,6 @@ static int unicam_start_streaming(struct
+ err_disable_unicam:
+       unicam_disable(dev);
+-      v4l2_subdev_call(dev->sensor, core, s_power, 0);
+-err_clock_unprepare:
+       clk_disable_unprepare(dev->clock);
+ err_pm_put:
+       unicam_runtime_put(dev);
+@@ -1306,11 +1299,6 @@ static void unicam_stop_streaming(struct
+       dev->next_frm = NULL;
+       spin_unlock_irqrestore(&dev->dma_queue_lock, flags);
+-      if (v4l2_subdev_has_op(dev->sensor, core, s_power)) {
+-              if (v4l2_subdev_call(dev->sensor, core, s_power, 0) < 0)
+-                      unicam_err(dev, "power off failed in subdev\n");
+-      }
+-
+       clk_disable_unprepare(dev->clock);
+       unicam_runtime_put(dev);
+ }
+@@ -1543,11 +1531,63 @@ static const struct vb2_ops unicam_video
+       .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_device *dev = video_drvdata(file);
++      int ret;
++
++      mutex_lock(&dev->lock);
++
++      ret = v4l2_fh_open(file);
++      if (ret) {
++              unicam_err(dev, "v4l2_fh_open failed\n");
++              goto unlock;
++      }
++
++      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);
++              goto unlock;
++      }
++
++unlock:
++      mutex_unlock(&dev->lock);
++      return ret;
++}
++
++static int unicam_release(struct file *file)
++{
++      struct unicam_device *dev = video_drvdata(file);
++      struct v4l2_subdev *sd = dev->sensor;
++      bool fh_singular;
++      int ret;
++
++      mutex_lock(&dev->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);
++
++      mutex_unlock(&dev->lock);
++
++      return ret;
++}
++
+ /* unicam capture driver file operations */
+ static const struct v4l2_file_operations unicam_fops = {
+       .owner          = THIS_MODULE,
+-      .open           = v4l2_fh_open,
+-      .release        = vb2_fop_release,
++      .open           = unicam_open,
++      .release        = unicam_release,
+       .read           = vb2_fop_read,
+       .poll           = vb2_fop_poll,
+       .unlocked_ioctl = video_ioctl2,
diff --git a/target/linux/brcm2708/patches-4.19/950-0283-audioinjector-octo-revert-to-dummy-supplies.patch b/target/linux/brcm2708/patches-4.19/950-0283-audioinjector-octo-revert-to-dummy-supplies.patch
new file mode 100644 (file)
index 0000000..760a7bf
--- /dev/null
@@ -0,0 +1,23 @@
+From 0e69aceab4e7615cf631a8c7bdb25093cbba240a Mon Sep 17 00:00:00 2001
+From: Matt Flax <flatmax@flatmax.org>
+Date: Tue, 29 Jan 2019 14:56:03 +1100
+Subject: [PATCH] audioinjector-octo: revert to dummy supplies
+
+The Audio Injector Octo has had a lot of reports of not coming up on power cycles. By reverting to dummy supplies, the card comes up reliably.
+---
+ arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
+@@ -25,10 +25,6 @@
+                               reg = <0x48>;
+                               clocks = <&cs42448_mclk>;
+                               clock-names = "mclk";
+-                              VA-supply = <&vdd_5v0_reg>;
+-                              VD-supply = <&vdd_3v3_reg>;
+-                              VLS-supply = <&vdd_3v3_reg>;
+-                              VLC-supply = <&vdd_3v3_reg>;
+                               status = "okay";
+                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0283-media-ov5647-Use-gpiod_set_value_cansleep.patch b/target/linux/brcm2708/patches-4.19/950-0283-media-ov5647-Use-gpiod_set_value_cansleep.patch
deleted file mode 100644 (file)
index e88afb0..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From 3be30ee1b3aafd7c6cc45bcea77f25c9613732f4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Sep 2018 11:08:51 +0100
-Subject: [PATCH] media: ov5647: Use gpiod_set_value_cansleep
-
-All calls to the gpio library are in contexts that can sleep,
-therefore there is no issue with having those GPIOs controlled
-by controllers which require sleeping (eg I2C GPIO expanders).
-
-Switch to using gpiod_set_value_cansleep instead of gpiod_set_value
-to avoid triggering the warning in gpiolib should the GPIO
-controller need to sleep.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/media/i2c/ov5647.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/media/i2c/ov5647.c
-+++ b/drivers/media/i2c/ov5647.c
-@@ -373,7 +373,7 @@ static int ov5647_sensor_power(struct v4
-               dev_dbg(&client->dev, "OV5647 power on\n");
-               if (ov5647->pwdn) {
--                      gpiod_set_value(ov5647->pwdn, 0);
-+                      gpiod_set_value_cansleep(ov5647->pwdn, 0);
-                       msleep(PWDN_ACTIVE_DELAY_MS);
-               }
-@@ -415,7 +415,7 @@ static int ov5647_sensor_power(struct v4
-               clk_disable_unprepare(ov5647->xclk);
--              gpiod_set_value(ov5647->pwdn, 1);
-+              gpiod_set_value_cansleep(ov5647->pwdn, 1);
-       }
-       /* Update the power count. */
-@@ -649,13 +649,13 @@ static int ov5647_probe(struct i2c_clien
-               goto mutex_remove;
-       if (sensor->pwdn) {
--              gpiod_set_value(sensor->pwdn, 0);
-+              gpiod_set_value_cansleep(sensor->pwdn, 0);
-               msleep(PWDN_ACTIVE_DELAY_MS);
-       }
-       ret = ov5647_detect(sd);
--      gpiod_set_value(sensor->pwdn, 1);
-+      gpiod_set_value_cansleep(sensor->pwdn, 1);
-       if (ret < 0)
-               goto error;
diff --git a/target/linux/brcm2708/patches-4.19/950-0284-media-bcm2835-unicam-Power-on-subdev-on-open-release.patch b/target/linux/brcm2708/patches-4.19/950-0284-media-bcm2835-unicam-Power-on-subdev-on-open-release.patch
deleted file mode 100644 (file)
index 0946b77..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-From bf1805e0c8c4fc05e2a13b0a03b510ff4e523418 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 15:56:10 +0000
-Subject: [PATCH] media:bcm2835-unicam: Power on subdev on
- open/release, not streaming
-
-The driver was powering on the source subdevice as part of STREAMON,
-and powering it off in STREAMOFF. This isn't so great if there is a
-significant amount of setup required for your device.
-
-Copy the approach taken in the Atmel ISC driver where s_power(1) is called
-on first file handle open, and s_power(0) is called on the last release.
-
-See https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=232437
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c   | 68 +++++++++++++++----
- 1 file changed, 54 insertions(+), 14 deletions(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -1237,11 +1237,6 @@ static int unicam_start_streaming(struct
-               unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
-               goto err_pm_put;
-       }
--      ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
--      if (ret < 0 && ret != -ENOIOCTLCMD) {
--              unicam_err(dev, "power on failed in subdev\n");
--              goto err_clock_unprepare;
--      }
-       dev->streaming = 1;
-       unicam_start_rx(dev, addr);
-@@ -1256,8 +1251,6 @@ static int unicam_start_streaming(struct
- err_disable_unicam:
-       unicam_disable(dev);
--      v4l2_subdev_call(dev->sensor, core, s_power, 0);
--err_clock_unprepare:
-       clk_disable_unprepare(dev->clock);
- err_pm_put:
-       unicam_runtime_put(dev);
-@@ -1306,11 +1299,6 @@ static void unicam_stop_streaming(struct
-       dev->next_frm = NULL;
-       spin_unlock_irqrestore(&dev->dma_queue_lock, flags);
--      if (v4l2_subdev_has_op(dev->sensor, core, s_power)) {
--              if (v4l2_subdev_call(dev->sensor, core, s_power, 0) < 0)
--                      unicam_err(dev, "power off failed in subdev\n");
--      }
--
-       clk_disable_unprepare(dev->clock);
-       unicam_runtime_put(dev);
- }
-@@ -1543,11 +1531,63 @@ static const struct vb2_ops unicam_video
-       .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_device *dev = video_drvdata(file);
-+      int ret;
-+
-+      mutex_lock(&dev->lock);
-+
-+      ret = v4l2_fh_open(file);
-+      if (ret) {
-+              unicam_err(dev, "v4l2_fh_open failed\n");
-+              goto unlock;
-+      }
-+
-+      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);
-+              goto unlock;
-+      }
-+
-+unlock:
-+      mutex_unlock(&dev->lock);
-+      return ret;
-+}
-+
-+static int unicam_release(struct file *file)
-+{
-+      struct unicam_device *dev = video_drvdata(file);
-+      struct v4l2_subdev *sd = dev->sensor;
-+      bool fh_singular;
-+      int ret;
-+
-+      mutex_lock(&dev->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);
-+
-+      mutex_unlock(&dev->lock);
-+
-+      return ret;
-+}
-+
- /* unicam capture driver file operations */
- static const struct v4l2_file_operations unicam_fops = {
-       .owner          = THIS_MODULE,
--      .open           = v4l2_fh_open,
--      .release        = vb2_fop_release,
-+      .open           = unicam_open,
-+      .release        = unicam_release,
-       .read           = vb2_fop_read,
-       .poll           = vb2_fop_poll,
-       .unlocked_ioctl = video_ioctl2,
diff --git a/target/linux/brcm2708/patches-4.19/950-0284-staging-bcm2835-camera-Correct-ctrl-min-max-step-def.patch b/target/linux/brcm2708/patches-4.19/950-0284-staging-bcm2835-camera-Correct-ctrl-min-max-step-def.patch
new file mode 100644 (file)
index 0000000..c1e5bb3
--- /dev/null
@@ -0,0 +1,58 @@
+From 8c420772ef0f15ebbc3f13ebcc340d34bbdfad71 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 16:20:38 +0000
+Subject: [PATCH] staging: bcm2835-camera: Correct ctrl
+ min/max/step/def to 64bit
+
+The V4L2 control API was expanded to take 64 bit values in commit
+0ba2aeb6dab (Apr 16 2014), but as this driver wasn't in the mainline
+kernel at that point this was overlooked.
+
+Update to use 64 bit values. This also fixes a couple of warnings
+in 64 bit builds.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/controls.c        | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -78,10 +78,10 @@ struct bm2835_mmal_v4l2_ctrl {
+       /* control minimum value or
+        * mask for MMAL_CONTROL_TYPE_STD_MENU
+        */
+-      s32 min;
+-      s32 max; /* maximum value of control */
+-      s32 def;  /* default value of control */
+-      s32 step; /* step size of the control */
++      s64 min;
++      s64 max; /* maximum value of control */
++      s64 def;  /* default value of control */
++      u64 step; /* step size of the control */
+       const s64 *imenu; /* integer menu array */
+       u32 mmal_id; /* mmal parameter id */
+       bm2835_mmal_v4l2_ctrl_cb *setter;
+@@ -1244,7 +1244,7 @@ int bm2835_mmal_init_controls(struct bm2
+               case MMAL_CONTROL_TYPE_STD_MENU:
+               {
+-                      int mask = ctrl->min;
++                      u64 mask = ctrl->min;
+                       if (ctrl->id == V4L2_CID_SCENE_MODE) {
+                               /* Special handling to work out the mask
+@@ -1254,11 +1254,11 @@ int bm2835_mmal_init_controls(struct bm2
+                                */
+                               int i;
+-                              mask = 1 << V4L2_SCENE_MODE_NONE;
++                              mask = BIT(V4L2_SCENE_MODE_NONE);
+                               for (i = 0;
+                                    i < ARRAY_SIZE(scene_configs);
+                                    i++) {
+-                                      mask |= 1 << scene_configs[i].v4l2_scene;
++                                      mask |= BIT(scene_configs[i].v4l2_scene);
+                               }
+                               mask = ~mask;
+                       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0285-audioinjector-octo-revert-to-dummy-supplies.patch b/target/linux/brcm2708/patches-4.19/950-0285-audioinjector-octo-revert-to-dummy-supplies.patch
deleted file mode 100644 (file)
index 760a7bf..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 0e69aceab4e7615cf631a8c7bdb25093cbba240a Mon Sep 17 00:00:00 2001
-From: Matt Flax <flatmax@flatmax.org>
-Date: Tue, 29 Jan 2019 14:56:03 +1100
-Subject: [PATCH] audioinjector-octo: revert to dummy supplies
-
-The Audio Injector Octo has had a lot of reports of not coming up on power cycles. By reverting to dummy supplies, the card comes up reliably.
----
- arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts | 4 ----
- 1 file changed, 4 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-@@ -25,10 +25,6 @@
-                               reg = <0x48>;
-                               clocks = <&cs42448_mclk>;
-                               clock-names = "mclk";
--                              VA-supply = <&vdd_5v0_reg>;
--                              VD-supply = <&vdd_3v3_reg>;
--                              VLS-supply = <&vdd_3v3_reg>;
--                              VLC-supply = <&vdd_3v3_reg>;
-                               status = "okay";
-                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0285-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch b/target/linux/brcm2708/patches-4.19/950-0285-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch
new file mode 100644 (file)
index 0000000..24a332f
--- /dev/null
@@ -0,0 +1,37 @@
+From 8920ce80058cfa3d18dc8bc7535119e9986dbad7 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 16:40:01 +0000
+Subject: [PATCH] staging: bcm2835-codec: variable vb2 may be used
+ uninitialised
+
+In op_buffer_cb, the failure path checked whether there was
+an associated vb2 buffer before the variable vb2 had been
+assigned.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c        | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -634,6 +634,9 @@ static void op_buffer_cb(struct vchiq_mm
+                __func__, status, mmal_buf, mmal_buf->length,
+                mmal_buf->mmal_flags, mmal_buf->pts);
++      buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
++      vb2 = &buf->m2m.vb;
++
+       if (status) {
+               /* error in transfer */
+               if (vb2) {
+@@ -658,9 +661,6 @@ static void op_buffer_cb(struct vchiq_mm
+               return;
+       }
+-      buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
+-      vb2 = &buf->m2m.vb;
+-
+       v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
+                __func__, mmal_buf->length, mmal_buf->mmal_flags,
+                vb2->vb2_buf.index);
diff --git a/target/linux/brcm2708/patches-4.19/950-0286-staging-bcm2835-camera-Correct-ctrl-min-max-step-def.patch b/target/linux/brcm2708/patches-4.19/950-0286-staging-bcm2835-camera-Correct-ctrl-min-max-step-def.patch
deleted file mode 100644 (file)
index c1e5bb3..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 8c420772ef0f15ebbc3f13ebcc340d34bbdfad71 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 16:20:38 +0000
-Subject: [PATCH] staging: bcm2835-camera: Correct ctrl
- min/max/step/def to 64bit
-
-The V4L2 control API was expanded to take 64 bit values in commit
-0ba2aeb6dab (Apr 16 2014), but as this driver wasn't in the mainline
-kernel at that point this was overlooked.
-
-Update to use 64 bit values. This also fixes a couple of warnings
-in 64 bit builds.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/controls.c        | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -78,10 +78,10 @@ struct bm2835_mmal_v4l2_ctrl {
-       /* control minimum value or
-        * mask for MMAL_CONTROL_TYPE_STD_MENU
-        */
--      s32 min;
--      s32 max; /* maximum value of control */
--      s32 def;  /* default value of control */
--      s32 step; /* step size of the control */
-+      s64 min;
-+      s64 max; /* maximum value of control */
-+      s64 def;  /* default value of control */
-+      u64 step; /* step size of the control */
-       const s64 *imenu; /* integer menu array */
-       u32 mmal_id; /* mmal parameter id */
-       bm2835_mmal_v4l2_ctrl_cb *setter;
-@@ -1244,7 +1244,7 @@ int bm2835_mmal_init_controls(struct bm2
-               case MMAL_CONTROL_TYPE_STD_MENU:
-               {
--                      int mask = ctrl->min;
-+                      u64 mask = ctrl->min;
-                       if (ctrl->id == V4L2_CID_SCENE_MODE) {
-                               /* Special handling to work out the mask
-@@ -1254,11 +1254,11 @@ int bm2835_mmal_init_controls(struct bm2
-                                */
-                               int i;
--                              mask = 1 << V4L2_SCENE_MODE_NONE;
-+                              mask = BIT(V4L2_SCENE_MODE_NONE);
-                               for (i = 0;
-                                    i < ARRAY_SIZE(scene_configs);
-                                    i++) {
--                                      mask |= 1 << scene_configs[i].v4l2_scene;
-+                                      mask |= BIT(scene_configs[i].v4l2_scene);
-                               }
-                               mask = ~mask;
-                       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0286-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch b/target/linux/brcm2708/patches-4.19/950-0286-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch
new file mode 100644 (file)
index 0000000..c8e3e22
--- /dev/null
@@ -0,0 +1,25 @@
+From 7e3cada9dae5d030256605a28df9537b26e776a8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 16:36:19 +0000
+Subject: [PATCH] staging: bcm2835-codec: Fix potentially uninitialised
+ vars
+
+src_m2m_buf and dst_m2m_buf were printed in log messages
+when there are code paths that don't initialise them.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../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
+@@ -743,7 +743,7 @@ static void device_run(void *priv)
+       struct bcm2835_codec_ctx *ctx = priv;
+       struct bcm2835_codec_dev *dev = ctx->dev;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+-      struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
++      struct m2m_mmal_buffer *src_m2m_buf = NULL, *dst_m2m_buf = NULL;
+       struct v4l2_m2m_buffer *m2m;
+       int ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0287-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch b/target/linux/brcm2708/patches-4.19/950-0287-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch
deleted file mode 100644 (file)
index 24a332f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 8920ce80058cfa3d18dc8bc7535119e9986dbad7 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 16:40:01 +0000
-Subject: [PATCH] staging: bcm2835-codec: variable vb2 may be used
- uninitialised
-
-In op_buffer_cb, the failure path checked whether there was
-an associated vb2 buffer before the variable vb2 had been
-assigned.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c        | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -634,6 +634,9 @@ static void op_buffer_cb(struct vchiq_mm
-                __func__, status, mmal_buf, mmal_buf->length,
-                mmal_buf->mmal_flags, mmal_buf->pts);
-+      buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
-+      vb2 = &buf->m2m.vb;
-+
-       if (status) {
-               /* error in transfer */
-               if (vb2) {
-@@ -658,9 +661,6 @@ static void op_buffer_cb(struct vchiq_mm
-               return;
-       }
--      buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
--      vb2 = &buf->m2m.vb;
--
-       v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
-                __func__, mmal_buf->length, mmal_buf->mmal_flags,
-                vb2->vb2_buf.index);
diff --git a/target/linux/brcm2708/patches-4.19/950-0287-video-bcm2708_fb-Add-compat_ioctl-support.patch b/target/linux/brcm2708/patches-4.19/950-0287-video-bcm2708_fb-Add-compat_ioctl-support.patch
new file mode 100644 (file)
index 0000000..eb53480
--- /dev/null
@@ -0,0 +1,154 @@
+From b5bd7b621f6ab2f29e9f18ec2a2720d702b9727c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 17:12:54 +0000
+Subject: [PATCH] video: bcm2708_fb: Add compat_ioctl support.
+
+When using a 64 bit kernel with 32 bit userspace we need
+compat ioctl handling for FBIODMACOPY as one of the
+parameters is a pointer.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 87 ++++++++++++++++++++++++--------
+ 1 file changed, 66 insertions(+), 21 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -482,9 +482,8 @@ static void dma_memcpy(struct bcm2708_fb
+ /* cache coherent but non-allocating in L1 and L2 */
+ #define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
+-static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
++static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
+ {
+-      struct fb_dmacopy ioparam;
+       size_t size = PAGE_SIZE;
+       u32 *buf = NULL;
+       dma_addr_t bus_addr;
+@@ -497,26 +496,16 @@ static long vc_mem_copy(struct bcm2708_f
+               goto out;
+       }
+-      /* Get the parameter data.
+-       */
+-      if (copy_from_user
+-          (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
+-              pr_err("[%s]: failed to copy-from-user\n",
+-                              __func__);
+-              rc = -EFAULT;
+-              goto out;
+-      }
+-
+-      if (fb->gpu.base == 0 || fb->gpu.length == 0) {
++      if (!fb->gpu.base || !fb->gpu.length) {
+               pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
+                       __func__, fb->gpu.base, fb->gpu.length);
+               return -EFAULT;
+       }
+-      if (INTALIAS_NORMAL(ioparam.src) < fb->gpu.base ||
+-              INTALIAS_NORMAL(ioparam.src) >= fb->gpu.base + fb->gpu.length) {
++      if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
++          INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
+               pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
+-                      INTALIAS_NORMAL(ioparam.src), fb->gpu.base,
++                      INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
+                       fb->gpu.base + fb->gpu.length);
+               return -EFAULT;
+       }
+@@ -530,11 +519,11 @@ static long vc_mem_copy(struct bcm2708_f
+               goto out;
+       }
+-      for (offset = 0; offset < ioparam.length; offset += size) {
+-              size_t remaining = ioparam.length - offset;
++      for (offset = 0; offset < ioparam->length; offset += size) {
++              size_t remaining = ioparam->length - offset;
+               size_t s = min(size, remaining);
+-              unsigned char *p = (unsigned char *)ioparam.src + offset;
+-              unsigned char *q = (unsigned char *)ioparam.dst + offset;
++              u8 *p = (u8 *)((uintptr_t)ioparam->src + offset);
++              u8 *q = (u8 *)ioparam->dst + offset;
+               dma_memcpy(fb, bus_addr,
+                          INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
+@@ -566,8 +555,19 @@ static int bcm2708_ioctl(struct fb_info
+                                           &dummy, sizeof(dummy));
+               break;
+       case FBIODMACOPY:
+-              ret = vc_mem_copy(fb, arg);
++      {
++              struct fb_dmacopy ioparam;
++              /* Get the parameter data.
++               */
++              if (copy_from_user
++                  (&ioparam, (void *)arg, sizeof(ioparam))) {
++                      pr_err("[%s]: failed to copy-from-user\n", __func__);
++                      ret = -EFAULT;
++                      break;
++              }
++              ret = vc_mem_copy(fb, &ioparam);
+               break;
++      }
+       default:
+               dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd);
+               return -ENOTTY;
+@@ -578,6 +578,48 @@ static int bcm2708_ioctl(struct fb_info
+       return ret;
+ }
++
++#ifdef CONFIG_COMPAT
++struct fb_dmacopy32 {
++      compat_uptr_t dst;
++      __u32 src;
++      __u32 length;
++};
++
++#define FBIODMACOPY32         _IOW('z', 0x22, struct fb_dmacopy32)
++
++static int bcm2708_compat_ioctl(struct fb_info *info, unsigned int cmd,
++                              unsigned long arg)
++{
++      struct bcm2708_fb *fb = to_bcm2708(info);
++      int ret;
++
++      switch (cmd) {
++      case FBIODMACOPY32:
++      {
++              struct fb_dmacopy32 param32;
++              struct fb_dmacopy param;
++              /* Get the parameter data.
++               */
++              if (copy_from_user(&param32, (void *)arg, sizeof(param32))) {
++                      pr_err("[%s]: failed to copy-from-user\n", __func__);
++                      ret = -EFAULT;
++                      break;
++              }
++              param.dst = compat_ptr(param32.dst);
++              param.src = param32.src;
++              param.length = param32.length;
++              ret = vc_mem_copy(fb, &param);
++              break;
++      }
++      default:
++              ret = bcm2708_ioctl(info, cmd, arg);
++              break;
++      }
++      return ret;
++}
++#endif
++
+ static void bcm2708_fb_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *rect)
+ {
+@@ -768,6 +810,9 @@ static struct fb_ops bcm2708_fb_ops = {
+       .fb_imageblit = bcm2708_fb_imageblit,
+       .fb_pan_display = bcm2708_fb_pan_display,
+       .fb_ioctl = bcm2708_ioctl,
++#ifdef CONFIG_COMPAT
++      .fb_compat_ioctl = bcm2708_compat_ioctl,
++#endif
+ };
+ static int bcm2708_fb_register(struct bcm2708_fb *fb)
diff --git a/target/linux/brcm2708/patches-4.19/950-0288-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch b/target/linux/brcm2708/patches-4.19/950-0288-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch
deleted file mode 100644 (file)
index c8e3e22..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 7e3cada9dae5d030256605a28df9537b26e776a8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 16:36:19 +0000
-Subject: [PATCH] staging: bcm2835-codec: Fix potentially uninitialised
- vars
-
-src_m2m_buf and dst_m2m_buf were printed in log messages
-when there are code paths that don't initialise them.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../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
-@@ -743,7 +743,7 @@ static void device_run(void *priv)
-       struct bcm2835_codec_ctx *ctx = priv;
-       struct bcm2835_codec_dev *dev = ctx->dev;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
--      struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
-+      struct m2m_mmal_buffer *src_m2m_buf = NULL, *dst_m2m_buf = NULL;
-       struct v4l2_m2m_buffer *m2m;
-       int ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0288-video-bcm2708_fb-Fix-warnings-on-64-bit-builds.patch b/target/linux/brcm2708/patches-4.19/950-0288-video-bcm2708_fb-Fix-warnings-on-64-bit-builds.patch
new file mode 100644 (file)
index 0000000..3c6dc09
--- /dev/null
@@ -0,0 +1,46 @@
+From ca128febc6abc040d747ddc0808fd203c135668e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 17:11:39 +0000
+Subject: [PATCH] video: bcm2708_fb: Fix warnings on 64 bit builds
+
+Fix up logging lines where the wrong format specifiers were
+being used.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -513,8 +513,8 @@ static long vc_mem_copy(struct bcm2708_f
+       buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr,
+                                GFP_ATOMIC);
+       if (!buf) {
+-              pr_err("[%s]: failed to dma_alloc_coherent(%d)\n",
+-                              __func__, size);
++              pr_err("[%s]: failed to dma_alloc_coherent(%zd)\n", __func__,
++                     size);
+               rc = -ENOMEM;
+               goto out;
+       }
+@@ -910,8 +910,7 @@ static int bcm2708_fb_probe(struct platf
+               goto free_fb;
+       }
+-      pr_info("BCM2708FB: allocated DMA memory %08x\n",
+-             fb->cb_handle);
++      pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
+       ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
+                                &fb->dma_chan_base, &fb->dma_irq);
+@@ -929,8 +928,7 @@ static int bcm2708_fb_probe(struct platf
+       }
+-      pr_info("BCM2708FB: allocated DMA channel %d @ %p\n",
+-             fb->dma_chan, fb->dma_chan_base);
++      pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
+       fb->dev = dev;
+       fb->fb.device = &dev->dev;
diff --git a/target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Add-compat_ioctl-support.patch b/target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Add-compat_ioctl-support.patch
deleted file mode 100644 (file)
index eb53480..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-From b5bd7b621f6ab2f29e9f18ec2a2720d702b9727c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 17:12:54 +0000
-Subject: [PATCH] video: bcm2708_fb: Add compat_ioctl support.
-
-When using a 64 bit kernel with 32 bit userspace we need
-compat ioctl handling for FBIODMACOPY as one of the
-parameters is a pointer.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 87 ++++++++++++++++++++++++--------
- 1 file changed, 66 insertions(+), 21 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -482,9 +482,8 @@ static void dma_memcpy(struct bcm2708_fb
- /* cache coherent but non-allocating in L1 and L2 */
- #define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
--static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
-+static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
- {
--      struct fb_dmacopy ioparam;
-       size_t size = PAGE_SIZE;
-       u32 *buf = NULL;
-       dma_addr_t bus_addr;
-@@ -497,26 +496,16 @@ static long vc_mem_copy(struct bcm2708_f
-               goto out;
-       }
--      /* Get the parameter data.
--       */
--      if (copy_from_user
--          (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
--              pr_err("[%s]: failed to copy-from-user\n",
--                              __func__);
--              rc = -EFAULT;
--              goto out;
--      }
--
--      if (fb->gpu.base == 0 || fb->gpu.length == 0) {
-+      if (!fb->gpu.base || !fb->gpu.length) {
-               pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
-                       __func__, fb->gpu.base, fb->gpu.length);
-               return -EFAULT;
-       }
--      if (INTALIAS_NORMAL(ioparam.src) < fb->gpu.base ||
--              INTALIAS_NORMAL(ioparam.src) >= fb->gpu.base + fb->gpu.length) {
-+      if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
-+          INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
-               pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
--                      INTALIAS_NORMAL(ioparam.src), fb->gpu.base,
-+                      INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
-                       fb->gpu.base + fb->gpu.length);
-               return -EFAULT;
-       }
-@@ -530,11 +519,11 @@ static long vc_mem_copy(struct bcm2708_f
-               goto out;
-       }
--      for (offset = 0; offset < ioparam.length; offset += size) {
--              size_t remaining = ioparam.length - offset;
-+      for (offset = 0; offset < ioparam->length; offset += size) {
-+              size_t remaining = ioparam->length - offset;
-               size_t s = min(size, remaining);
--              unsigned char *p = (unsigned char *)ioparam.src + offset;
--              unsigned char *q = (unsigned char *)ioparam.dst + offset;
-+              u8 *p = (u8 *)((uintptr_t)ioparam->src + offset);
-+              u8 *q = (u8 *)ioparam->dst + offset;
-               dma_memcpy(fb, bus_addr,
-                          INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
-@@ -566,8 +555,19 @@ static int bcm2708_ioctl(struct fb_info
-                                           &dummy, sizeof(dummy));
-               break;
-       case FBIODMACOPY:
--              ret = vc_mem_copy(fb, arg);
-+      {
-+              struct fb_dmacopy ioparam;
-+              /* Get the parameter data.
-+               */
-+              if (copy_from_user
-+                  (&ioparam, (void *)arg, sizeof(ioparam))) {
-+                      pr_err("[%s]: failed to copy-from-user\n", __func__);
-+                      ret = -EFAULT;
-+                      break;
-+              }
-+              ret = vc_mem_copy(fb, &ioparam);
-               break;
-+      }
-       default:
-               dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd);
-               return -ENOTTY;
-@@ -578,6 +578,48 @@ static int bcm2708_ioctl(struct fb_info
-       return ret;
- }
-+
-+#ifdef CONFIG_COMPAT
-+struct fb_dmacopy32 {
-+      compat_uptr_t dst;
-+      __u32 src;
-+      __u32 length;
-+};
-+
-+#define FBIODMACOPY32         _IOW('z', 0x22, struct fb_dmacopy32)
-+
-+static int bcm2708_compat_ioctl(struct fb_info *info, unsigned int cmd,
-+                              unsigned long arg)
-+{
-+      struct bcm2708_fb *fb = to_bcm2708(info);
-+      int ret;
-+
-+      switch (cmd) {
-+      case FBIODMACOPY32:
-+      {
-+              struct fb_dmacopy32 param32;
-+              struct fb_dmacopy param;
-+              /* Get the parameter data.
-+               */
-+              if (copy_from_user(&param32, (void *)arg, sizeof(param32))) {
-+                      pr_err("[%s]: failed to copy-from-user\n", __func__);
-+                      ret = -EFAULT;
-+                      break;
-+              }
-+              param.dst = compat_ptr(param32.dst);
-+              param.src = param32.src;
-+              param.length = param32.length;
-+              ret = vc_mem_copy(fb, &param);
-+              break;
-+      }
-+      default:
-+              ret = bcm2708_ioctl(info, cmd, arg);
-+              break;
-+      }
-+      return ret;
-+}
-+#endif
-+
- static void bcm2708_fb_fillrect(struct fb_info *info,
-                               const struct fb_fillrect *rect)
- {
-@@ -768,6 +810,9 @@ static struct fb_ops bcm2708_fb_ops = {
-       .fb_imageblit = bcm2708_fb_imageblit,
-       .fb_pan_display = bcm2708_fb_pan_display,
-       .fb_ioctl = bcm2708_ioctl,
-+#ifdef CONFIG_COMPAT
-+      .fb_compat_ioctl = bcm2708_compat_ioctl,
-+#endif
- };
- static int bcm2708_fb_register(struct bcm2708_fb *fb)
diff --git a/target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Clean-up-coding-style-issues.patch b/target/linux/brcm2708/patches-4.19/950-0289-video-bcm2708_fb-Clean-up-coding-style-issues.patch
new file mode 100644 (file)
index 0000000..43bb8ce
--- /dev/null
@@ -0,0 +1,275 @@
+From 47f7687efaf3873fe8c0e47653515e9ada1b86da Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 17:32:54 +0000
+Subject: [PATCH] video: bcm2708_fb: Clean up coding style issues
+
+Now checkpatch clean except for 2 long lines, missing
+SPDX header, and no DT documentation.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 96 ++++++++++++++------------------
+ 1 file changed, 42 insertions(+), 54 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -41,7 +41,7 @@
+ #define MODULE_NAME "bcm2708_fb"
+ #ifdef BCM2708_FB_DEBUG
+-#define print_debug(fmt, ...) pr_debug("%s:%s:%d: "fmt, \
++#define print_debug(fmt, ...) pr_debug("%s:%s:%d: " fmt, \
+                       MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
+ #else
+ #define print_debug(fmt, ...)
+@@ -57,7 +57,7 @@ static int fbheight = 480;   /* module par
+ static int fbdepth = 32;      /* module parameter */
+ static int fbswap;            /* module parameter */
+-static u32 dma_busy_wait_threshold = 1<<15;
++static u32 dma_busy_wait_threshold = 1 << 15;
+ module_param(dma_busy_wait_threshold, int, 0644);
+ MODULE_PARM_DESC(dma_busy_wait_threshold, "Busy-wait for DMA completion below this area");
+@@ -132,8 +132,8 @@ static int bcm2708_fb_debugfs_init(struc
+       fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
+       fb->stats.regset.base = &fb->stats;
+-      if (!debugfs_create_regset32(
+-              "stats", 0444, fb->debugfs_dir, &fb->stats.regset)) {
++      if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
++                                   &fb->stats.regset)) {
+               pr_warn("%s: could not create statistics registers\n",
+                       __func__);
+               goto fail;
+@@ -223,25 +223,22 @@ static int bcm2708_fb_check_var(struct f
+ {
+       /* info input, var output */
+       print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
+-              __func__,
+-              info,
+-              info->var.xres, info->var.yres, info->var.xres_virtual,
+-              info->var.yres_virtual, (int)info->screen_size,
+-              info->var.bits_per_pixel);
+-      print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var,
+-              var->xres, var->yres, var->xres_virtual, var->yres_virtual,
+-              var->bits_per_pixel);
++                  __func__, info, info->var.xres, info->var.yres,
++                  info->var.xres_virtual, info->var.yres_virtual,
++                  (int)info->screen_size, info->var.bits_per_pixel);
++      print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
++                  var->yres, var->xres_virtual, var->yres_virtual,
++                  var->bits_per_pixel);
+       if (!var->bits_per_pixel)
+               var->bits_per_pixel = 16;
+       if (bcm2708_fb_set_bitfields(var) != 0) {
+               pr_err("%s: invalid bits_per_pixel %d\n", __func__,
+-                   var->bits_per_pixel);
++                     var->bits_per_pixel);
+               return -EINVAL;
+       }
+-
+       if (var->xres_virtual < var->xres)
+               var->xres_virtual = var->xres;
+       /* use highest possible virtual resolution */
+@@ -249,7 +246,7 @@ static int bcm2708_fb_check_var(struct f
+               var->yres_virtual = 480;
+               pr_err("%s: virtual resolution set to maximum of %dx%d\n",
+-                   __func__, var->xres_virtual, var->yres_virtual);
++                     __func__, var->xres_virtual, var->yres_virtual);
+       }
+       if (var->yres_virtual < var->yres)
+               var->yres_virtual = var->yres;
+@@ -294,9 +291,9 @@ static int bcm2708_fb_set_par(struct fb_
+       int ret;
+       print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
+-              info->var.xres, info->var.yres, info->var.xres_virtual,
+-              info->var.yres_virtual, (int)info->screen_size,
+-              info->var.bits_per_pixel);
++                  info->var.xres, info->var.yres, info->var.xres_virtual,
++                  info->var.yres_virtual, (int)info->screen_size,
++                  info->var.bits_per_pixel);
+       ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
+       if (ret) {
+@@ -328,12 +325,10 @@ static int bcm2708_fb_set_par(struct fb_
+               return -ENOMEM;
+       }
+-      print_debug(
+-        "%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
+-        __func__,
+-        (void *)fb->fb.screen_base, (void *)fb->fb_bus_address,
+-        fbinfo.xres, fbinfo.yres, fbinfo.bpp,
+-        fbinfo.pitch, (int)fb->fb.screen_size);
++      print_debug("%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
++                  __func__, (void *)fb->fb.screen_base,
++                  (void *)fb->fb_bus_address, fbinfo.xres, fbinfo.yres,
++                  fbinfo.bpp, fbinfo.pitch, (int)fb->fb.screen_size);
+       return 0;
+ }
+@@ -345,7 +340,6 @@ static inline u32 convert_bitfield(int v
+       return (val >> (16 - bf->length) & mask) << bf->offset;
+ }
+-
+ static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
+                               unsigned int green, unsigned int blue,
+                               unsigned int transp, struct fb_info *info)
+@@ -379,11 +373,11 @@ static int bcm2708_fb_setcolreg(unsigned
+                       packet->offset = 0;
+                       packet->length = regno + 1;
+                       memcpy(packet->cmap, fb->gpu_cmap,
+-                              sizeof(packet->cmap));
++                             sizeof(packet->cmap));
+                       ret = rpi_firmware_property(fb->fw,
+-                                      RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
+-                                      packet,
+-                                      (2 + packet->length) * sizeof(u32));
++                                                  RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
++                                                  packet,
++                                                  (2 + packet->length) * sizeof(u32));
+                       if (ret || packet->offset)
+                               dev_err(info->device,
+                                       "Failed to set palette (%d,%u)\n",
+@@ -392,9 +386,9 @@ static int bcm2708_fb_setcolreg(unsigned
+               }
+       } else if (regno < 16) {
+               fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+-              convert_bitfield(blue, &fb->fb.var.blue) |
+-              convert_bitfield(green, &fb->fb.var.green) |
+-              convert_bitfield(red, &fb->fb.var.red);
++                                convert_bitfield(blue, &fb->fb.var.blue) |
++                                convert_bitfield(green, &fb->fb.var.green) |
++                                convert_bitfield(red, &fb->fb.var.red);
+       }
+       return regno > 255;
+ }
+@@ -437,8 +431,8 @@ static int bcm2708_fb_pan_display(struct
+       info->var.yoffset = var->yoffset;
+       result = bcm2708_fb_set_par(info);
+       if (result != 0)
+-              pr_err("%s(%d,%d) returns=%d\n", __func__,
+-                      var->xoffset, var->yoffset, result);
++              pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
++                     var->yoffset, result);
+       return result;
+ }
+@@ -468,9 +462,8 @@ static void dma_memcpy(struct bcm2708_fb
+               cb->info |= BCM2708_DMA_INT_EN;
+               bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+               while (bcm_dma_is_busy(dma_chan)) {
+-                      wait_event_interruptible(
+-                              fb->dma_waitq,
+-                              !bcm_dma_is_busy(dma_chan));
++                      wait_event_interruptible(fb->dma_waitq,
++                                               !bcm_dma_is_busy(dma_chan));
+               }
+               fb->stats.dma_irqs++;
+       }
+@@ -478,9 +471,9 @@ static void dma_memcpy(struct bcm2708_fb
+ }
+ /* address with no aliases */
+-#define INTALIAS_NORMAL(x) ((x)&~0xc0000000)
++#define INTALIAS_NORMAL(x) ((x) & ~0xc0000000)
+ /* cache coherent but non-allocating in L1 and L2 */
+-#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
++#define INTALIAS_L1L2_NONALLOCATING(x) (((x) & ~0xc0000000) | 0x80000000)
+ static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
+ {
+@@ -498,15 +491,15 @@ static long vc_mem_copy(struct bcm2708_f
+       if (!fb->gpu.base || !fb->gpu.length) {
+               pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
+-                      __func__, fb->gpu.base, fb->gpu.length);
++                     __func__, fb->gpu.base, fb->gpu.length);
+               return -EFAULT;
+       }
+       if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
+           INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
+               pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
+-                      INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
+-                      fb->gpu.base + fb->gpu.length);
++                     INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
++                     fb->gpu.base + fb->gpu.length);
+               return -EFAULT;
+       }
+@@ -528,8 +521,7 @@ static long vc_mem_copy(struct bcm2708_f
+               dma_memcpy(fb, bus_addr,
+                          INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
+               if (copy_to_user(q, buf, s) != 0) {
+-                      pr_err("[%s]: failed to copy-to-user\n",
+-                                      __func__);
++                      pr_err("[%s]: failed to copy-to-user\n", __func__);
+                       rc = -EFAULT;
+                       goto out;
+               }
+@@ -755,7 +747,6 @@ static void bcm2708_fb_copyarea(struct f
+       /* end of dma control blocks chain */
+       cb->next = 0;
+-
+       if (pixels < dma_busy_wait_threshold) {
+               bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+               bcm_dma_wait_idle(fb->dma_chan_base);
+@@ -765,9 +756,8 @@ static void bcm2708_fb_copyarea(struct f
+               cb->info |= BCM2708_DMA_INT_EN;
+               bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+               while (bcm_dma_is_busy(dma_chan)) {
+-                      wait_event_interruptible(
+-                              fb->dma_waitq,
+-                              !bcm_dma_is_busy(dma_chan));
++                      wait_event_interruptible(fb->dma_waitq,
++                                               !bcm_dma_is_busy(dma_chan));
+               }
+               fb->stats.dma_irqs++;
+       }
+@@ -863,7 +853,7 @@ static int bcm2708_fb_register(struct bc
+               return ret;
+       print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
+-              fbwidth, fbheight, fbdepth, fbswap);
++                  fbwidth, fbheight, fbdepth, fbswap);
+       ret = register_framebuffer(&fb->fb);
+       print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
+@@ -893,7 +883,7 @@ static int bcm2708_fb_probe(struct platf
+       if (!fw)
+               return -EPROBE_DEFER;
+-      fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
++      fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb) {
+               ret = -ENOMEM;
+               goto free_region;
+@@ -927,7 +917,6 @@ static int bcm2708_fb_probe(struct platf
+               goto free_dma_chan;
+       }
+-
+       pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
+       fb->dev = dev;
+@@ -936,9 +925,8 @@ static int bcm2708_fb_probe(struct platf
+       /* failure here isn't fatal, but we'll fail in vc_mem_copy if
+        * fb->gpu is not valid
+        */
+-      rpi_firmware_property(fb->fw,
+-                                  RPI_FIRMWARE_GET_VC_MEMORY,
+-                                  &fb->gpu, sizeof(fb->gpu));
++      rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
++                            sizeof(fb->gpu));
+       ret = bcm2708_fb_register(fb);
+       if (ret == 0) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0290-bcm2835-dma-Add-support-for-per-channel-flags.patch b/target/linux/brcm2708/patches-4.19/950-0290-bcm2835-dma-Add-support-for-per-channel-flags.patch
new file mode 100644 (file)
index 0000000..ff56439
--- /dev/null
@@ -0,0 +1,48 @@
+From 4ebec374d97c0bba1e41558071bfa062894b07a0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 20 Jul 2018 22:03:41 +0100
+Subject: [PATCH] bcm2835-dma: Add support for per-channel flags
+
+Add the ability to interpret the high bits of the dreq specifier as
+flags to be included in the DMA_CS register. The motivation for this
+change is the ability to set the DISDEBUG flag for SD card transfers
+to avoid corruption when using the VPU debugger.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/dma/bcm2835-dma.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -146,6 +146,10 @@ struct bcm2835_desc {
+ #define BCM2835_DMA_S_DREQ    BIT(10) /* enable SREQ for source */
+ #define BCM2835_DMA_S_IGNORE  BIT(11) /* ignore source reads - read 0 */
+ #define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12)
++#define BCM2835_DMA_CS_FLAGS(x) (x & (BCM2835_DMA_PRIORITY(15) | \
++                                    BCM2835_DMA_PANIC_PRIORITY(15) | \
++                                    BCM2835_DMA_WAIT_FOR_WRITES | \
++                                    BCM2835_DMA_DIS_DEBUG))
+ #define BCM2835_DMA_PER_MAP(x)        ((x & 31) << 16) /* REQ source */
+ #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 */
+@@ -461,7 +465,8 @@ static void bcm2835_dma_start_desc(struc
+       c->desc = d = to_bcm2835_dma_desc(&vd->tx);
+       writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
+-      writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
++      writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
++             c->chan_base + BCM2835_DMA_CS);
+ }
+ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
+@@ -488,7 +493,8 @@ static irqreturn_t bcm2835_dma_callback(
+        * if this IRQ handler is threaded.) If the channel is finished, it
+        * will remain idle despite the ACTIVE flag being set.
+        */
+-      writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
++      writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
++             BCM2835_DMA_CS_FLAGS(c->dreq),
+              c->chan_base + BCM2835_DMA_CS);
+       d = c->desc;
diff --git a/target/linux/brcm2708/patches-4.19/950-0290-video-bcm2708_fb-Fix-warnings-on-64-bit-builds.patch b/target/linux/brcm2708/patches-4.19/950-0290-video-bcm2708_fb-Fix-warnings-on-64-bit-builds.patch
deleted file mode 100644 (file)
index 3c6dc09..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From ca128febc6abc040d747ddc0808fd203c135668e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 17:11:39 +0000
-Subject: [PATCH] video: bcm2708_fb: Fix warnings on 64 bit builds
-
-Fix up logging lines where the wrong format specifiers were
-being used.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 10 ++++------
- 1 file changed, 4 insertions(+), 6 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -513,8 +513,8 @@ static long vc_mem_copy(struct bcm2708_f
-       buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr,
-                                GFP_ATOMIC);
-       if (!buf) {
--              pr_err("[%s]: failed to dma_alloc_coherent(%d)\n",
--                              __func__, size);
-+              pr_err("[%s]: failed to dma_alloc_coherent(%zd)\n", __func__,
-+                     size);
-               rc = -ENOMEM;
-               goto out;
-       }
-@@ -910,8 +910,7 @@ static int bcm2708_fb_probe(struct platf
-               goto free_fb;
-       }
--      pr_info("BCM2708FB: allocated DMA memory %08x\n",
--             fb->cb_handle);
-+      pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
-       ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
-                                &fb->dma_chan_base, &fb->dma_irq);
-@@ -929,8 +928,7 @@ static int bcm2708_fb_probe(struct platf
-       }
--      pr_info("BCM2708FB: allocated DMA channel %d @ %p\n",
--             fb->dma_chan, fb->dma_chan_base);
-+      pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
-       fb->dev = dev;
-       fb->fb.device = &dev->dev;
diff --git a/target/linux/brcm2708/patches-4.19/950-0291-bcm283x-Set-the-DISDEBUG-flag-for-SD-transfers.patch b/target/linux/brcm2708/patches-4.19/950-0291-bcm283x-Set-the-DISDEBUG-flag-for-SD-transfers.patch
new file mode 100644 (file)
index 0000000..ec0d0d8
--- /dev/null
@@ -0,0 +1,21 @@
+From 18a739ba2e76a5e2bb3a02d9083faeabdee93777 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 20 Jul 2018 22:08:05 +0100
+Subject: [PATCH] bcm283x: Set the DISDEBUG flag for SD transfers
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -400,7 +400,7 @@
+                       reg = <0x7e202000 0x100>;
+                       interrupts = <2 24>;
+                       clocks = <&clocks BCM2835_CLOCK_VPU>;
+-                      dmas = <&dma 13>;
++                      dmas = <&dma (13|(1<<29))>;
+                       dma-names = "rx-tx";
+                       status = "disabled";
+               };
diff --git a/target/linux/brcm2708/patches-4.19/950-0291-video-bcm2708_fb-Clean-up-coding-style-issues.patch b/target/linux/brcm2708/patches-4.19/950-0291-video-bcm2708_fb-Clean-up-coding-style-issues.patch
deleted file mode 100644 (file)
index 43bb8ce..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-From 47f7687efaf3873fe8c0e47653515e9ada1b86da Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 17:32:54 +0000
-Subject: [PATCH] video: bcm2708_fb: Clean up coding style issues
-
-Now checkpatch clean except for 2 long lines, missing
-SPDX header, and no DT documentation.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 96 ++++++++++++++------------------
- 1 file changed, 42 insertions(+), 54 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -41,7 +41,7 @@
- #define MODULE_NAME "bcm2708_fb"
- #ifdef BCM2708_FB_DEBUG
--#define print_debug(fmt, ...) pr_debug("%s:%s:%d: "fmt, \
-+#define print_debug(fmt, ...) pr_debug("%s:%s:%d: " fmt, \
-                       MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
- #else
- #define print_debug(fmt, ...)
-@@ -57,7 +57,7 @@ static int fbheight = 480;   /* module par
- static int fbdepth = 32;      /* module parameter */
- static int fbswap;            /* module parameter */
--static u32 dma_busy_wait_threshold = 1<<15;
-+static u32 dma_busy_wait_threshold = 1 << 15;
- module_param(dma_busy_wait_threshold, int, 0644);
- MODULE_PARM_DESC(dma_busy_wait_threshold, "Busy-wait for DMA completion below this area");
-@@ -132,8 +132,8 @@ static int bcm2708_fb_debugfs_init(struc
-       fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
-       fb->stats.regset.base = &fb->stats;
--      if (!debugfs_create_regset32(
--              "stats", 0444, fb->debugfs_dir, &fb->stats.regset)) {
-+      if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
-+                                   &fb->stats.regset)) {
-               pr_warn("%s: could not create statistics registers\n",
-                       __func__);
-               goto fail;
-@@ -223,25 +223,22 @@ static int bcm2708_fb_check_var(struct f
- {
-       /* info input, var output */
-       print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
--              __func__,
--              info,
--              info->var.xres, info->var.yres, info->var.xres_virtual,
--              info->var.yres_virtual, (int)info->screen_size,
--              info->var.bits_per_pixel);
--      print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var,
--              var->xres, var->yres, var->xres_virtual, var->yres_virtual,
--              var->bits_per_pixel);
-+                  __func__, info, info->var.xres, info->var.yres,
-+                  info->var.xres_virtual, info->var.yres_virtual,
-+                  (int)info->screen_size, info->var.bits_per_pixel);
-+      print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
-+                  var->yres, var->xres_virtual, var->yres_virtual,
-+                  var->bits_per_pixel);
-       if (!var->bits_per_pixel)
-               var->bits_per_pixel = 16;
-       if (bcm2708_fb_set_bitfields(var) != 0) {
-               pr_err("%s: invalid bits_per_pixel %d\n", __func__,
--                   var->bits_per_pixel);
-+                     var->bits_per_pixel);
-               return -EINVAL;
-       }
--
-       if (var->xres_virtual < var->xres)
-               var->xres_virtual = var->xres;
-       /* use highest possible virtual resolution */
-@@ -249,7 +246,7 @@ static int bcm2708_fb_check_var(struct f
-               var->yres_virtual = 480;
-               pr_err("%s: virtual resolution set to maximum of %dx%d\n",
--                   __func__, var->xres_virtual, var->yres_virtual);
-+                     __func__, var->xres_virtual, var->yres_virtual);
-       }
-       if (var->yres_virtual < var->yres)
-               var->yres_virtual = var->yres;
-@@ -294,9 +291,9 @@ static int bcm2708_fb_set_par(struct fb_
-       int ret;
-       print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
--              info->var.xres, info->var.yres, info->var.xres_virtual,
--              info->var.yres_virtual, (int)info->screen_size,
--              info->var.bits_per_pixel);
-+                  info->var.xres, info->var.yres, info->var.xres_virtual,
-+                  info->var.yres_virtual, (int)info->screen_size,
-+                  info->var.bits_per_pixel);
-       ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
-       if (ret) {
-@@ -328,12 +325,10 @@ static int bcm2708_fb_set_par(struct fb_
-               return -ENOMEM;
-       }
--      print_debug(
--        "%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
--        __func__,
--        (void *)fb->fb.screen_base, (void *)fb->fb_bus_address,
--        fbinfo.xres, fbinfo.yres, fbinfo.bpp,
--        fbinfo.pitch, (int)fb->fb.screen_size);
-+      print_debug("%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
-+                  __func__, (void *)fb->fb.screen_base,
-+                  (void *)fb->fb_bus_address, fbinfo.xres, fbinfo.yres,
-+                  fbinfo.bpp, fbinfo.pitch, (int)fb->fb.screen_size);
-       return 0;
- }
-@@ -345,7 +340,6 @@ static inline u32 convert_bitfield(int v
-       return (val >> (16 - bf->length) & mask) << bf->offset;
- }
--
- static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
-                               unsigned int green, unsigned int blue,
-                               unsigned int transp, struct fb_info *info)
-@@ -379,11 +373,11 @@ static int bcm2708_fb_setcolreg(unsigned
-                       packet->offset = 0;
-                       packet->length = regno + 1;
-                       memcpy(packet->cmap, fb->gpu_cmap,
--                              sizeof(packet->cmap));
-+                             sizeof(packet->cmap));
-                       ret = rpi_firmware_property(fb->fw,
--                                      RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
--                                      packet,
--                                      (2 + packet->length) * sizeof(u32));
-+                                                  RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
-+                                                  packet,
-+                                                  (2 + packet->length) * sizeof(u32));
-                       if (ret || packet->offset)
-                               dev_err(info->device,
-                                       "Failed to set palette (%d,%u)\n",
-@@ -392,9 +386,9 @@ static int bcm2708_fb_setcolreg(unsigned
-               }
-       } else if (regno < 16) {
-               fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
--              convert_bitfield(blue, &fb->fb.var.blue) |
--              convert_bitfield(green, &fb->fb.var.green) |
--              convert_bitfield(red, &fb->fb.var.red);
-+                                convert_bitfield(blue, &fb->fb.var.blue) |
-+                                convert_bitfield(green, &fb->fb.var.green) |
-+                                convert_bitfield(red, &fb->fb.var.red);
-       }
-       return regno > 255;
- }
-@@ -437,8 +431,8 @@ static int bcm2708_fb_pan_display(struct
-       info->var.yoffset = var->yoffset;
-       result = bcm2708_fb_set_par(info);
-       if (result != 0)
--              pr_err("%s(%d,%d) returns=%d\n", __func__,
--                      var->xoffset, var->yoffset, result);
-+              pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
-+                     var->yoffset, result);
-       return result;
- }
-@@ -468,9 +462,8 @@ static void dma_memcpy(struct bcm2708_fb
-               cb->info |= BCM2708_DMA_INT_EN;
-               bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-               while (bcm_dma_is_busy(dma_chan)) {
--                      wait_event_interruptible(
--                              fb->dma_waitq,
--                              !bcm_dma_is_busy(dma_chan));
-+                      wait_event_interruptible(fb->dma_waitq,
-+                                               !bcm_dma_is_busy(dma_chan));
-               }
-               fb->stats.dma_irqs++;
-       }
-@@ -478,9 +471,9 @@ static void dma_memcpy(struct bcm2708_fb
- }
- /* address with no aliases */
--#define INTALIAS_NORMAL(x) ((x)&~0xc0000000)
-+#define INTALIAS_NORMAL(x) ((x) & ~0xc0000000)
- /* cache coherent but non-allocating in L1 and L2 */
--#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
-+#define INTALIAS_L1L2_NONALLOCATING(x) (((x) & ~0xc0000000) | 0x80000000)
- static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
- {
-@@ -498,15 +491,15 @@ static long vc_mem_copy(struct bcm2708_f
-       if (!fb->gpu.base || !fb->gpu.length) {
-               pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
--                      __func__, fb->gpu.base, fb->gpu.length);
-+                     __func__, fb->gpu.base, fb->gpu.length);
-               return -EFAULT;
-       }
-       if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
-           INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
-               pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
--                      INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
--                      fb->gpu.base + fb->gpu.length);
-+                     INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
-+                     fb->gpu.base + fb->gpu.length);
-               return -EFAULT;
-       }
-@@ -528,8 +521,7 @@ static long vc_mem_copy(struct bcm2708_f
-               dma_memcpy(fb, bus_addr,
-                          INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
-               if (copy_to_user(q, buf, s) != 0) {
--                      pr_err("[%s]: failed to copy-to-user\n",
--                                      __func__);
-+                      pr_err("[%s]: failed to copy-to-user\n", __func__);
-                       rc = -EFAULT;
-                       goto out;
-               }
-@@ -755,7 +747,6 @@ static void bcm2708_fb_copyarea(struct f
-       /* end of dma control blocks chain */
-       cb->next = 0;
--
-       if (pixels < dma_busy_wait_threshold) {
-               bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-               bcm_dma_wait_idle(fb->dma_chan_base);
-@@ -765,9 +756,8 @@ static void bcm2708_fb_copyarea(struct f
-               cb->info |= BCM2708_DMA_INT_EN;
-               bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-               while (bcm_dma_is_busy(dma_chan)) {
--                      wait_event_interruptible(
--                              fb->dma_waitq,
--                              !bcm_dma_is_busy(dma_chan));
-+                      wait_event_interruptible(fb->dma_waitq,
-+                                               !bcm_dma_is_busy(dma_chan));
-               }
-               fb->stats.dma_irqs++;
-       }
-@@ -863,7 +853,7 @@ static int bcm2708_fb_register(struct bc
-               return ret;
-       print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
--              fbwidth, fbheight, fbdepth, fbswap);
-+                  fbwidth, fbheight, fbdepth, fbswap);
-       ret = register_framebuffer(&fb->fb);
-       print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
-@@ -893,7 +883,7 @@ static int bcm2708_fb_probe(struct platf
-       if (!fw)
-               return -EPROBE_DEFER;
--      fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
-+      fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-       if (!fb) {
-               ret = -ENOMEM;
-               goto free_region;
-@@ -927,7 +917,6 @@ static int bcm2708_fb_probe(struct platf
-               goto free_dma_chan;
-       }
--
-       pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
-       fb->dev = dev;
-@@ -936,9 +925,8 @@ static int bcm2708_fb_probe(struct platf
-       /* failure here isn't fatal, but we'll fail in vc_mem_copy if
-        * fb->gpu is not valid
-        */
--      rpi_firmware_property(fb->fw,
--                                  RPI_FIRMWARE_GET_VC_MEMORY,
--                                  &fb->gpu, sizeof(fb->gpu));
-+      rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
-+                            sizeof(fb->gpu));
-       ret = bcm2708_fb_register(fb);
-       if (ret == 0) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0292-ASoC-pcm512x-Implement-the-digital_mute-interface.patch b/target/linux/brcm2708/patches-4.19/950-0292-ASoC-pcm512x-Implement-the-digital_mute-interface.patch
new file mode 100644 (file)
index 0000000..e68cf7b
--- /dev/null
@@ -0,0 +1,196 @@
+From 4a15efde52bb79bf44e63b998cd84f896404d728 Mon Sep 17 00:00:00 2001
+From: Dimitris Papavasiliou <dpapavas@gmail.com>
+Date: Sat, 24 Nov 2018 22:05:42 +0200
+Subject: [PATCH] ASoC: pcm512x: Implement the digital_mute interface
+
+[ Upstream commit 3500f1c589e92e0b6b1f8d31b4084fbde08d49cb ]
+
+Clicks and pops of various volumes can be produced while the device is
+opened, closed, put into and taken out of standby, or reconfigured.
+Fix this, by implementing the digital_mute interface, so that the
+output is muted during such operations.
+
+Signed-off-by: Dimitris Papavasiliou <dpapavas@gmail.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/pcm512x.c | 121 ++++++++++++++++++++++++++++++++++++-
+ sound/soc/codecs/pcm512x.h |   2 +
+ 2 files changed, 121 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/pcm512x.c
++++ b/sound/soc/codecs/pcm512x.c
+@@ -53,6 +53,8 @@ struct pcm512x_priv {
+       unsigned long overclock_pll;
+       unsigned long overclock_dac;
+       unsigned long overclock_dsp;
++      int mute;
++      struct mutex mutex;
+       int lrclk_div;
+ };
+@@ -385,6 +387,61 @@ static const struct soc_enum pcm512x_ved
+       SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
+                       pcm512x_ramp_step_text);
++static int pcm512x_update_mute(struct pcm512x_priv *pcm512x)
++{
++      return regmap_update_bits(
++              pcm512x->regmap, PCM512x_MUTE, PCM512x_RQML | PCM512x_RQMR,
++              (!!(pcm512x->mute & 0x5) << PCM512x_RQML_SHIFT)
++              | (!!(pcm512x->mute & 0x3) << PCM512x_RQMR_SHIFT));
++}
++
++static int pcm512x_digital_playback_switch_get(struct snd_kcontrol *kcontrol,
++                                             struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
++      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++
++      mutex_lock(&pcm512x->mutex);
++      ucontrol->value.integer.value[0] = !(pcm512x->mute & 0x4);
++      ucontrol->value.integer.value[1] = !(pcm512x->mute & 0x2);
++      mutex_unlock(&pcm512x->mutex);
++
++      return 0;
++}
++
++static int pcm512x_digital_playback_switch_put(struct snd_kcontrol *kcontrol,
++                                             struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
++      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++      int ret, changed = 0;
++
++      mutex_lock(&pcm512x->mutex);
++
++      if ((pcm512x->mute & 0x4) == (ucontrol->value.integer.value[0] << 2)) {
++              pcm512x->mute ^= 0x4;
++              changed = 1;
++      }
++      if ((pcm512x->mute & 0x2) == (ucontrol->value.integer.value[1] << 1)) {
++              pcm512x->mute ^= 0x2;
++              changed = 1;
++      }
++
++      if (changed) {
++              ret = pcm512x_update_mute(pcm512x);
++              if (ret != 0) {
++                      dev_err(component->dev,
++                              "Failed to update digital mute: %d\n", ret);
++                      mutex_unlock(&pcm512x->mutex);
++                      return ret;
++              }
++      }
++
++      mutex_unlock(&pcm512x->mutex);
++
++      return changed;
++}
++
+ static const struct snd_kcontrol_new pcm512x_controls[] = {
+ SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
+                PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
+@@ -392,8 +449,15 @@ SOC_DOUBLE_TLV("Analogue Playback Volume
+              PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
+ SOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
+              PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
+-SOC_DOUBLE("Digital Playback Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
+-         PCM512x_RQMR_SHIFT, 1, 1),
++{
++      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++      .name = "Digital Playback Switch",
++      .index = 0,
++      .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++      .info = snd_ctl_boolean_stereo_info,
++      .get = pcm512x_digital_playback_switch_get,
++      .put = pcm512x_digital_playback_switch_put
++},
+ SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
+ SOC_ENUM("DSP Program", pcm512x_dsp_program),
+@@ -1323,6 +1387,56 @@ static int pcm512x_set_fmt(struct snd_so
+       return 0;
+ }
++static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
++{
++      struct snd_soc_component *component = dai->component;
++      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++      int ret;
++      unsigned int mute_det;
++
++      mutex_lock(&pcm512x->mutex);
++
++      if (mute) {
++              pcm512x->mute |= 0x1;
++              ret = regmap_update_bits(pcm512x->regmap, PCM512x_MUTE,
++                                       PCM512x_RQML | PCM512x_RQMR,
++                                       PCM512x_RQML | PCM512x_RQMR);
++              if (ret != 0) {
++                      dev_err(component->dev,
++                              "Failed to set digital mute: %d\n", ret);
++                      mutex_unlock(&pcm512x->mutex);
++                      return ret;
++              }
++
++              regmap_read_poll_timeout(pcm512x->regmap,
++                                       PCM512x_ANALOG_MUTE_DET,
++                                       mute_det, (mute_det & 0x3) == 0,
++                                       200, 10000);
++
++              mutex_unlock(&pcm512x->mutex);
++      } else {
++              pcm512x->mute &= ~0x1;
++              ret = pcm512x_update_mute(pcm512x);
++              if (ret != 0) {
++                      dev_err(component->dev,
++                              "Failed to update digital mute: %d\n", ret);
++                      mutex_unlock(&pcm512x->mutex);
++                      return ret;
++              }
++
++              regmap_read_poll_timeout(pcm512x->regmap,
++                                       PCM512x_ANALOG_MUTE_DET,
++                                       mute_det,
++                                       (mute_det & 0x3)
++                                       == ((~pcm512x->mute >> 1) & 0x3),
++                                       200, 10000);
++      }
++
++      mutex_unlock(&pcm512x->mutex);
++
++      return 0;
++}
++
+ static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
+       unsigned int tx_mask, unsigned int rx_mask,
+       int slots, int width)
+@@ -1348,6 +1462,7 @@ static const struct snd_soc_dai_ops pcm5
+       .startup = pcm512x_dai_startup,
+       .hw_params = pcm512x_hw_params,
+       .set_fmt = pcm512x_set_fmt,
++      .digital_mute = pcm512x_digital_mute,
+       .set_tdm_slot = pcm512x_set_tdm_slot,
+ };
+@@ -1414,6 +1529,8 @@ int pcm512x_probe(struct device *dev, st
+       if (!pcm512x)
+               return -ENOMEM;
++      mutex_init(&pcm512x->mutex);
++
+       dev_set_drvdata(dev, pcm512x);
+       pcm512x->regmap = regmap;
+--- a/sound/soc/codecs/pcm512x.h
++++ b/sound/soc/codecs/pcm512x.h
+@@ -112,7 +112,9 @@
+ #define PCM512x_RQST_SHIFT 4
+ /* Page 0, Register 3 - mute */
++#define PCM512x_RQMR (1 << 0)
+ #define PCM512x_RQMR_SHIFT 0
++#define PCM512x_RQML (1 << 4)
+ #define PCM512x_RQML_SHIFT 4
+ /* Page 0, Register 4 - PLL */
diff --git a/target/linux/brcm2708/patches-4.19/950-0292-bcm2835-dma-Add-support-for-per-channel-flags.patch b/target/linux/brcm2708/patches-4.19/950-0292-bcm2835-dma-Add-support-for-per-channel-flags.patch
deleted file mode 100644 (file)
index ff56439..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 4ebec374d97c0bba1e41558071bfa062894b07a0 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 20 Jul 2018 22:03:41 +0100
-Subject: [PATCH] bcm2835-dma: Add support for per-channel flags
-
-Add the ability to interpret the high bits of the dreq specifier as
-flags to be included in the DMA_CS register. The motivation for this
-change is the ability to set the DISDEBUG flag for SD card transfers
-to avoid corruption when using the VPU debugger.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/dma/bcm2835-dma.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -146,6 +146,10 @@ struct bcm2835_desc {
- #define BCM2835_DMA_S_DREQ    BIT(10) /* enable SREQ for source */
- #define BCM2835_DMA_S_IGNORE  BIT(11) /* ignore source reads - read 0 */
- #define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12)
-+#define BCM2835_DMA_CS_FLAGS(x) (x & (BCM2835_DMA_PRIORITY(15) | \
-+                                    BCM2835_DMA_PANIC_PRIORITY(15) | \
-+                                    BCM2835_DMA_WAIT_FOR_WRITES | \
-+                                    BCM2835_DMA_DIS_DEBUG))
- #define BCM2835_DMA_PER_MAP(x)        ((x & 31) << 16) /* REQ source */
- #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 */
-@@ -461,7 +465,8 @@ static void bcm2835_dma_start_desc(struc
-       c->desc = d = to_bcm2835_dma_desc(&vd->tx);
-       writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
--      writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
-+      writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
-+             c->chan_base + BCM2835_DMA_CS);
- }
- static irqreturn_t bcm2835_dma_callback(int irq, void *data)
-@@ -488,7 +493,8 @@ static irqreturn_t bcm2835_dma_callback(
-        * if this IRQ handler is threaded.) If the channel is finished, it
-        * will remain idle despite the ACTIVE flag being set.
-        */
--      writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
-+      writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
-+             BCM2835_DMA_CS_FLAGS(c->dreq),
-              c->chan_base + BCM2835_DMA_CS);
-       d = c->desc;
diff --git a/target/linux/brcm2708/patches-4.19/950-0293-ASoC-pcm512x-Fix-a-double-unlock-in-pcm512x_digital_.patch b/target/linux/brcm2708/patches-4.19/950-0293-ASoC-pcm512x-Fix-a-double-unlock-in-pcm512x_digital_.patch
new file mode 100644 (file)
index 0000000..f1a09c4
--- /dev/null
@@ -0,0 +1,62 @@
+From 26001d54a7f803258b161f25f457ce11523695d7 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Fri, 21 Dec 2018 12:11:20 +0300
+Subject: [PATCH] ASoC: pcm512x: Fix a double unlock in
+ pcm512x_digital_mute()
+
+[ Upstream commit 28b698b7342c7d5300cfe217cd77ff7d2a55e03d ]
+
+We accidentally call mutex_unlock(&pcm512x->mutex); twice in a row.
+
+I re-wrote the error handling to use "goto unlock;" instead of returning
+directly.  Hopefully, it makes the code a little simpler.
+
+Fixes: 3500f1c589e9 ("ASoC: pcm512x: Implement the digital_mute interface")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviwed-by: Dimitris Papavasiliou <dpapavas@gmail.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/pcm512x.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+--- a/sound/soc/codecs/pcm512x.c
++++ b/sound/soc/codecs/pcm512x.c
+@@ -1404,24 +1404,20 @@ static int pcm512x_digital_mute(struct s
+               if (ret != 0) {
+                       dev_err(component->dev,
+                               "Failed to set digital mute: %d\n", ret);
+-                      mutex_unlock(&pcm512x->mutex);
+-                      return ret;
++                      goto unlock;
+               }
+               regmap_read_poll_timeout(pcm512x->regmap,
+                                        PCM512x_ANALOG_MUTE_DET,
+                                        mute_det, (mute_det & 0x3) == 0,
+                                        200, 10000);
+-
+-              mutex_unlock(&pcm512x->mutex);
+       } else {
+               pcm512x->mute &= ~0x1;
+               ret = pcm512x_update_mute(pcm512x);
+               if (ret != 0) {
+                       dev_err(component->dev,
+                               "Failed to update digital mute: %d\n", ret);
+-                      mutex_unlock(&pcm512x->mutex);
+-                      return ret;
++                      goto unlock;
+               }
+               regmap_read_poll_timeout(pcm512x->regmap,
+@@ -1432,9 +1428,10 @@ static int pcm512x_digital_mute(struct s
+                                        200, 10000);
+       }
++unlock:
+       mutex_unlock(&pcm512x->mutex);
+-      return 0;
++      return ret;
+ }
+ static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
diff --git a/target/linux/brcm2708/patches-4.19/950-0293-bcm283x-Set-the-DISDEBUG-flag-for-SD-transfers.patch b/target/linux/brcm2708/patches-4.19/950-0293-bcm283x-Set-the-DISDEBUG-flag-for-SD-transfers.patch
deleted file mode 100644 (file)
index ec0d0d8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-From 18a739ba2e76a5e2bb3a02d9083faeabdee93777 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 20 Jul 2018 22:08:05 +0100
-Subject: [PATCH] bcm283x: Set the DISDEBUG flag for SD transfers
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm283x.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -400,7 +400,7 @@
-                       reg = <0x7e202000 0x100>;
-                       interrupts = <2 24>;
-                       clocks = <&clocks BCM2835_CLOCK_VPU>;
--                      dmas = <&dma 13>;
-+                      dmas = <&dma (13|(1<<29))>;
-                       dma-names = "rx-tx";
-                       status = "disabled";
-               };
diff --git a/target/linux/brcm2708/patches-4.19/950-0294-ASoC-pcm512x-Implement-the-digital_mute-interface.patch b/target/linux/brcm2708/patches-4.19/950-0294-ASoC-pcm512x-Implement-the-digital_mute-interface.patch
deleted file mode 100644 (file)
index e68cf7b..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-From 4a15efde52bb79bf44e63b998cd84f896404d728 Mon Sep 17 00:00:00 2001
-From: Dimitris Papavasiliou <dpapavas@gmail.com>
-Date: Sat, 24 Nov 2018 22:05:42 +0200
-Subject: [PATCH] ASoC: pcm512x: Implement the digital_mute interface
-
-[ Upstream commit 3500f1c589e92e0b6b1f8d31b4084fbde08d49cb ]
-
-Clicks and pops of various volumes can be produced while the device is
-opened, closed, put into and taken out of standby, or reconfigured.
-Fix this, by implementing the digital_mute interface, so that the
-output is muted during such operations.
-
-Signed-off-by: Dimitris Papavasiliou <dpapavas@gmail.com>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/pcm512x.c | 121 ++++++++++++++++++++++++++++++++++++-
- sound/soc/codecs/pcm512x.h |   2 +
- 2 files changed, 121 insertions(+), 2 deletions(-)
-
---- a/sound/soc/codecs/pcm512x.c
-+++ b/sound/soc/codecs/pcm512x.c
-@@ -53,6 +53,8 @@ struct pcm512x_priv {
-       unsigned long overclock_pll;
-       unsigned long overclock_dac;
-       unsigned long overclock_dsp;
-+      int mute;
-+      struct mutex mutex;
-       int lrclk_div;
- };
-@@ -385,6 +387,61 @@ static const struct soc_enum pcm512x_ved
-       SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
-                       pcm512x_ramp_step_text);
-+static int pcm512x_update_mute(struct pcm512x_priv *pcm512x)
-+{
-+      return regmap_update_bits(
-+              pcm512x->regmap, PCM512x_MUTE, PCM512x_RQML | PCM512x_RQMR,
-+              (!!(pcm512x->mute & 0x5) << PCM512x_RQML_SHIFT)
-+              | (!!(pcm512x->mute & 0x3) << PCM512x_RQMR_SHIFT));
-+}
-+
-+static int pcm512x_digital_playback_switch_get(struct snd_kcontrol *kcontrol,
-+                                             struct snd_ctl_elem_value *ucontrol)
-+{
-+      struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
-+      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+
-+      mutex_lock(&pcm512x->mutex);
-+      ucontrol->value.integer.value[0] = !(pcm512x->mute & 0x4);
-+      ucontrol->value.integer.value[1] = !(pcm512x->mute & 0x2);
-+      mutex_unlock(&pcm512x->mutex);
-+
-+      return 0;
-+}
-+
-+static int pcm512x_digital_playback_switch_put(struct snd_kcontrol *kcontrol,
-+                                             struct snd_ctl_elem_value *ucontrol)
-+{
-+      struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
-+      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+      int ret, changed = 0;
-+
-+      mutex_lock(&pcm512x->mutex);
-+
-+      if ((pcm512x->mute & 0x4) == (ucontrol->value.integer.value[0] << 2)) {
-+              pcm512x->mute ^= 0x4;
-+              changed = 1;
-+      }
-+      if ((pcm512x->mute & 0x2) == (ucontrol->value.integer.value[1] << 1)) {
-+              pcm512x->mute ^= 0x2;
-+              changed = 1;
-+      }
-+
-+      if (changed) {
-+              ret = pcm512x_update_mute(pcm512x);
-+              if (ret != 0) {
-+                      dev_err(component->dev,
-+                              "Failed to update digital mute: %d\n", ret);
-+                      mutex_unlock(&pcm512x->mutex);
-+                      return ret;
-+              }
-+      }
-+
-+      mutex_unlock(&pcm512x->mutex);
-+
-+      return changed;
-+}
-+
- static const struct snd_kcontrol_new pcm512x_controls[] = {
- SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
-                PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
-@@ -392,8 +449,15 @@ SOC_DOUBLE_TLV("Analogue Playback Volume
-              PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
- SOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
-              PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
--SOC_DOUBLE("Digital Playback Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
--         PCM512x_RQMR_SHIFT, 1, 1),
-+{
-+      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+      .name = "Digital Playback Switch",
-+      .index = 0,
-+      .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+      .info = snd_ctl_boolean_stereo_info,
-+      .get = pcm512x_digital_playback_switch_get,
-+      .put = pcm512x_digital_playback_switch_put
-+},
- SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
- SOC_ENUM("DSP Program", pcm512x_dsp_program),
-@@ -1323,6 +1387,56 @@ static int pcm512x_set_fmt(struct snd_so
-       return 0;
- }
-+static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
-+{
-+      struct snd_soc_component *component = dai->component;
-+      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+      int ret;
-+      unsigned int mute_det;
-+
-+      mutex_lock(&pcm512x->mutex);
-+
-+      if (mute) {
-+              pcm512x->mute |= 0x1;
-+              ret = regmap_update_bits(pcm512x->regmap, PCM512x_MUTE,
-+                                       PCM512x_RQML | PCM512x_RQMR,
-+                                       PCM512x_RQML | PCM512x_RQMR);
-+              if (ret != 0) {
-+                      dev_err(component->dev,
-+                              "Failed to set digital mute: %d\n", ret);
-+                      mutex_unlock(&pcm512x->mutex);
-+                      return ret;
-+              }
-+
-+              regmap_read_poll_timeout(pcm512x->regmap,
-+                                       PCM512x_ANALOG_MUTE_DET,
-+                                       mute_det, (mute_det & 0x3) == 0,
-+                                       200, 10000);
-+
-+              mutex_unlock(&pcm512x->mutex);
-+      } else {
-+              pcm512x->mute &= ~0x1;
-+              ret = pcm512x_update_mute(pcm512x);
-+              if (ret != 0) {
-+                      dev_err(component->dev,
-+                              "Failed to update digital mute: %d\n", ret);
-+                      mutex_unlock(&pcm512x->mutex);
-+                      return ret;
-+              }
-+
-+              regmap_read_poll_timeout(pcm512x->regmap,
-+                                       PCM512x_ANALOG_MUTE_DET,
-+                                       mute_det,
-+                                       (mute_det & 0x3)
-+                                       == ((~pcm512x->mute >> 1) & 0x3),
-+                                       200, 10000);
-+      }
-+
-+      mutex_unlock(&pcm512x->mutex);
-+
-+      return 0;
-+}
-+
- static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
-       unsigned int tx_mask, unsigned int rx_mask,
-       int slots, int width)
-@@ -1348,6 +1462,7 @@ static const struct snd_soc_dai_ops pcm5
-       .startup = pcm512x_dai_startup,
-       .hw_params = pcm512x_hw_params,
-       .set_fmt = pcm512x_set_fmt,
-+      .digital_mute = pcm512x_digital_mute,
-       .set_tdm_slot = pcm512x_set_tdm_slot,
- };
-@@ -1414,6 +1529,8 @@ int pcm512x_probe(struct device *dev, st
-       if (!pcm512x)
-               return -ENOMEM;
-+      mutex_init(&pcm512x->mutex);
-+
-       dev_set_drvdata(dev, pcm512x);
-       pcm512x->regmap = regmap;
---- a/sound/soc/codecs/pcm512x.h
-+++ b/sound/soc/codecs/pcm512x.h
-@@ -112,7 +112,9 @@
- #define PCM512x_RQST_SHIFT 4
- /* Page 0, Register 3 - mute */
-+#define PCM512x_RQMR (1 << 0)
- #define PCM512x_RQMR_SHIFT 0
-+#define PCM512x_RQML (1 << 4)
- #define PCM512x_RQML_SHIFT 4
- /* Page 0, Register 4 - PLL */
diff --git a/target/linux/brcm2708/patches-4.19/950-0294-usb-dwc_otg-Clean-up-build-warnings-on-64bit-kernels.patch b/target/linux/brcm2708/patches-4.19/950-0294-usb-dwc_otg-Clean-up-build-warnings-on-64bit-kernels.patch
new file mode 100644 (file)
index 0000000..cc99a11
--- /dev/null
@@ -0,0 +1,110 @@
+From d2536830d8f1ef06afdc84c5ac6e1a70b3a2bc40 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 16:03:31 +0000
+Subject: [PATCH] usb: dwc_otg: Clean up build warnings on 64bit
+ kernels
+
+No functional changes. Almost all are changes to logging lines.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c    |  3 +--
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c   |  2 +-
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c       | 19 ++++++++++++++-----
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 ++++------
+ 4 files changed, 20 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+@@ -837,8 +837,7 @@ static int dwc_otg_driver_probe(
+               retval = -ENOMEM;
+               goto fail;
+       }
+-      dev_info(&_dev->dev, "base=0x%08x\n",
+-                (unsigned)dwc_otg_device->os_dep.base);
++      dev_info(&_dev->dev, "base=%p\n", dwc_otg_device->os_dep.base);
+ #endif
+       /*
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -301,7 +301,7 @@ static int notrace fiq_iso_out_advance(s
+               last = 1;
+       /* New DMA address - address of bounce buffer referred to in index */
+-      hcdma.d32 = (uint32_t) &blob->channel[n].index[i].buf[0];
++      hcdma.d32 = (dma_addr_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
+@@ -1041,8 +1041,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
+                * moderately readable array casts.
+                */
+               hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base);
+-              DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d",
+-                              (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base,
++              DWC_WARN("FIQ DMA bounce buffers: virt = %px dma = %pad len=%zu",
++                              hcd->fiq_dmab, &hcd->fiq_state->dma_base,
+                               sizeof(struct fiq_dma_channel) * num_channels);
+               DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024);
+@@ -1522,9 +1522,12 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
+               /*
+                * Set dma_regs to bounce buffer. FIQ will update the
+                * state depending on transaction progress.
++               * 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 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
++              st->hcdma_copy.d32 = (dma_addr_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.
+                */
+@@ -1571,9 +1574,15 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
+                               st->nrpackets = i;
+                       }
+                       ptr = qtd->urb->buf + frame_desc->offset;
+-                      /* Point the HC at the DMA address of the bounce buffers */
++                      /*
++                       * Point the HC at the DMA address of the bounce buffers
++                       *
++                       * 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 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
++                      st->hcdma_copy.d32 = (dma_addr_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_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -454,11 +454,9 @@ static void hcd_init_fiq(void *cookie)
+               DWC_ERROR("Can't claim FIQ");
+               BUG();
+       }
+-      DWC_WARN("FIQ on core %d at 0x%08x",
+-                              smp_processor_id(),
+-                              (fiq_fsm_enable ? (int)&dwc_otg_fiq_fsm : (int)&dwc_otg_fiq_nop));
+-      DWC_WARN("FIQ ASM at 0x%08x length %d", (int)&_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
+-              set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
++      DWC_WARN("FIQ on core %d", smp_processor_id());
++      DWC_WARN("FIQ ASM at %px length %d", &_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
++      set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
+       memset(&regs,0,sizeof(regs));
+       regs.ARM_r8 = (long) dwc_otg_hcd->fiq_state;
+@@ -483,7 +481,7 @@ static void hcd_init_fiq(void *cookie)
+       dwc_otg_hcd->fiq_state->mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;
+       dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
+       dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
+-      DWC_WARN("MPHI regs_base at 0x%08x", (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
++      DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
+       //Enable mphi peripheral
+       writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
+ #ifdef DEBUG
diff --git a/target/linux/brcm2708/patches-4.19/950-0295-ASoC-pcm512x-Fix-a-double-unlock-in-pcm512x_digital_.patch b/target/linux/brcm2708/patches-4.19/950-0295-ASoC-pcm512x-Fix-a-double-unlock-in-pcm512x_digital_.patch
deleted file mode 100644 (file)
index f1a09c4..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-From 26001d54a7f803258b161f25f457ce11523695d7 Mon Sep 17 00:00:00 2001
-From: Dan Carpenter <dan.carpenter@oracle.com>
-Date: Fri, 21 Dec 2018 12:11:20 +0300
-Subject: [PATCH] ASoC: pcm512x: Fix a double unlock in
- pcm512x_digital_mute()
-
-[ Upstream commit 28b698b7342c7d5300cfe217cd77ff7d2a55e03d ]
-
-We accidentally call mutex_unlock(&pcm512x->mutex); twice in a row.
-
-I re-wrote the error handling to use "goto unlock;" instead of returning
-directly.  Hopefully, it makes the code a little simpler.
-
-Fixes: 3500f1c589e9 ("ASoC: pcm512x: Implement the digital_mute interface")
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-Reviwed-by: Dimitris Papavasiliou <dpapavas@gmail.com>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/pcm512x.c | 11 ++++-------
- 1 file changed, 4 insertions(+), 7 deletions(-)
-
---- a/sound/soc/codecs/pcm512x.c
-+++ b/sound/soc/codecs/pcm512x.c
-@@ -1404,24 +1404,20 @@ static int pcm512x_digital_mute(struct s
-               if (ret != 0) {
-                       dev_err(component->dev,
-                               "Failed to set digital mute: %d\n", ret);
--                      mutex_unlock(&pcm512x->mutex);
--                      return ret;
-+                      goto unlock;
-               }
-               regmap_read_poll_timeout(pcm512x->regmap,
-                                        PCM512x_ANALOG_MUTE_DET,
-                                        mute_det, (mute_det & 0x3) == 0,
-                                        200, 10000);
--
--              mutex_unlock(&pcm512x->mutex);
-       } else {
-               pcm512x->mute &= ~0x1;
-               ret = pcm512x_update_mute(pcm512x);
-               if (ret != 0) {
-                       dev_err(component->dev,
-                               "Failed to update digital mute: %d\n", ret);
--                      mutex_unlock(&pcm512x->mutex);
--                      return ret;
-+                      goto unlock;
-               }
-               regmap_read_poll_timeout(pcm512x->regmap,
-@@ -1432,9 +1428,10 @@ static int pcm512x_digital_mute(struct s
-                                        200, 10000);
-       }
-+unlock:
-       mutex_unlock(&pcm512x->mutex);
--      return 0;
-+      return ret;
- }
- static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
diff --git a/target/linux/brcm2708/patches-4.19/950-0295-usb-dwc_otg-Use-dma-allocation-for-mphi-dummy_send-b.patch b/target/linux/brcm2708/patches-4.19/950-0295-usb-dwc_otg-Use-dma-allocation-for-mphi-dummy_send-b.patch
new file mode 100644 (file)
index 0000000..edc9336
--- /dev/null
@@ -0,0 +1,74 @@
+From f0d93c5098283f88ea1de3af152a190177da8f36 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 30 Jan 2019 17:47:51 +0000
+Subject: [PATCH] usb: dwc_otg: Use dma allocation for mphi dummy_send
+ buffer
+
+The FIQ driver used a kzalloc'ed buffer for dummy_send,
+passing a kernel virtual address to the hardware block.
+The buffer is only ever used for a dummy read, so it
+should be harmless, but there is the chance that it will
+cause exceptions.
+
+Use a dma allocation so that we have a genuine bus address,
+and read from that.
+Free the allocation when done for good measure.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 4 ++--
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 1 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c     | 5 ++++-
+ 3 files changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -1347,7 +1347,7 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
+       /* We got an interrupt, didn't handle it. */
+       if (kick_irq) {
+               state->mphi_int_count++;
+-              FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
++              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+               FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+       }
+@@ -1408,7 +1408,7 @@ void notrace dwc_otg_fiq_nop(struct fiq_
+               FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
+               /* Force a clear before another dummy send */
+               FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
+-              FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
++              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+               FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+       }
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+@@ -352,6 +352,7 @@ struct fiq_state {
+       dma_addr_t dma_base;
+       struct fiq_dma_blob *fiq_dmab;
+       void *dummy_send;
++      dma_addr_t dummy_send_dma;
+       gintmsk_data_t gintmsk_saved;
+       haintmsk_data_t haintmsk_saved;
+       int mphi_int_count;
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -929,6 +929,8 @@ static void dwc_otg_hcd_free(dwc_otg_hcd
+       DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
+       DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
+       DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
++      DWC_DMA_FREE(dev, 16, dwc_otg_hcd->fiq_state->dummy_send,
++                   dwc_otg_hcd->fiq_state->dummy_send_dma);
+       DWC_FREE(dwc_otg_hcd->fiq_state);
+ #ifdef DWC_DEV_SRPCAP
+@@ -1021,7 +1023,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
+               for (i = 0; i < num_channels; i++) {
+                       hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH;
+               }
+-              hcd->fiq_state->dummy_send = DWC_ALLOC_ATOMIC(16);
++              hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16,
++                                                       &hcd->fiq_state->dummy_send_dma);
+               hcd->fiq_stack = DWC_ALLOC(sizeof(struct fiq_stack));
+               if (!hcd->fiq_stack) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0296-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch b/target/linux/brcm2708/patches-4.19/950-0296-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch
new file mode 100644 (file)
index 0000000..31e050a
--- /dev/null
@@ -0,0 +1,47 @@
+From f03f60a51efdf7fbc1f7d2c5b120a7de93ea6d9e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:13:25 +0000
+Subject: [PATCH] staging: vchiq_arm: Set up dma ranges on child
+ devices
+
+The VCHIQ driver now loads the audio, camera, codec, and vc-sm
+drivers as platform drivers. However they were not being given
+the correct DMA configuration.
+
+Call of_dma_configure with the parent (VCHIQ) parameters to be
+inherited by the child.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/interface/vchiq_arm/vchiq_arm.c   | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3585,6 +3585,7 @@ static struct platform_device *
+ vchiq_register_child(struct platform_device *pdev, const char *name)
+ {
+       struct platform_device_info pdevinfo;
++      struct platform_device *new_dev;
+       memset(&pdevinfo, 0, sizeof(pdevinfo));
+@@ -3593,7 +3594,17 @@ vchiq_register_child(struct platform_dev
+       pdevinfo.id = PLATFORM_DEVID_NONE;
+       pdevinfo.dma_mask = DMA_BIT_MASK(32);
+-      return platform_device_register_full(&pdevinfo);
++      new_dev = platform_device_register_full(&pdevinfo);
++      if (!new_dev)
++              return NULL;
++
++      /*
++       * We want the dma-ranges etc to be copied from the parent VCHIQ device
++       * to be passed on to the children too.
++       */
++      of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
++
++      return new_dev;
+ }
+ static int vchiq_probe(struct platform_device *pdev)
diff --git a/target/linux/brcm2708/patches-4.19/950-0296-usb-dwc_otg-Clean-up-build-warnings-on-64bit-kernels.patch b/target/linux/brcm2708/patches-4.19/950-0296-usb-dwc_otg-Clean-up-build-warnings-on-64bit-kernels.patch
deleted file mode 100644 (file)
index cc99a11..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-From d2536830d8f1ef06afdc84c5ac6e1a70b3a2bc40 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 16:03:31 +0000
-Subject: [PATCH] usb: dwc_otg: Clean up build warnings on 64bit
- kernels
-
-No functional changes. Almost all are changes to logging lines.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_driver.c    |  3 +--
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c   |  2 +-
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c       | 19 ++++++++++++++-----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 ++++------
- 4 files changed, 20 insertions(+), 14 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-@@ -837,8 +837,7 @@ static int dwc_otg_driver_probe(
-               retval = -ENOMEM;
-               goto fail;
-       }
--      dev_info(&_dev->dev, "base=0x%08x\n",
--                (unsigned)dwc_otg_device->os_dep.base);
-+      dev_info(&_dev->dev, "base=%p\n", dwc_otg_device->os_dep.base);
- #endif
-       /*
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-@@ -301,7 +301,7 @@ static int notrace fiq_iso_out_advance(s
-               last = 1;
-       /* New DMA address - address of bounce buffer referred to in index */
--      hcdma.d32 = (uint32_t) &blob->channel[n].index[i].buf[0];
-+      hcdma.d32 = (dma_addr_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
-@@ -1041,8 +1041,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
-                * moderately readable array casts.
-                */
-               hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base);
--              DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d",
--                              (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base,
-+              DWC_WARN("FIQ DMA bounce buffers: virt = %px dma = %pad len=%zu",
-+                              hcd->fiq_dmab, &hcd->fiq_state->dma_base,
-                               sizeof(struct fiq_dma_channel) * num_channels);
-               DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024);
-@@ -1522,9 +1522,12 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
-               /*
-                * Set dma_regs to bounce buffer. FIQ will update the
-                * state depending on transaction progress.
-+               * 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 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
-+              st->hcdma_copy.d32 = (dma_addr_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.
-                */
-@@ -1571,9 +1574,15 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
-                               st->nrpackets = i;
-                       }
-                       ptr = qtd->urb->buf + frame_desc->offset;
--                      /* Point the HC at the DMA address of the bounce buffers */
-+                      /*
-+                       * Point the HC at the DMA address of the bounce buffers
-+                       *
-+                       * 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 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
-+                      st->hcdma_copy.d32 = (dma_addr_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_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -454,11 +454,9 @@ static void hcd_init_fiq(void *cookie)
-               DWC_ERROR("Can't claim FIQ");
-               BUG();
-       }
--      DWC_WARN("FIQ on core %d at 0x%08x",
--                              smp_processor_id(),
--                              (fiq_fsm_enable ? (int)&dwc_otg_fiq_fsm : (int)&dwc_otg_fiq_nop));
--      DWC_WARN("FIQ ASM at 0x%08x length %d", (int)&_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
--              set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
-+      DWC_WARN("FIQ on core %d", smp_processor_id());
-+      DWC_WARN("FIQ ASM at %px length %d", &_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
-+      set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
-       memset(&regs,0,sizeof(regs));
-       regs.ARM_r8 = (long) dwc_otg_hcd->fiq_state;
-@@ -483,7 +481,7 @@ static void hcd_init_fiq(void *cookie)
-       dwc_otg_hcd->fiq_state->mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;
-       dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
-       dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
--      DWC_WARN("MPHI regs_base at 0x%08x", (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
-+      DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
-       //Enable mphi peripheral
-       writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
- #ifdef DEBUG
diff --git a/target/linux/brcm2708/patches-4.19/950-0297-staging-vc-sm-cma-Correct-DMA-configuration.patch b/target/linux/brcm2708/patches-4.19/950-0297-staging-vc-sm-cma-Correct-DMA-configuration.patch
new file mode 100644 (file)
index 0000000..8709eef
--- /dev/null
@@ -0,0 +1,44 @@
+From ea000a969afa022776bdf8050aaa501b2679e028 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:24:41 +0000
+Subject: [PATCH] staging: vc-sm-cma: Correct DMA configuration.
+
+Now that VCHIQ is setting up the DMA configuration as our
+parent device, don't try to configure it during probe.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -703,9 +703,6 @@ err_free_mem:
+ /* Driver loading. */
+ static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
+ {
+-      struct device *dev = &pdev->dev;
+-      int err;
+-
+       pr_info("%s: Videocore shared memory driver\n", __func__);
+       sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
+@@ -714,13 +711,11 @@ static int bcm2835_vc_sm_cma_probe(struc
+       sm_state->pdev = pdev;
+       mutex_init(&sm_state->map_lock);
+-      dev->coherent_dma_mask = DMA_BIT_MASK(32);
+-      dev->dma_mask = &dev->coherent_dma_mask;
+-      err = of_dma_configure(dev, NULL, true);
+-      if (err) {
+-              dev_err(dev, "Unable to setup DMA: %d\n", err);
+-              return err;
+-      }
++      pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
++                                         sizeof(*pdev->dev.dma_parms),
++                                         GFP_KERNEL);
++      /* dma_set_max_seg_size checks if dma_parms is NULL. */
++      dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF);
+       vchiq_add_connected_callback(vc_sm_connected_init);
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0297-usb-dwc_otg-Use-dma-allocation-for-mphi-dummy_send-b.patch b/target/linux/brcm2708/patches-4.19/950-0297-usb-dwc_otg-Use-dma-allocation-for-mphi-dummy_send-b.patch
deleted file mode 100644 (file)
index edc9336..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-From f0d93c5098283f88ea1de3af152a190177da8f36 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 30 Jan 2019 17:47:51 +0000
-Subject: [PATCH] usb: dwc_otg: Use dma allocation for mphi dummy_send
- buffer
-
-The FIQ driver used a kzalloc'ed buffer for dummy_send,
-passing a kernel virtual address to the hardware block.
-The buffer is only ever used for a dummy read, so it
-should be harmless, but there is the chance that it will
-cause exceptions.
-
-Use a dma allocation so that we have a genuine bus address,
-and read from that.
-Free the allocation when done for good measure.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 4 ++--
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 1 +
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c     | 5 ++++-
- 3 files changed, 7 insertions(+), 3 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-@@ -1347,7 +1347,7 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
-       /* We got an interrupt, didn't handle it. */
-       if (kick_irq) {
-               state->mphi_int_count++;
--              FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
-+              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-               FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-       }
-@@ -1408,7 +1408,7 @@ void notrace dwc_otg_fiq_nop(struct fiq_
-               FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
-               /* Force a clear before another dummy send */
-               FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
--              FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
-+              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-               FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-       }
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-@@ -352,6 +352,7 @@ struct fiq_state {
-       dma_addr_t dma_base;
-       struct fiq_dma_blob *fiq_dmab;
-       void *dummy_send;
-+      dma_addr_t dummy_send_dma;
-       gintmsk_data_t gintmsk_saved;
-       haintmsk_data_t haintmsk_saved;
-       int mphi_int_count;
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -929,6 +929,8 @@ static void dwc_otg_hcd_free(dwc_otg_hcd
-       DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
-       DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
-       DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
-+      DWC_DMA_FREE(dev, 16, dwc_otg_hcd->fiq_state->dummy_send,
-+                   dwc_otg_hcd->fiq_state->dummy_send_dma);
-       DWC_FREE(dwc_otg_hcd->fiq_state);
- #ifdef DWC_DEV_SRPCAP
-@@ -1021,7 +1023,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
-               for (i = 0; i < num_channels; i++) {
-                       hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH;
-               }
--              hcd->fiq_state->dummy_send = DWC_ALLOC_ATOMIC(16);
-+              hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16,
-+                                                       &hcd->fiq_state->dummy_send_dma);
-               hcd->fiq_stack = DWC_ALLOC(sizeof(struct fiq_stack));
-               if (!hcd->fiq_stack) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0298-staging-vc-sm-cma-Use-a-void-pointer-as-the-handle-w.patch b/target/linux/brcm2708/patches-4.19/950-0298-staging-vc-sm-cma-Use-a-void-pointer-as-the-handle-w.patch
new file mode 100644 (file)
index 0000000..6a43d94
--- /dev/null
@@ -0,0 +1,111 @@
+From df84621e5bd5cc206d1039ce0880ccd0b325525b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:29:00 +0000
+Subject: [PATCH] staging: vc-sm-cma: Use a void* pointer as the handle
+ within the kernel
+
+The driver was using an unsigned int as the handle to the outside world,
+and doing a nasty cast to the struct dmabuf when handed it back.
+This breaks badly with a 64 bit kernel where the pointer doesn't fit
+in an unsigned int.
+
+Switch to using a void* within the kernel. Reality is that it is
+a struct dma_buf*, but advertising it as such to other drivers seems
+to encourage the use of it as such, and I'm not sure on the implications
+of that.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c        | 10 +++++-----
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h    |  6 +++---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-common.h |  2 +-
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c  |  2 +-
+ 4 files changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -745,7 +745,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+ }
+ /* Get an internal resource handle mapped from the external one. */
+-int vc_sm_cma_int_handle(int handle)
++int vc_sm_cma_int_handle(void *handle)
+ {
+       struct dma_buf *dma_buf = (struct dma_buf *)handle;
+       struct vc_sm_buffer *res;
+@@ -762,7 +762,7 @@ int vc_sm_cma_int_handle(int handle)
+ EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
+ /* Free a previously allocated shared memory handle and block. */
+-int vc_sm_cma_free(int handle)
++int vc_sm_cma_free(void *handle)
+ {
+       struct dma_buf *dma_buf = (struct dma_buf *)handle;
+@@ -772,7 +772,7 @@ int vc_sm_cma_free(int handle)
+               return -EPERM;
+       }
+-      pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
++      pr_debug("%s: handle %p/dmabuf %p\n", __func__, handle, dma_buf);
+       dma_buf_put(dma_buf);
+@@ -781,7 +781,7 @@ int vc_sm_cma_free(int handle)
+ EXPORT_SYMBOL_GPL(vc_sm_cma_free);
+ /* Import a dmabuf to be shared with VC. */
+-int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
++int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
+ {
+       struct dma_buf *new_dma_buf;
+       struct vc_sm_buffer *res;
+@@ -801,7 +801,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
+               res = (struct vc_sm_buffer *)new_dma_buf->priv;
+               /* Assign valid handle at this time.*/
+-              *handle = (int)new_dma_buf;
++              *handle = new_dma_buf;
+       } else {
+               /*
+                * succeeded in importing the dma_buf, but then
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
+@@ -17,12 +17,12 @@
+ #endif
+ /* Free a previously allocated or imported shared memory handle and block. */
+-int vc_sm_cma_free(int handle);
++int vc_sm_cma_free(void *handle);
+ /* Get an internal resource handle mapped from the external one. */
+-int vc_sm_cma_int_handle(int handle);
++int vc_sm_cma_int_handle(void *handle);
+ /* Import a block of memory into the GPU space. */
+-int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
++int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, void **handle);
+ #endif /* __VC_SM_KNL_H__INCLUDED__ */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -52,7 +52,7 @@ struct mmal_buffer {
+       struct mmal_msg_context *msg_context;
+       struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
+-      int vcsm_handle;        /* VCSM handle having imported the dmabuf */
++      void *vcsm_handle;      /* VCSM handle having imported the dmabuf */
+       u32 vc_handle;          /* VC handle to that dmabuf */
+       u32 cmd;                /* MMAL command. 0=data. */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1794,7 +1794,7 @@ int mmal_vchi_buffer_cleanup(struct mmal
+       if (buf->vcsm_handle) {
+               int ret;
+-              pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
++              pr_debug("%s: vc_sm_cma_free on handle %p\n", __func__,
+                        buf->vcsm_handle);
+               ret = vc_sm_cma_free(buf->vcsm_handle);
+               if (ret)
diff --git a/target/linux/brcm2708/patches-4.19/950-0298-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch b/target/linux/brcm2708/patches-4.19/950-0298-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch
deleted file mode 100644 (file)
index 31e050a..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From f03f60a51efdf7fbc1f7d2c5b120a7de93ea6d9e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:13:25 +0000
-Subject: [PATCH] staging: vchiq_arm: Set up dma ranges on child
- devices
-
-The VCHIQ driver now loads the audio, camera, codec, and vc-sm
-drivers as platform drivers. However they were not being given
-the correct DMA configuration.
-
-Call of_dma_configure with the parent (VCHIQ) parameters to be
-inherited by the child.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/interface/vchiq_arm/vchiq_arm.c   | 13 ++++++++++++-
- 1 file changed, 12 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -3585,6 +3585,7 @@ static struct platform_device *
- vchiq_register_child(struct platform_device *pdev, const char *name)
- {
-       struct platform_device_info pdevinfo;
-+      struct platform_device *new_dev;
-       memset(&pdevinfo, 0, sizeof(pdevinfo));
-@@ -3593,7 +3594,17 @@ vchiq_register_child(struct platform_dev
-       pdevinfo.id = PLATFORM_DEVID_NONE;
-       pdevinfo.dma_mask = DMA_BIT_MASK(32);
--      return platform_device_register_full(&pdevinfo);
-+      new_dev = platform_device_register_full(&pdevinfo);
-+      if (!new_dev)
-+              return NULL;
-+
-+      /*
-+       * We want the dma-ranges etc to be copied from the parent VCHIQ device
-+       * to be passed on to the children too.
-+       */
-+      of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
-+
-+      return new_dev;
- }
- static int vchiq_probe(struct platform_device *pdev)
diff --git a/target/linux/brcm2708/patches-4.19/950-0299-staging-vc-sm-cma-Correct-DMA-configuration.patch b/target/linux/brcm2708/patches-4.19/950-0299-staging-vc-sm-cma-Correct-DMA-configuration.patch
deleted file mode 100644 (file)
index 8709eef..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From ea000a969afa022776bdf8050aaa501b2679e028 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:24:41 +0000
-Subject: [PATCH] staging: vc-sm-cma: Correct DMA configuration.
-
-Now that VCHIQ is setting up the DMA configuration as our
-parent device, don't try to configure it during probe.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 15 +++++----------
- 1 file changed, 5 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -703,9 +703,6 @@ err_free_mem:
- /* Driver loading. */
- static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
- {
--      struct device *dev = &pdev->dev;
--      int err;
--
-       pr_info("%s: Videocore shared memory driver\n", __func__);
-       sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
-@@ -714,13 +711,11 @@ static int bcm2835_vc_sm_cma_probe(struc
-       sm_state->pdev = pdev;
-       mutex_init(&sm_state->map_lock);
--      dev->coherent_dma_mask = DMA_BIT_MASK(32);
--      dev->dma_mask = &dev->coherent_dma_mask;
--      err = of_dma_configure(dev, NULL, true);
--      if (err) {
--              dev_err(dev, "Unable to setup DMA: %d\n", err);
--              return err;
--      }
-+      pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
-+                                         sizeof(*pdev->dev.dma_parms),
-+                                         GFP_KERNEL);
-+      /* dma_set_max_seg_size checks if dma_parms is NULL. */
-+      dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF);
-       vchiq_add_connected_callback(vc_sm_connected_init);
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0299-staging-vc-sm-cma-Fix-up-for-64bit-builds.patch b/target/linux/brcm2708/patches-4.19/950-0299-staging-vc-sm-cma-Fix-up-for-64bit-builds.patch
new file mode 100644 (file)
index 0000000..5216414
--- /dev/null
@@ -0,0 +1,199 @@
+From 696aa66a971b20e4f00431cb53747f0e4b92bb03 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:32:57 +0000
+Subject: [PATCH] staging: vc-sm-cma: Fix up for 64bit builds
+
+There were a number of logging lines that were using
+inappropriate formatting under 64bit kernels.
+
+The kernel_id field passed to/from the VPU was being
+abused for storing the struct vc_sm_buffer *.
+This breaks with 64bit kernels, so change to using an IDR.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 60 +++++++++++++++----
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  |  3 +-
+ 2 files changed, 48 insertions(+), 15 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -75,6 +75,9 @@ struct sm_state_t {
+       struct miscdevice dev;
+       struct sm_instance *sm_handle;  /* Handle for videocore service. */
++      spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
++      struct idr kernelid_map;
++
+       struct mutex map_lock;          /* Global map lock. */
+       struct list_head buffer_list;   /* List of buffer. */
+@@ -97,6 +100,29 @@ static int sm_inited;
+ /* ---- Private Functions ------------------------------------------------ */
++static int get_kernel_id(struct vc_sm_buffer *buffer)
++{
++      int handle;
++
++      spin_lock(&sm_state->kernelid_map_lock);
++      handle = idr_alloc(&sm_state->kernelid_map, buffer, 0, 0, GFP_KERNEL);
++      spin_unlock(&sm_state->kernelid_map_lock);
++
++      return handle;
++}
++
++static struct vc_sm_buffer *lookup_kernel_id(int handle)
++{
++      return idr_find(&sm_state->kernelid_map, handle);
++}
++
++static void free_kernel_id(int handle)
++{
++      spin_lock(&sm_state->kernelid_map_lock);
++      idr_remove(&sm_state->kernelid_map, handle);
++      spin_unlock(&sm_state->kernelid_map_lock);
++}
++
+ static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
+ {
+       struct sm_pde_t *sm_pde;
+@@ -129,8 +155,7 @@ static int vc_sm_cma_global_state_show(s
+       if (!sm_state)
+               return 0;
+-      seq_printf(s, "\nVC-ServiceHandle     0x%x\n",
+-                 (unsigned int)sm_state->sm_handle);
++      seq_printf(s, "\nVC-ServiceHandle     %p\n", sm_state->sm_handle);
+       /* Log all applicable mapping(s). */
+@@ -145,7 +170,7 @@ static int vc_sm_cma_global_state_show(s
+                                  resource);
+                       seq_printf(s, "           NAME         %s\n",
+                                  resource->name);
+-                      seq_printf(s, "           SIZE         %d\n",
++                      seq_printf(s, "           SIZE         %zu\n",
+                                  resource->size);
+                       seq_printf(s, "           DMABUF       %p\n",
+                                  resource->dma_buf);
+@@ -181,7 +206,7 @@ static void vc_sm_add_resource(struct vc
+       list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
+       mutex_unlock(&sm_state->map_lock);
+-      pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
++      pr_debug("[%s]: added buffer %p (name %s, size %zu)\n",
+                __func__, buffer, buffer->name, buffer->size);
+ }
+@@ -194,7 +219,7 @@ static void vc_sm_release_resource(struc
+       mutex_lock(&sm_state->map_lock);
+       mutex_lock(&buffer->lock);
+-      pr_debug("[%s]: buffer %p (name %s, size %d)\n",
++      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
+                __func__, buffer, buffer->name, buffer->size);
+       if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
+@@ -443,6 +468,7 @@ vc_sm_cma_import_dmabuf_internal(struct
+       struct vc_sm_import_result result = { };
+       struct dma_buf_attachment *attach = NULL;
+       struct sg_table *sgt = NULL;
++      dma_addr_t dma_addr;
+       int ret = 0;
+       int status;
+@@ -478,21 +504,22 @@ vc_sm_cma_import_dmabuf_internal(struct
+       }
+       import.type = VC_SM_ALLOC_NON_CACHED;
+-      import.addr = (uint32_t)sg_dma_address(sgt->sgl);
++      dma_addr = sg_dma_address(sgt->sgl);
++      import.addr = (uint32_t)dma_addr;
+       if ((import.addr & 0xC0000000) != 0xC0000000) {
+-              pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
+-                     __func__, import.addr);
++              pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
++                     __func__, &dma_addr);
+               import.addr |= 0xC0000000;
+       }
+       import.size = sg_dma_len(sgt->sgl);
+       import.allocator = current->tgid;
+-      import.kernel_id = (uint32_t)buffer;    //FIXME: 64 bit support needed.
++      import.kernel_id = get_kernel_id(buffer);
+       memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
+              sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
+-      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
+-               __func__, import.name, import.type, (void *)import.addr,
++      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
++               __func__, import.name, import.type, &dma_addr,
+                import.size);
+       /* Allocate the videocore buffer. */
+@@ -527,7 +554,7 @@ vc_sm_cma_import_dmabuf_internal(struct
+       buffer->attach = attach;
+       buffer->sgt = sgt;
+-      buffer->dma_addr = sg_dma_address(sgt->sgl);
++      buffer->dma_addr = dma_addr;
+       buffer->in_use = 1;
+       /*
+@@ -559,6 +586,7 @@ error:
+               vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
+                                   &sm_state->int_trans_id);
+       }
++      free_kernel_id(import.kernel_id);
+       kfree(buffer);
+       if (sgt)
+               dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+@@ -586,7 +614,7 @@ vc_sm_vpu_event(struct sm_instance *inst
+       {
+               struct vc_sm_released *release = (struct vc_sm_released *)reply;
+               struct vc_sm_buffer *buffer =
+-                              (struct vc_sm_buffer *)release->kernel_id;
++                                      lookup_kernel_id(release->kernel_id);
+               /*
+                * FIXME: Need to check buffer is still valid and allocated
+@@ -599,6 +627,7 @@ vc_sm_vpu_event(struct sm_instance *inst
+               buffer->vc_handle = 0;
+               buffer->vpu_state = VPU_NOT_MAPPED;
+               mutex_unlock(&buffer->lock);
++              free_kernel_id(release->kernel_id);
+               vc_sm_release_resource(buffer, 0);
+       }
+@@ -711,6 +740,9 @@ static int bcm2835_vc_sm_cma_probe(struc
+       sm_state->pdev = pdev;
+       mutex_init(&sm_state->map_lock);
++      spin_lock_init(&sm_state->kernelid_map_lock);
++      idr_init_base(&sm_state->kernelid_map, 1);
++
+       pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
+                                          sizeof(*pdev->dev.dma_parms),
+                                          GFP_KERNEL);
+@@ -735,6 +767,8 @@ static int bcm2835_vc_sm_cma_remove(stru
+               /* Stop the videocore shared memory service. */
+               vc_sm_cma_vchi_stop(&sm_state->sm_handle);
++              idr_destroy(&sm_state->kernelid_map);
++
+               /* Free the memory for the state structure. */
+               mutex_destroy(&sm_state->map_lock);
+               kfree(sm_state);
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -356,8 +356,7 @@ struct sm_instance *vc_sm_cma_vchi_init(
+       set_user_nice(instance->io_thread, -10);
+       wake_up_process(instance->io_thread);
+-      pr_debug("%s: success - instance 0x%x", __func__,
+-               (unsigned int)instance);
++      pr_debug("%s: success - instance %p", __func__, instance);
+       return instance;
+ err_close_services:
diff --git a/target/linux/brcm2708/patches-4.19/950-0300-configs-Enable-the-AD193x-codecs.patch b/target/linux/brcm2708/patches-4.19/950-0300-configs-Enable-the-AD193x-codecs.patch
new file mode 100644 (file)
index 0000000..29f7ee3
--- /dev/null
@@ -0,0 +1,28 @@
+From 3ffbec3df726c6d36ef728d476cb3ff3fcc17c81 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 7 Feb 2019 18:16:25 +0000
+Subject: [PATCH] configs: Enable the AD193x codecs
+
+See: https://github.com/raspberrypi/linux/issues/2850
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ sound/soc/codecs/Kconfig             | 4 ++--
+ 4 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -295,11 +295,11 @@ config SND_SOC_AD193X
+       tristate
+ config SND_SOC_AD193X_SPI
+-      tristate
++      tristate "Analog Devices AU193X CODEC - SPI"
+       select SND_SOC_AD193X
+ config SND_SOC_AD193X_I2C
+-      tristate
++      tristate "Analog Devices AU193X CODEC - I2C"
+       select SND_SOC_AD193X
+ config SND_SOC_AD1980
diff --git a/target/linux/brcm2708/patches-4.19/950-0300-staging-vc-sm-cma-Use-a-void-pointer-as-the-handle-w.patch b/target/linux/brcm2708/patches-4.19/950-0300-staging-vc-sm-cma-Use-a-void-pointer-as-the-handle-w.patch
deleted file mode 100644 (file)
index 6a43d94..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-From df84621e5bd5cc206d1039ce0880ccd0b325525b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:29:00 +0000
-Subject: [PATCH] staging: vc-sm-cma: Use a void* pointer as the handle
- within the kernel
-
-The driver was using an unsigned int as the handle to the outside world,
-and doing a nasty cast to the struct dmabuf when handed it back.
-This breaks badly with a 64 bit kernel where the pointer doesn't fit
-in an unsigned int.
-
-Switch to using a void* within the kernel. Reality is that it is
-a struct dma_buf*, but advertising it as such to other drivers seems
-to encourage the use of it as such, and I'm not sure on the implications
-of that.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c        | 10 +++++-----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h    |  6 +++---
- drivers/staging/vc04_services/vchiq-mmal/mmal-common.h |  2 +-
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c  |  2 +-
- 4 files changed, 10 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -745,7 +745,7 @@ static int bcm2835_vc_sm_cma_remove(stru
- }
- /* Get an internal resource handle mapped from the external one. */
--int vc_sm_cma_int_handle(int handle)
-+int vc_sm_cma_int_handle(void *handle)
- {
-       struct dma_buf *dma_buf = (struct dma_buf *)handle;
-       struct vc_sm_buffer *res;
-@@ -762,7 +762,7 @@ int vc_sm_cma_int_handle(int handle)
- EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
- /* Free a previously allocated shared memory handle and block. */
--int vc_sm_cma_free(int handle)
-+int vc_sm_cma_free(void *handle)
- {
-       struct dma_buf *dma_buf = (struct dma_buf *)handle;
-@@ -772,7 +772,7 @@ int vc_sm_cma_free(int handle)
-               return -EPERM;
-       }
--      pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
-+      pr_debug("%s: handle %p/dmabuf %p\n", __func__, handle, dma_buf);
-       dma_buf_put(dma_buf);
-@@ -781,7 +781,7 @@ int vc_sm_cma_free(int handle)
- EXPORT_SYMBOL_GPL(vc_sm_cma_free);
- /* Import a dmabuf to be shared with VC. */
--int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
-+int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
- {
-       struct dma_buf *new_dma_buf;
-       struct vc_sm_buffer *res;
-@@ -801,7 +801,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
-               res = (struct vc_sm_buffer *)new_dma_buf->priv;
-               /* Assign valid handle at this time.*/
--              *handle = (int)new_dma_buf;
-+              *handle = new_dma_buf;
-       } else {
-               /*
-                * succeeded in importing the dma_buf, but then
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-@@ -17,12 +17,12 @@
- #endif
- /* Free a previously allocated or imported shared memory handle and block. */
--int vc_sm_cma_free(int handle);
-+int vc_sm_cma_free(void *handle);
- /* Get an internal resource handle mapped from the external one. */
--int vc_sm_cma_int_handle(int handle);
-+int vc_sm_cma_int_handle(void *handle);
- /* Import a block of memory into the GPU space. */
--int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
-+int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, void **handle);
- #endif /* __VC_SM_KNL_H__INCLUDED__ */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -52,7 +52,7 @@ struct mmal_buffer {
-       struct mmal_msg_context *msg_context;
-       struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
--      int vcsm_handle;        /* VCSM handle having imported the dmabuf */
-+      void *vcsm_handle;      /* VCSM handle having imported the dmabuf */
-       u32 vc_handle;          /* VC handle to that dmabuf */
-       u32 cmd;                /* MMAL command. 0=data. */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1794,7 +1794,7 @@ int mmal_vchi_buffer_cleanup(struct mmal
-       if (buf->vcsm_handle) {
-               int ret;
--              pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
-+              pr_debug("%s: vc_sm_cma_free on handle %p\n", __func__,
-                        buf->vcsm_handle);
-               ret = vc_sm_cma_free(buf->vcsm_handle);
-               if (ret)
diff --git a/target/linux/brcm2708/patches-4.19/950-0301-overlays-balenaFin-v1.1.0-carrier-board-update.patch b/target/linux/brcm2708/patches-4.19/950-0301-overlays-balenaFin-v1.1.0-carrier-board-update.patch
new file mode 100644 (file)
index 0000000..4dc4141
--- /dev/null
@@ -0,0 +1,109 @@
+From 6cafe647492605d21c2418b6261bf3182b9229f2 Mon Sep 17 00:00:00 2001
+From: Zahari Petkov <zahari@balena.io>
+Date: Fri, 8 Feb 2019 13:03:38 +0200
+Subject: [PATCH] overlays: balenaFin v1.1.0 carrier board update
+
+A backward compatible update for the balenaFin carrier board for the
+Raspberry Pi Compute Module 3/3+ Lite.
+
+The updated overlay includes:
+  * support for the newly introduced RGB LEDs
+  * i2c-gpio and SDIO improvements
+  * DT based Marvell 88W8887 configuration
+
+Signed-off-by: Zahari Petkov <zahari@balena.io>
+---
+ arch/arm/boot/dts/overlays/README             |  2 +-
+ .../boot/dts/overlays/balena-fin-overlay.dts  | 46 ++++++++++++++++++-
+ 2 files changed, 45 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -472,7 +472,7 @@ Params: swap_lr                 Reverse
+ Name:   balena-fin
+ Info:   Overlay that enables WiFi, Bluetooth and the GPIO expander on the
+-        Balena Fin board.
++        balenaFin carrier board for the Raspberry Pi Compute Module 3/3+ Lite.
+ Load:   dtoverlay=balena-fin
+ Params: <None>
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -11,6 +11,7 @@
+                       pinctrl-0 = <&sdio_pins>;
+                       bus-width = <4>;
+                       brcm,overclock-50 = <35>;
++                      non-removable;
+                       status = "okay";
+               };
+       };
+@@ -34,7 +35,8 @@
+       fragment@2 {
+               target-path = "/";
+               __overlay__ {
+-                      // We should investigate how to switch to mmc-pwrseq-sd8787
++                      // We should switch to mmc-pwrseq-sd8787 after making it
++                      // compatible with sd8887
+                       // Currently that module requires two GPIOs to function since it
+                       // targets a slightly different chip
+                       power_ctrl: power_ctrl {
+@@ -46,10 +48,21 @@
+                       i2c_soft: i2c@0 {
+                               compatible = "i2c-gpio";
+                               gpios = <&gpio 43 0 /* sda */ &gpio 42 0 /* scl */>;
+-                              i2c-gpio,delay-us = <2>; /* ~100 kHz */
++                              i2c-gpio,delay-us = <5>;
++                              i2c-gpio,scl-open-drain;
++                              i2c-gpio,sda-open-drain;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
++
++                      sd8xxx-wlan {
++                              drvdbg = <0x6>;
++                              drv_mode = <0x1>;
++                              cfg80211_wext = <0xf>;
++                              sta_name = "wlan";
++                              wfd_name = "p2p";
++                              cal_data_cfg = "none";
++                      };
+               };
+       };
+@@ -74,6 +87,35 @@
+                               reg = <0x68>;
+                               status = "okay";
+                       };
++
++                      // RGB LEDs (>= v1.1.0)
++                      pca9633: pca9633@62 {
++                              compatible = "nxp,pca9633";
++                              reg = <0x62>;
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++
++                              red@0 {
++                                      label = "red";
++                                      reg = <0>;
++                                      linux,default-trigger = "none";
++                              };
++                              green@1 {
++                                      label = "green";
++                                      reg = <1>;
++                                      linux,default-trigger = "none";
++                              };
++                              blue@2 {
++                                      label = "blue";
++                                      reg = <2>;
++                                      linux,default-trigger = "none";
++                              };
++                              unused@3 {
++                                      label = "unused";
++                                      reg = <3>;
++                                      linux,default-trigger = "none";
++                              };
++                      };
+               };
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0301-staging-vc-sm-cma-Fix-up-for-64bit-builds.patch b/target/linux/brcm2708/patches-4.19/950-0301-staging-vc-sm-cma-Fix-up-for-64bit-builds.patch
deleted file mode 100644 (file)
index 5216414..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-From 696aa66a971b20e4f00431cb53747f0e4b92bb03 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:32:57 +0000
-Subject: [PATCH] staging: vc-sm-cma: Fix up for 64bit builds
-
-There were a number of logging lines that were using
-inappropriate formatting under 64bit kernels.
-
-The kernel_id field passed to/from the VPU was being
-abused for storing the struct vc_sm_buffer *.
-This breaks with 64bit kernels, so change to using an IDR.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 60 +++++++++++++++----
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  |  3 +-
- 2 files changed, 48 insertions(+), 15 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -75,6 +75,9 @@ struct sm_state_t {
-       struct miscdevice dev;
-       struct sm_instance *sm_handle;  /* Handle for videocore service. */
-+      spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
-+      struct idr kernelid_map;
-+
-       struct mutex map_lock;          /* Global map lock. */
-       struct list_head buffer_list;   /* List of buffer. */
-@@ -97,6 +100,29 @@ static int sm_inited;
- /* ---- Private Functions ------------------------------------------------ */
-+static int get_kernel_id(struct vc_sm_buffer *buffer)
-+{
-+      int handle;
-+
-+      spin_lock(&sm_state->kernelid_map_lock);
-+      handle = idr_alloc(&sm_state->kernelid_map, buffer, 0, 0, GFP_KERNEL);
-+      spin_unlock(&sm_state->kernelid_map_lock);
-+
-+      return handle;
-+}
-+
-+static struct vc_sm_buffer *lookup_kernel_id(int handle)
-+{
-+      return idr_find(&sm_state->kernelid_map, handle);
-+}
-+
-+static void free_kernel_id(int handle)
-+{
-+      spin_lock(&sm_state->kernelid_map_lock);
-+      idr_remove(&sm_state->kernelid_map, handle);
-+      spin_unlock(&sm_state->kernelid_map_lock);
-+}
-+
- static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
- {
-       struct sm_pde_t *sm_pde;
-@@ -129,8 +155,7 @@ static int vc_sm_cma_global_state_show(s
-       if (!sm_state)
-               return 0;
--      seq_printf(s, "\nVC-ServiceHandle     0x%x\n",
--                 (unsigned int)sm_state->sm_handle);
-+      seq_printf(s, "\nVC-ServiceHandle     %p\n", sm_state->sm_handle);
-       /* Log all applicable mapping(s). */
-@@ -145,7 +170,7 @@ static int vc_sm_cma_global_state_show(s
-                                  resource);
-                       seq_printf(s, "           NAME         %s\n",
-                                  resource->name);
--                      seq_printf(s, "           SIZE         %d\n",
-+                      seq_printf(s, "           SIZE         %zu\n",
-                                  resource->size);
-                       seq_printf(s, "           DMABUF       %p\n",
-                                  resource->dma_buf);
-@@ -181,7 +206,7 @@ static void vc_sm_add_resource(struct vc
-       list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
-       mutex_unlock(&sm_state->map_lock);
--      pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
-+      pr_debug("[%s]: added buffer %p (name %s, size %zu)\n",
-                __func__, buffer, buffer->name, buffer->size);
- }
-@@ -194,7 +219,7 @@ static void vc_sm_release_resource(struc
-       mutex_lock(&sm_state->map_lock);
-       mutex_lock(&buffer->lock);
--      pr_debug("[%s]: buffer %p (name %s, size %d)\n",
-+      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
-                __func__, buffer, buffer->name, buffer->size);
-       if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
-@@ -443,6 +468,7 @@ vc_sm_cma_import_dmabuf_internal(struct
-       struct vc_sm_import_result result = { };
-       struct dma_buf_attachment *attach = NULL;
-       struct sg_table *sgt = NULL;
-+      dma_addr_t dma_addr;
-       int ret = 0;
-       int status;
-@@ -478,21 +504,22 @@ vc_sm_cma_import_dmabuf_internal(struct
-       }
-       import.type = VC_SM_ALLOC_NON_CACHED;
--      import.addr = (uint32_t)sg_dma_address(sgt->sgl);
-+      dma_addr = sg_dma_address(sgt->sgl);
-+      import.addr = (uint32_t)dma_addr;
-       if ((import.addr & 0xC0000000) != 0xC0000000) {
--              pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
--                     __func__, import.addr);
-+              pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
-+                     __func__, &dma_addr);
-               import.addr |= 0xC0000000;
-       }
-       import.size = sg_dma_len(sgt->sgl);
-       import.allocator = current->tgid;
--      import.kernel_id = (uint32_t)buffer;    //FIXME: 64 bit support needed.
-+      import.kernel_id = get_kernel_id(buffer);
-       memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
-              sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
--      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
--               __func__, import.name, import.type, (void *)import.addr,
-+      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
-+               __func__, import.name, import.type, &dma_addr,
-                import.size);
-       /* Allocate the videocore buffer. */
-@@ -527,7 +554,7 @@ vc_sm_cma_import_dmabuf_internal(struct
-       buffer->attach = attach;
-       buffer->sgt = sgt;
--      buffer->dma_addr = sg_dma_address(sgt->sgl);
-+      buffer->dma_addr = dma_addr;
-       buffer->in_use = 1;
-       /*
-@@ -559,6 +586,7 @@ error:
-               vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
-                                   &sm_state->int_trans_id);
-       }
-+      free_kernel_id(import.kernel_id);
-       kfree(buffer);
-       if (sgt)
-               dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
-@@ -586,7 +614,7 @@ vc_sm_vpu_event(struct sm_instance *inst
-       {
-               struct vc_sm_released *release = (struct vc_sm_released *)reply;
-               struct vc_sm_buffer *buffer =
--                              (struct vc_sm_buffer *)release->kernel_id;
-+                                      lookup_kernel_id(release->kernel_id);
-               /*
-                * FIXME: Need to check buffer is still valid and allocated
-@@ -599,6 +627,7 @@ vc_sm_vpu_event(struct sm_instance *inst
-               buffer->vc_handle = 0;
-               buffer->vpu_state = VPU_NOT_MAPPED;
-               mutex_unlock(&buffer->lock);
-+              free_kernel_id(release->kernel_id);
-               vc_sm_release_resource(buffer, 0);
-       }
-@@ -711,6 +740,9 @@ static int bcm2835_vc_sm_cma_probe(struc
-       sm_state->pdev = pdev;
-       mutex_init(&sm_state->map_lock);
-+      spin_lock_init(&sm_state->kernelid_map_lock);
-+      idr_init_base(&sm_state->kernelid_map, 1);
-+
-       pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
-                                          sizeof(*pdev->dev.dma_parms),
-                                          GFP_KERNEL);
-@@ -735,6 +767,8 @@ static int bcm2835_vc_sm_cma_remove(stru
-               /* Stop the videocore shared memory service. */
-               vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-+              idr_destroy(&sm_state->kernelid_map);
-+
-               /* Free the memory for the state structure. */
-               mutex_destroy(&sm_state->map_lock);
-               kfree(sm_state);
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -356,8 +356,7 @@ struct sm_instance *vc_sm_cma_vchi_init(
-       set_user_nice(instance->io_thread, -10);
-       wake_up_process(instance->io_thread);
--      pr_debug("%s: success - instance 0x%x", __func__,
--               (unsigned int)instance);
-+      pr_debug("%s: success - instance %p", __func__, instance);
-       return instance;
- err_close_services:
diff --git a/target/linux/brcm2708/patches-4.19/950-0302-configs-Enable-the-AD193x-codecs.patch b/target/linux/brcm2708/patches-4.19/950-0302-configs-Enable-the-AD193x-codecs.patch
deleted file mode 100644 (file)
index 29f7ee3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 3ffbec3df726c6d36ef728d476cb3ff3fcc17c81 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 7 Feb 2019 18:16:25 +0000
-Subject: [PATCH] configs: Enable the AD193x codecs
-
-See: https://github.com/raspberrypi/linux/issues/2850
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- sound/soc/codecs/Kconfig             | 4 ++--
- 4 files changed, 8 insertions(+), 2 deletions(-)
-
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -295,11 +295,11 @@ config SND_SOC_AD193X
-       tristate
- config SND_SOC_AD193X_SPI
--      tristate
-+      tristate "Analog Devices AU193X CODEC - SPI"
-       select SND_SOC_AD193X
- config SND_SOC_AD193X_I2C
--      tristate
-+      tristate "Analog Devices AU193X CODEC - I2C"
-       select SND_SOC_AD193X
- config SND_SOC_AD1980
diff --git a/target/linux/brcm2708/patches-4.19/950-0302-gpu-vc4-fkms-Update-driver-to-not-use-plane-crtc.patch b/target/linux/brcm2708/patches-4.19/950-0302-gpu-vc4-fkms-Update-driver-to-not-use-plane-crtc.patch
new file mode 100644 (file)
index 0000000..b4567d8
--- /dev/null
@@ -0,0 +1,36 @@
+From e5285033e0fbfb6750d7d39e7edebf67a16c8434 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 19 Feb 2019 15:06:31 +0000
+Subject: [PATCH] gpu:vc4-fkms: Update driver to not use plane->crtc.
+
+Following on from
+commit 2f958af7fc248 ("drm/vc4: Stop updating plane->fb/crtc")
+do the same in the firmwarekms driver and look at plane_state->crtc
+instead.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -193,8 +193,8 @@ static void vc4_cursor_plane_atomic_upda
+                                          struct drm_plane_state *old_state)
+ {
+       struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+-      struct vc4_crtc *vc4_crtc = to_vc4_crtc(plane->crtc);
+       struct drm_plane_state *state = plane->state;
++      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+       dma_addr_t addr = bo->paddr + fb->offsets[0];
+@@ -682,8 +682,6 @@ static int vc4_fkms_bind(struct device *
+       drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane,
+                                 &vc4_crtc_funcs, NULL);
+       drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
+-      primary_plane->crtc = crtc;
+-      cursor_plane->crtc = crtc;
+       vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
+       if (!vc4_encoder)
diff --git a/target/linux/brcm2708/patches-4.19/950-0303-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch b/target/linux/brcm2708/patches-4.19/950-0303-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch
new file mode 100644 (file)
index 0000000..6690dfc
--- /dev/null
@@ -0,0 +1,26 @@
+From bb8e85deab20dd38c26d354452e1ac42add37530 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 19 Feb 2019 15:18:25 +0000
+Subject: [PATCH] drm: vc4: Programming the CTM is conditional on
+ running full KMS
+
+vc4_ctm_commit writes to HVS registers, so this is only applicable
+when in full KMS mode, not in firmware KMS mode. Add this conditional.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -147,7 +147,8 @@ vc4_atomic_complete_commit(struct drm_at
+       drm_atomic_helper_commit_modeset_disables(dev, state);
+-      vc4_ctm_commit(vc4, state);
++      if (!vc4->firmware_kms)
++              vc4_ctm_commit(vc4, state);
+       drm_atomic_helper_commit_planes(dev, state, 0);
diff --git a/target/linux/brcm2708/patches-4.19/950-0303-overlays-balenaFin-v1.1.0-carrier-board-update.patch b/target/linux/brcm2708/patches-4.19/950-0303-overlays-balenaFin-v1.1.0-carrier-board-update.patch
deleted file mode 100644 (file)
index 4dc4141..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-From 6cafe647492605d21c2418b6261bf3182b9229f2 Mon Sep 17 00:00:00 2001
-From: Zahari Petkov <zahari@balena.io>
-Date: Fri, 8 Feb 2019 13:03:38 +0200
-Subject: [PATCH] overlays: balenaFin v1.1.0 carrier board update
-
-A backward compatible update for the balenaFin carrier board for the
-Raspberry Pi Compute Module 3/3+ Lite.
-
-The updated overlay includes:
-  * support for the newly introduced RGB LEDs
-  * i2c-gpio and SDIO improvements
-  * DT based Marvell 88W8887 configuration
-
-Signed-off-by: Zahari Petkov <zahari@balena.io>
----
- arch/arm/boot/dts/overlays/README             |  2 +-
- .../boot/dts/overlays/balena-fin-overlay.dts  | 46 ++++++++++++++++++-
- 2 files changed, 45 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -472,7 +472,7 @@ Params: swap_lr                 Reverse
- Name:   balena-fin
- Info:   Overlay that enables WiFi, Bluetooth and the GPIO expander on the
--        Balena Fin board.
-+        balenaFin carrier board for the Raspberry Pi Compute Module 3/3+ Lite.
- Load:   dtoverlay=balena-fin
- Params: <None>
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -11,6 +11,7 @@
-                       pinctrl-0 = <&sdio_pins>;
-                       bus-width = <4>;
-                       brcm,overclock-50 = <35>;
-+                      non-removable;
-                       status = "okay";
-               };
-       };
-@@ -34,7 +35,8 @@
-       fragment@2 {
-               target-path = "/";
-               __overlay__ {
--                      // We should investigate how to switch to mmc-pwrseq-sd8787
-+                      // We should switch to mmc-pwrseq-sd8787 after making it
-+                      // compatible with sd8887
-                       // Currently that module requires two GPIOs to function since it
-                       // targets a slightly different chip
-                       power_ctrl: power_ctrl {
-@@ -46,10 +48,21 @@
-                       i2c_soft: i2c@0 {
-                               compatible = "i2c-gpio";
-                               gpios = <&gpio 43 0 /* sda */ &gpio 42 0 /* scl */>;
--                              i2c-gpio,delay-us = <2>; /* ~100 kHz */
-+                              i2c-gpio,delay-us = <5>;
-+                              i2c-gpio,scl-open-drain;
-+                              i2c-gpio,sda-open-drain;
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
-+
-+                      sd8xxx-wlan {
-+                              drvdbg = <0x6>;
-+                              drv_mode = <0x1>;
-+                              cfg80211_wext = <0xf>;
-+                              sta_name = "wlan";
-+                              wfd_name = "p2p";
-+                              cal_data_cfg = "none";
-+                      };
-               };
-       };
-@@ -74,6 +87,35 @@
-                               reg = <0x68>;
-                               status = "okay";
-                       };
-+
-+                      // RGB LEDs (>= v1.1.0)
-+                      pca9633: pca9633@62 {
-+                              compatible = "nxp,pca9633";
-+                              reg = <0x62>;
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+
-+                              red@0 {
-+                                      label = "red";
-+                                      reg = <0>;
-+                                      linux,default-trigger = "none";
-+                              };
-+                              green@1 {
-+                                      label = "green";
-+                                      reg = <1>;
-+                                      linux,default-trigger = "none";
-+                              };
-+                              blue@2 {
-+                                      label = "blue";
-+                                      reg = <2>;
-+                                      linux,default-trigger = "none";
-+                              };
-+                              unused@3 {
-+                                      label = "unused";
-+                                      reg = <3>;
-+                                      linux,default-trigger = "none";
-+                              };
-+                      };
-               };
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0304-gpu-vc4-fkms-Update-driver-to-not-use-plane-crtc.patch b/target/linux/brcm2708/patches-4.19/950-0304-gpu-vc4-fkms-Update-driver-to-not-use-plane-crtc.patch
deleted file mode 100644 (file)
index b4567d8..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From e5285033e0fbfb6750d7d39e7edebf67a16c8434 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 19 Feb 2019 15:06:31 +0000
-Subject: [PATCH] gpu:vc4-fkms: Update driver to not use plane->crtc.
-
-Following on from
-commit 2f958af7fc248 ("drm/vc4: Stop updating plane->fb/crtc")
-do the same in the firmwarekms driver and look at plane_state->crtc
-instead.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -193,8 +193,8 @@ static void vc4_cursor_plane_atomic_upda
-                                          struct drm_plane_state *old_state)
- {
-       struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
--      struct vc4_crtc *vc4_crtc = to_vc4_crtc(plane->crtc);
-       struct drm_plane_state *state = plane->state;
-+      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
-       struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
-       dma_addr_t addr = bo->paddr + fb->offsets[0];
-@@ -682,8 +682,6 @@ static int vc4_fkms_bind(struct device *
-       drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane,
-                                 &vc4_crtc_funcs, NULL);
-       drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
--      primary_plane->crtc = crtc;
--      cursor_plane->crtc = crtc;
-       vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
-       if (!vc4_encoder)
diff --git a/target/linux/brcm2708/patches-4.19/950-0304-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch b/target/linux/brcm2708/patches-4.19/950-0304-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch
new file mode 100644 (file)
index 0000000..1280251
--- /dev/null
@@ -0,0 +1,51 @@
+From 39c4b77533bee8d88d2f4c9be9463041ec1dd483 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 12:33:29 +0000
+Subject: [PATCH] staging: mmal_vchiq: Add in the Bayer encoding
+ formats
+
+The list of formats was copied before Bayer support was added.
+The ISP supports Bayer and is being supported by the bcm2835_codec
+driver, so add in the encodings for them.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-encodings.h | 27 +++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
+@@ -69,6 +69,33 @@
+  */
+ #define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
++/* Bayer formats
++ * FourCC values copied from V4L2 where defined.
++ */
++/* 8 bit per pixel Bayer formats. */
++#define MMAL_ENCODING_BAYER_SBGGR8     MMAL_FOURCC('B', 'A', '8', '1')
++#define MMAL_ENCODING_BAYER_SGBRG8     MMAL_FOURCC('G', 'B', 'R', 'G')
++#define MMAL_ENCODING_BAYER_SGRBG8     MMAL_FOURCC('G', 'R', 'B', 'G')
++#define MMAL_ENCODING_BAYER_SRGGB8     MMAL_FOURCC('R', 'G', 'G', 'B')
++
++/* 10 bit per pixel packed Bayer formats. */
++#define MMAL_ENCODING_BAYER_SBGGR10P   MMAL_FOURCC('p', 'B', 'A', 'A')
++#define MMAL_ENCODING_BAYER_SGRBG10P   MMAL_FOURCC('p', 'g', 'A', 'A')
++#define MMAL_ENCODING_BAYER_SGBRG10P   MMAL_FOURCC('p', 'G', 'A', 'A')
++#define MMAL_ENCODING_BAYER_SRGGB10P   MMAL_FOURCC('p', 'R', 'A', 'A')
++
++/* 12 bit per pixel packed Bayer formats. */
++#define MMAL_ENCODING_BAYER_SBGGR12P   MMAL_FOURCC('p', 'B', '1', '2')
++#define MMAL_ENCODING_BAYER_SGRBG12P   MMAL_FOURCC('p', 'g', '1', '2')
++#define MMAL_ENCODING_BAYER_SGBRG12P   MMAL_FOURCC('p', 'G', '1', '2')
++#define MMAL_ENCODING_BAYER_SRGGB12P   MMAL_FOURCC('p', 'R', '1', '2')
++
++/* 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')
++#define MMAL_ENCODING_BAYER_SGRBG16    MMAL_FOURCC('G', 'R', '1', '6')
++#define MMAL_ENCODING_BAYER_SRGGB16    MMAL_FOURCC('R', 'G', '1', '6')
++
+ /** An EGL image handle
+  */
+ #define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
diff --git a/target/linux/brcm2708/patches-4.19/950-0305-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch b/target/linux/brcm2708/patches-4.19/950-0305-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch
deleted file mode 100644 (file)
index 6690dfc..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From bb8e85deab20dd38c26d354452e1ac42add37530 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 19 Feb 2019 15:18:25 +0000
-Subject: [PATCH] drm: vc4: Programming the CTM is conditional on
- running full KMS
-
-vc4_ctm_commit writes to HVS registers, so this is only applicable
-when in full KMS mode, not in firmware KMS mode. Add this conditional.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -147,7 +147,8 @@ vc4_atomic_complete_commit(struct drm_at
-       drm_atomic_helper_commit_modeset_disables(dev, state);
--      vc4_ctm_commit(vc4, state);
-+      if (!vc4->firmware_kms)
-+              vc4_ctm_commit(vc4, state);
-       drm_atomic_helper_commit_planes(dev, state, 0);
diff --git a/target/linux/brcm2708/patches-4.19/950-0305-staging-mmal-vchiq-Always-return-the-param-size-from.patch b/target/linux/brcm2708/patches-4.19/950-0305-staging-mmal-vchiq-Always-return-the-param-size-from.patch
new file mode 100644 (file)
index 0000000..121f855
--- /dev/null
@@ -0,0 +1,38 @@
+From 0c0e55d9b04868733f30c348df7400fa5e6d30e2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 12:36:56 +0000
+Subject: [PATCH] staging: mmal-vchiq: Always return the param size
+ from param_get
+
+mmal-vchiq is a reimplementation of the userland library for MMAL.
+When getting a parameter, the client provides the storage and
+the size of the storage. The VPU then returns the size of the
+parameter that it wished to return, and as much as possible of
+that parameter is returned to the client.
+
+The implementation previously only returned the size provided
+by the VPU should it exceed the buffer size. So for parameters
+such as the supported encodings list the client had no idea
+how much of the provided storage had been populated.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1413,11 +1413,12 @@ static int port_parameter_get(struct vch
+                */
+               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+                      *value_size);
+-              *value_size = rmsg->u.port_parameter_get_reply.size;
+       } else {
+               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+                      rmsg->u.port_parameter_get_reply.size);
+       }
++      /* Always report the size of the returned parameter to the caller */
++      *value_size = rmsg->u.port_parameter_get_reply.size;
+       pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
+                ret, port->component->handle, port->handle, parameter_id);
diff --git a/target/linux/brcm2708/patches-4.19/950-0306-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch b/target/linux/brcm2708/patches-4.19/950-0306-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch
new file mode 100644 (file)
index 0000000..603b394
--- /dev/null
@@ -0,0 +1,29 @@
+From 78c34cf60b9ae8bf8aa797c72d2f1abdc0a0bb9d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 12:51:03 +0000
+Subject: [PATCH] staging: mmal-vchiq: If the VPU returns an error,
+ don't negate it
+
+There is an enum for the errors that the VPU can return.
+port_parameter_get was negating that value, but also using -EINVAL
+from the Linux error codes.
+Pass the VPU error code as positive values. Should the function
+need to pass a Linux failure, then return that as negative.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1401,7 +1401,8 @@ static int port_parameter_get(struct vch
+               goto release_msg;
+       }
+-      ret = -rmsg->u.port_parameter_get_reply.status;
++      ret = rmsg->u.port_parameter_get_reply.status;
++
+       /* port_parameter_get_reply.size includes the header,
+        * whilst *value_size doesn't.
+        */
diff --git a/target/linux/brcm2708/patches-4.19/950-0306-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch b/target/linux/brcm2708/patches-4.19/950-0306-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch
deleted file mode 100644 (file)
index 1280251..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From 39c4b77533bee8d88d2f4c9be9463041ec1dd483 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 12:33:29 +0000
-Subject: [PATCH] staging: mmal_vchiq: Add in the Bayer encoding
- formats
-
-The list of formats was copied before Bayer support was added.
-The ISP supports Bayer and is being supported by the bcm2835_codec
-driver, so add in the encodings for them.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-encodings.h | 27 +++++++++++++++++++
- 1 file changed, 27 insertions(+)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
-@@ -69,6 +69,33 @@
-  */
- #define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
-+/* Bayer formats
-+ * FourCC values copied from V4L2 where defined.
-+ */
-+/* 8 bit per pixel Bayer formats. */
-+#define MMAL_ENCODING_BAYER_SBGGR8     MMAL_FOURCC('B', 'A', '8', '1')
-+#define MMAL_ENCODING_BAYER_SGBRG8     MMAL_FOURCC('G', 'B', 'R', 'G')
-+#define MMAL_ENCODING_BAYER_SGRBG8     MMAL_FOURCC('G', 'R', 'B', 'G')
-+#define MMAL_ENCODING_BAYER_SRGGB8     MMAL_FOURCC('R', 'G', 'G', 'B')
-+
-+/* 10 bit per pixel packed Bayer formats. */
-+#define MMAL_ENCODING_BAYER_SBGGR10P   MMAL_FOURCC('p', 'B', 'A', 'A')
-+#define MMAL_ENCODING_BAYER_SGRBG10P   MMAL_FOURCC('p', 'g', 'A', 'A')
-+#define MMAL_ENCODING_BAYER_SGBRG10P   MMAL_FOURCC('p', 'G', 'A', 'A')
-+#define MMAL_ENCODING_BAYER_SRGGB10P   MMAL_FOURCC('p', 'R', 'A', 'A')
-+
-+/* 12 bit per pixel packed Bayer formats. */
-+#define MMAL_ENCODING_BAYER_SBGGR12P   MMAL_FOURCC('p', 'B', '1', '2')
-+#define MMAL_ENCODING_BAYER_SGRBG12P   MMAL_FOURCC('p', 'g', '1', '2')
-+#define MMAL_ENCODING_BAYER_SGBRG12P   MMAL_FOURCC('p', 'G', '1', '2')
-+#define MMAL_ENCODING_BAYER_SRGGB12P   MMAL_FOURCC('p', 'R', '1', '2')
-+
-+/* 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')
-+#define MMAL_ENCODING_BAYER_SGRBG16    MMAL_FOURCC('G', 'R', '1', '6')
-+#define MMAL_ENCODING_BAYER_SRGGB16    MMAL_FOURCC('R', 'G', '1', '6')
-+
- /** An EGL image handle
-  */
- #define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
diff --git a/target/linux/brcm2708/patches-4.19/950-0307-staging-bcm2835_codec-Query-supported-formats-from-t.patch b/target/linux/brcm2708/patches-4.19/950-0307-staging-bcm2835_codec-Query-supported-formats-from-t.patch
new file mode 100644 (file)
index 0000000..5eec74e
--- /dev/null
@@ -0,0 +1,727 @@
+From ce8cc7a85839af588b753ce4af0832db9c467f45 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 13:44:00 +0000
+Subject: [PATCH] staging: bcm2835_codec: Query supported formats from
+ the component
+
+The driver was previously working with hard coded tables of
+which video formats were supported by each component.
+The components advertise this information via a MMAL parameter,
+so retrieve the information from there during probe, and store
+in the state structure for that device.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 455 +++++++++++++-----
+ 1 file changed, 327 insertions(+), 128 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -88,17 +88,12 @@ struct bcm2835_codec_fmt {
+       int     bytesperline_align;
+       u32     flags;
+       u32     mmal_fmt;
+-      bool    decode_only;
+-      bool    encode_only;
+       int     size_multiplier_x2;
+ };
+-/* Supported raw pixel formats. Those supported for both encode and decode
+- * must come first, with those only supported for decode coming after (there
+- * are no formats supported for encode only).
+- */
+-static struct bcm2835_codec_fmt raw_formats[] = {
++static const struct bcm2835_codec_fmt supported_formats[] = {
+       {
++              /* YUV formats */
+               .fourcc                 = V4L2_PIX_FMT_YUV420,
+               .depth                  = 8,
+               .bytesperline_align     = 32,
+@@ -139,7 +134,6 @@ static struct bcm2835_codec_fmt raw_form
+               .bytesperline_align     = 32,
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_YUYV,
+-              .encode_only            = true,
+               .size_multiplier_x2     = 2,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_UYVY,
+@@ -147,7 +141,6 @@ static struct bcm2835_codec_fmt raw_form
+               .bytesperline_align     = 32,
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_UYVY,
+-              .encode_only            = true,
+               .size_multiplier_x2     = 2,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_YVYU,
+@@ -155,7 +148,6 @@ static struct bcm2835_codec_fmt raw_form
+               .bytesperline_align     = 32,
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_YVYU,
+-              .encode_only            = true,
+               .size_multiplier_x2     = 2,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_VYUY,
+@@ -163,15 +155,14 @@ static struct bcm2835_codec_fmt raw_form
+               .bytesperline_align     = 32,
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_VYUY,
+-              .encode_only            = true,
+               .size_multiplier_x2     = 2,
+       }, {
++              /* RGB formats */
+               .fourcc                 = V4L2_PIX_FMT_RGB24,
+               .depth                  = 24,
+               .bytesperline_align     = 32,
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_RGB24,
+-              .encode_only            = true,
+               .size_multiplier_x2     = 2,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_BGR24,
+@@ -179,7 +170,6 @@ static struct bcm2835_codec_fmt raw_form
+               .bytesperline_align     = 32,
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BGR24,
+-              .encode_only            = true,
+               .size_multiplier_x2     = 2,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_BGR32,
+@@ -187,17 +177,126 @@ static struct bcm2835_codec_fmt raw_form
+               .bytesperline_align     = 32,
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BGRA,
+-              .encode_only            = true,
+               .size_multiplier_x2     = 2,
+-      },
+-};
+-
+-/* Supported encoded formats. Those supported for both encode and decode
+- * must come first, with those only supported for decode coming after (there
+- * are no formats supported for encode only).
+- */
+-static struct bcm2835_codec_fmt encoded_formats[] = {
+-      {
++      }, {
++              /* Bayer formats */
++              /* 8 bit */
++              .fourcc                 = V4L2_PIX_FMT_SRGGB8,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB8,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SBGGR8,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR8,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGRBG8,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG8,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGBRG8,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG8,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* 10 bit */
++              .fourcc                 = V4L2_PIX_FMT_SRGGB10P,
++              .depth                  = 10,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB10P,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SBGGR10P,
++              .depth                  = 10,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR10P,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGRBG10P,
++              .depth                  = 10,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG10P,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGBRG10P,
++              .depth                  = 10,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG10P,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* 12 bit */
++              .fourcc                 = V4L2_PIX_FMT_SRGGB12P,
++              .depth                  = 12,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB12P,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SBGGR12P,
++              .depth                  = 12,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR12P,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGRBG12P,
++              .depth                  = 12,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG12P,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGBRG12P,
++              .depth                  = 12,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG12P,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* 16 bit */
++              .fourcc                 = V4L2_PIX_FMT_SRGGB16,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB16,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SBGGR16,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR16,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGRBG16,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG16,
++              .size_multiplier_x2     = 2,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGBRG16,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG16,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* Compressed formats */
+               .fourcc                 = V4L2_PIX_FMT_H264,
+               .depth                  = 0,
+               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
+@@ -212,30 +311,22 @@ static struct bcm2835_codec_fmt encoded_
+               .depth                  = 0,
+               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
+               .mmal_fmt               = MMAL_ENCODING_MP4V,
+-              .decode_only            = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_H263,
+               .depth                  = 0,
+               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
+               .mmal_fmt               = MMAL_ENCODING_H263,
+-              .decode_only            = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_MPEG2,
+               .depth                  = 0,
+               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
+               .mmal_fmt               = MMAL_ENCODING_MP2V,
+-              .decode_only            = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_VP8,
+               .depth                  = 0,
+               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
+               .mmal_fmt               = MMAL_ENCODING_VP8,
+-              .decode_only            = true,
+       },
+-      /*
+-       * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
+-       * support them.
+-       */
+ };
+ struct bcm2835_codec_fmt_list {
+@@ -243,19 +334,6 @@ struct bcm2835_codec_fmt_list {
+       unsigned int num_entries;
+ };
+-#define RAW_LIST      0
+-#define ENCODED_LIST  1
+-
+-struct bcm2835_codec_fmt_list formats[] = {
+-      {
+-              .list = raw_formats,
+-              .num_entries = ARRAY_SIZE(raw_formats),
+-      }, {
+-              .list = encoded_formats,
+-              .num_entries = ARRAY_SIZE(encoded_formats),
+-      },
+-};
+-
+ struct m2m_mmal_buffer {
+       struct v4l2_m2m_buffer  m2m;
+       struct mmal_buffer      mmal;
+@@ -284,52 +362,6 @@ struct bcm2835_codec_q_data {
+       bool                    eos_buffer_in_use;      /* debug only */
+ };
+-enum {
+-      V4L2_M2M_SRC = 0,
+-      V4L2_M2M_DST = 1,
+-};
+-
+-static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
+-                                                           bool capture)
+-{
+-      return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
+-}
+-
+-static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
+-{
+-      return &get_format_list(decode, capture)->list[0];
+-}
+-
+-static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
+-                                           bool capture)
+-{
+-      struct bcm2835_codec_fmt *fmt;
+-      unsigned int k;
+-      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
+-
+-      for (k = 0; k < fmts->num_entries; k++) {
+-              fmt = &fmts->list[k];
+-              if (fmt->fourcc == f->fmt.pix.pixelformat)
+-                      break;
+-      }
+-
+-      /*
+-       * Some compressed formats are only supported for decoding, not
+-       * encoding.
+-       */
+-      if (!decode && fmts->list[k].decode_only)
+-              return NULL;
+-
+-      /* Some pixel formats are only supported for encoding, not decoding. */
+-      if (decode && fmts->list[k].encode_only)
+-              return NULL;
+-
+-      if (k == fmts->num_entries)
+-              return NULL;
+-
+-      return &fmts->list[k];
+-}
+-
+ struct bcm2835_codec_dev {
+       struct platform_device *pdev;
+@@ -342,6 +374,9 @@ struct bcm2835_codec_dev {
+       /* allocated mmal instance and components */
+       bool                    decode;  /* Is this instance a decoder? */
++      /* The list of formats supported on input and output queues. */
++      struct bcm2835_codec_fmt_list   supported_fmts[2];
++
+       struct vchiq_mmal_instance      *instance;
+       struct v4l2_m2m_dev     *m2m_dev;
+@@ -374,8 +409,59 @@ struct bcm2835_codec_ctx {
+ struct bcm2835_codec_driver {
+       struct bcm2835_codec_dev *encode;
+       struct bcm2835_codec_dev *decode;
++      struct bcm2835_codec_dev *isp;
++};
++
++enum {
++      V4L2_M2M_SRC = 0,
++      V4L2_M2M_DST = 1,
+ };
++static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
++{
++      unsigned int i;
++
++      for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
++              if (supported_formats[i].mmal_fmt == mmal_fmt)
++                      return &supported_formats[i];
++      }
++      return NULL;
++}
++
++static inline
++struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
++                                             bool capture)
++{
++      return &dev->supported_fmts[capture ? 1 : 0];
++}
++
++static
++struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
++                                           bool capture)
++{
++      return &dev->supported_fmts[capture ? 1 : 0].list[0];
++}
++
++static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
++                                           struct bcm2835_codec_dev *dev,
++                                           bool capture)
++{
++      struct bcm2835_codec_fmt *fmt;
++      unsigned int k;
++      struct bcm2835_codec_fmt_list *fmts =
++                                      &dev->supported_fmts[capture ? 1 : 0];
++
++      for (k = 0; k < fmts->num_entries; k++) {
++              fmt = &fmts->list[k];
++              if (fmt->fourcc == f->fmt.pix.pixelformat)
++                      break;
++      }
++      if (k == fmts->num_entries)
++              return NULL;
++
++      return &fmts->list[k];
++}
++
+ static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
+ {
+       return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
+@@ -456,7 +542,6 @@ static inline unsigned int get_bytesperl
+ }
+ static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
+-                                 bool decode,
+                                  struct bcm2835_codec_q_data *q_data,
+                                  struct vchiq_mmal_port *port)
+ {
+@@ -473,7 +558,7 @@ static void setup_mmal_port_format(struc
+               port->es.video.frame_rate.den = 1;
+       } else {
+               /* Compressed format - leave resolution as 0 for decode */
+-              if (decode) {
++              if (ctx->dev->decode) {
+                       port->es.video.width = 0;
+                       port->es.video.height = 0;
+                       port->es.video.crop.width = 0;
+@@ -802,22 +887,15 @@ static int vidioc_querycap(struct file *
+       return 0;
+ }
+-static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
++static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
++                  bool capture)
+ {
+       struct bcm2835_codec_fmt *fmt;
+-      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
++      struct bcm2835_codec_fmt_list *fmts =
++                                      get_format_list(ctx->dev, capture);
+       if (f->index < fmts->num_entries) {
+               /* Format found */
+-              /* Check format isn't a decode only format when encoding */
+-              if (!decode &&
+-                  fmts->list[f->index].decode_only)
+-                      return -EINVAL;
+-              /* Check format isn't a decode only format when encoding */
+-              if (decode &&
+-                  fmts->list[f->index].encode_only)
+-                      return -EINVAL;
+-
+               fmt = &fmts->list[f->index];
+               f->pixelformat = fmt->fourcc;
+               f->flags = fmt->flags;
+@@ -833,7 +911,7 @@ static int vidioc_enum_fmt_vid_cap(struc
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      return enum_fmt(f, ctx->dev->decode, true);
++      return enum_fmt(f, ctx, true);
+ }
+ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+@@ -841,7 +919,7 @@ static int vidioc_enum_fmt_vid_out(struc
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      return enum_fmt(f, ctx->dev->decode, false);
++      return enum_fmt(f, ctx, false);
+ }
+ static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
+@@ -933,11 +1011,11 @@ static int vidioc_try_fmt_vid_cap(struct
+       struct bcm2835_codec_fmt *fmt;
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      fmt = find_format(f, ctx->dev->decode, true);
++      fmt = find_format(f, ctx->dev, true);
+       if (!fmt) {
+-              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+                                                           true)->fourcc;
+-              fmt = find_format(f, ctx->dev->decode, true);
++              fmt = find_format(f, ctx->dev, true);
+       }
+       return vidioc_try_fmt(f, fmt);
+@@ -949,11 +1027,11 @@ static int vidioc_try_fmt_vid_out(struct
+       struct bcm2835_codec_fmt *fmt;
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      fmt = find_format(f, ctx->dev->decode, false);
++      fmt = find_format(f, ctx->dev, false);
+       if (!fmt) {
+-              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+                                                           false)->fourcc;
+-              fmt = find_format(f, ctx->dev->decode, false);
++              fmt = find_format(f, ctx->dev, false);
+       }
+       if (!f->fmt.pix.colorspace)
+@@ -988,7 +1066,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+               return -EBUSY;
+       }
+-      q_data->fmt = find_format(f, ctx->dev->decode,
++      q_data->fmt = find_format(f, ctx->dev,
+                                 f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       q_data->crop_width = f->fmt.pix.width;
+       q_data->height = f->fmt.pix.height;
+@@ -1041,7 +1119,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+       if (!port)
+               return 0;
+-      setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
++      setup_mmal_port_format(ctx, q_data, port);
+       ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
+       if (ret) {
+               v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
+@@ -1064,8 +1142,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+               struct bcm2835_codec_q_data *q_data_dst =
+                                               &ctx->q_data[V4L2_M2M_DST];
+-              setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
+-                                     port_dst);
++              setup_mmal_port_format(ctx, q_data_dst, port_dst);
+               ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
+               if (ret) {
+                       v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
+@@ -1636,10 +1713,10 @@ static int bcm2835_codec_create_componen
+                                     MMAL_PARAMETER_ZERO_COPY, &enable,
+                                     sizeof(enable));
+-      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
++      setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
+                              &ctx->component->input[0]);
+-      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
++      setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
+                              &ctx->component->output[0]);
+       ret = vchiq_mmal_port_set_format(dev->instance,
+@@ -2025,8 +2102,8 @@ static int bcm2835_codec_open(struct fil
+               goto open_unlock;
+       }
+-      ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
+-      ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
++      ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
++      ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
+       if (dev->decode) {
+               /*
+                * Input width and height are irrelevant as they will be defined
+@@ -2209,13 +2286,130 @@ static const struct v4l2_m2m_ops m2m_ops
+       .job_abort      = job_abort,
+ };
++/* 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
++ * overhead on that.
++ */
++#define MAX_SUPPORTED_ENCODINGS 40
++
++/* Populate dev->supported_fmts with the formats supported by those ports. */
++static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
++{
++      struct bcm2835_codec_fmt *list;
++      struct vchiq_mmal_component *component;
++      u32 fourccs[MAX_SUPPORTED_ENCODINGS];
++      u32 param_size = sizeof(fourccs);
++      unsigned int i, j, num_encodings;
++      int ret;
++
++      ret = vchiq_mmal_component_init(dev->instance,
++                                      dev->decode ?
++                                              "ril.video_decode" :
++                                              "ril.video_encode",
++                                      &component);
++      if (ret < 0) {
++              v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
++                       __func__);
++              return -ENOMEM;
++      }
++
++      ret = vchiq_mmal_port_parameter_get(dev->instance,
++                                          &component->input[0],
++                                          MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++                                          &fourccs,
++                                          &param_size);
++
++      if (ret) {
++              if (ret == MMAL_MSG_STATUS_ENOSPC) {
++                      v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
++                               __func__);
++                      num_encodings = MAX_SUPPORTED_ENCODINGS;
++              } else {
++                      v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
++                               __func__, ret);
++                      ret = -EINVAL;
++                      goto destroy_component;
++              }
++      } else {
++              num_encodings = param_size / sizeof(u32);
++      }
++
++      /* Assume at this stage that all encodings will be supported in V4L2.
++       * Any that aren't supported will waste a very small amount of memory.
++       */
++      list = devm_kzalloc(&dev->pdev->dev,
++                          sizeof(struct bcm2835_codec_fmt) * num_encodings,
++                          GFP_KERNEL);
++      if (!list) {
++              ret = -ENOMEM;
++              goto destroy_component;
++      }
++      dev->supported_fmts[0].list = list;
++
++      for (i = 0, j = 0; i < num_encodings; i++) {
++              const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
++
++              if (fmt) {
++                      list[j] = *fmt;
++                      j++;
++              }
++      }
++      dev->supported_fmts[0].num_entries = j;
++
++      param_size = sizeof(fourccs);
++      ret = vchiq_mmal_port_parameter_get(dev->instance,
++                                          &component->output[0],
++                                          MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++                                          &fourccs,
++                                          &param_size);
++
++      if (ret) {
++              if (ret == MMAL_MSG_STATUS_ENOSPC) {
++                      v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
++                               __func__);
++                      num_encodings = MAX_SUPPORTED_ENCODINGS;
++              } else {
++                      ret = -EINVAL;
++                      goto destroy_component;
++              }
++      } else {
++              num_encodings = param_size / sizeof(u32);
++      }
++      /* Assume at this stage that all encodings will be supported in V4L2. */
++      list = devm_kzalloc(&dev->pdev->dev,
++                          sizeof(struct bcm2835_codec_fmt) * num_encodings,
++                          GFP_KERNEL);
++      if (!list) {
++              ret = -ENOMEM;
++              goto destroy_component;
++      }
++      dev->supported_fmts[1].list = list;
++
++      for (i = 0, j = 0; i < num_encodings; i++) {
++              const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
++
++              if (fmt) {
++                      list[j] = *fmt;
++                      j++;
++              }
++      }
++      dev->supported_fmts[1].num_entries = j;
++
++      ret = 0;
++
++destroy_component:
++      vchiq_mmal_component_finalise(dev->instance, component);
++
++      return ret;
++}
++
+ static int bcm2835_codec_create(struct platform_device *pdev,
+                               struct bcm2835_codec_dev **new_dev,
+                               bool decode)
+ {
+       struct bcm2835_codec_dev *dev;
+       struct video_device *vfd;
+-      struct vchiq_mmal_instance *instance = NULL;
+       int video_nr;
+       int ret;
+@@ -2227,10 +2421,18 @@ static int bcm2835_codec_create(struct p
+       dev->decode = decode;
+-      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++      ret = vchiq_mmal_init(&dev->instance);
+       if (ret)
+               return ret;
++      ret = bcm2835_codec_get_supported_fmts(dev);
++      if (ret)
++              goto vchiq_finalise;
++
++      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++      if (ret)
++              goto vchiq_finalise;
++
+       atomic_set(&dev->num_inst, 0);
+       mutex_init(&dev->dev_mutex);
+@@ -2270,12 +2472,7 @@ static int bcm2835_codec_create(struct p
+               goto err_m2m;
+       }
+-      ret = vchiq_mmal_init(&instance);
+-      if (ret < 0)
+-              goto err_m2m;
+-      dev->instance = instance;
+-
+-      v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
++      v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
+                 dev->decode ? "decode" : "encode");
+       return 0;
+@@ -2284,7 +2481,8 @@ err_m2m:
+       video_unregister_device(&dev->vfd);
+ unreg_dev:
+       v4l2_device_unregister(&dev->v4l2_dev);
+-
++vchiq_finalise:
++      vchiq_mmal_finalise(dev->instance);
+       return ret;
+ }
+@@ -2297,6 +2495,7 @@ static int bcm2835_codec_destroy(struct
+       v4l2_m2m_release(dev->m2m_dev);
+       video_unregister_device(&dev->vfd);
+       v4l2_device_unregister(&dev->v4l2_dev);
++      vchiq_mmal_finalise(dev->instance);
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0307-staging-mmal-vchiq-Always-return-the-param-size-from.patch b/target/linux/brcm2708/patches-4.19/950-0307-staging-mmal-vchiq-Always-return-the-param-size-from.patch
deleted file mode 100644 (file)
index 121f855..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 0c0e55d9b04868733f30c348df7400fa5e6d30e2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 12:36:56 +0000
-Subject: [PATCH] staging: mmal-vchiq: Always return the param size
- from param_get
-
-mmal-vchiq is a reimplementation of the userland library for MMAL.
-When getting a parameter, the client provides the storage and
-the size of the storage. The VPU then returns the size of the
-parameter that it wished to return, and as much as possible of
-that parameter is returned to the client.
-
-The implementation previously only returned the size provided
-by the VPU should it exceed the buffer size. So for parameters
-such as the supported encodings list the client had no idea
-how much of the provided storage had been populated.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1413,11 +1413,12 @@ static int port_parameter_get(struct vch
-                */
-               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
-                      *value_size);
--              *value_size = rmsg->u.port_parameter_get_reply.size;
-       } else {
-               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
-                      rmsg->u.port_parameter_get_reply.size);
-       }
-+      /* Always report the size of the returned parameter to the caller */
-+      *value_size = rmsg->u.port_parameter_get_reply.size;
-       pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
-                ret, port->component->handle, port->handle, parameter_id);
diff --git a/target/linux/brcm2708/patches-4.19/950-0308-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch b/target/linux/brcm2708/patches-4.19/950-0308-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch
new file mode 100644 (file)
index 0000000..df59acd
--- /dev/null
@@ -0,0 +1,384 @@
+From 7afce6566802bcaa468f92b9e06da8b899161128 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 14:07:52 +0000
+Subject: [PATCH] staging: bcm2835_codec: Add support for the ISP as an
+ M2M device
+
+The MMAL ISP component can also use this same V4L2 wrapper to
+provide a M2M format conversion and resizer.
+Instantiate 3 V4L2 devices now, one for each of decode, encode,
+and isp.
+The ISP currently doesn't expose any controls via V4L2, but this
+can be extended in the future.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 132 ++++++++++++------
+ 1 file changed, 92 insertions(+), 40 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -54,10 +54,26 @@ static int encode_video_nr = 11;
+ module_param(encode_video_nr, int, 0644);
+ MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
++static int isp_video_nr = 12;
++module_param(isp_video_nr, int, 0644);
++MODULE_PARM_DESC(isp_video_nr, "isp video device number");
++
+ static unsigned int debug;
+ module_param(debug, uint, 0644);
+ MODULE_PARM_DESC(debug, "activates debug info (0-3)");
++enum bcm2835_codec_role {
++      DECODE,
++      ENCODE,
++      ISP,
++};
++
++static const char * const components[] = {
++      "ril.video_decode",
++      "ril.video_encode",
++      "ril.isp",
++};
++
+ #define MIN_W         32
+ #define MIN_H         32
+ #define MAX_W         1920
+@@ -373,7 +389,7 @@ struct bcm2835_codec_dev {
+       atomic_t                num_inst;
+       /* allocated mmal instance and components */
+-      bool                    decode;  /* Is this instance a decoder? */
++      enum bcm2835_codec_role role;
+       /* The list of formats supported on input and output queues. */
+       struct bcm2835_codec_fmt_list   supported_fmts[2];
+@@ -558,7 +574,7 @@ static void setup_mmal_port_format(struc
+               port->es.video.frame_rate.den = 1;
+       } else {
+               /* Compressed format - leave resolution as 0 for decode */
+-              if (ctx->dev->decode) {
++              if (ctx->dev->role == DECODE) {
+                       port->es.video.width = 0;
+                       port->es.video.height = 0;
+                       port->es.video.crop.width = 0;
+@@ -1089,7 +1105,8 @@ static int vidioc_s_fmt(struct bcm2835_c
+       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
+                q_data->bytesperline, q_data->sizeimage);
+-      if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
++      if (ctx->dev->role == DECODE &&
++          q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
+           f->fmt.pix.width && f->fmt.pix.height) {
+               /*
+                * On the decoder, if provided with a resolution on the input
+@@ -1188,7 +1205,8 @@ static int vidioc_g_selection(struct fil
+       bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
+                                                               true : false;
+-      if (capture_queue ^ ctx->dev->decode)
++      if ((ctx->dev->role == DECODE && !capture_queue) ||
++          (ctx->dev->role == ENCODE && capture_queue))
+               /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
+               return -EINVAL;
+@@ -1196,7 +1214,8 @@ static int vidioc_g_selection(struct fil
+       if (!q_data)
+               return -EINVAL;
+-      if (ctx->dev->decode) {
++      switch (ctx->dev->role) {
++      case DECODE:
+               switch (s->target) {
+               case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+               case V4L2_SEL_TGT_COMPOSE:
+@@ -1214,7 +1233,8 @@ static int vidioc_g_selection(struct fil
+               default:
+                       return -EINVAL;
+               }
+-      } else {
++              break;
++      case ENCODE:
+               switch (s->target) {
+               case V4L2_SEL_TGT_CROP_DEFAULT:
+               case V4L2_SEL_TGT_CROP_BOUNDS:
+@@ -1232,6 +1252,9 @@ static int vidioc_g_selection(struct fil
+               default:
+                       return -EINVAL;
+               }
++              break;
++      case ISP:
++              break;
+       }
+       return 0;
+@@ -1249,7 +1272,8 @@ static int vidioc_s_selection(struct fil
+                __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
+                s->r.width, s->r.height);
+-      if (capture_queue ^ ctx->dev->decode)
++      if ((ctx->dev->role == DECODE && !capture_queue) ||
++          (ctx->dev->role == ENCODE && capture_queue))
+               /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
+               return -EINVAL;
+@@ -1257,7 +1281,8 @@ static int vidioc_s_selection(struct fil
+       if (!q_data)
+               return -EINVAL;
+-      if (ctx->dev->decode) {
++      switch (ctx->dev->role) {
++      case DECODE:
+               switch (s->target) {
+               case V4L2_SEL_TGT_COMPOSE:
+                       /* Accept cropped image */
+@@ -1272,7 +1297,8 @@ static int vidioc_s_selection(struct fil
+               default:
+                       return -EINVAL;
+               }
+-      } else {
++              break;
++      case ENCODE:
+               switch (s->target) {
+               case V4L2_SEL_TGT_CROP:
+                       /* Only support crop from (0,0) */
+@@ -1287,6 +1313,9 @@ static int vidioc_s_selection(struct fil
+               default:
+                       return -EINVAL;
+               }
++              break;
++      case ISP:
++              break;
+       }
+       return 0;
+@@ -1490,7 +1519,7 @@ static int vidioc_try_decoder_cmd(struct
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      if (!ctx->dev->decode)
++      if (ctx->dev->role != DECODE)
+               return -EINVAL;
+       switch (cmd->cmd) {
+@@ -1564,7 +1593,7 @@ static int vidioc_try_encoder_cmd(struct
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      if (ctx->dev->decode)
++      if (ctx->dev->role != ENCODE)
+               return -EINVAL;
+       switch (cmd->cmd) {
+@@ -1697,12 +1726,11 @@ static int bcm2835_codec_create_componen
+       unsigned int enable = 1;
+       int ret;
+-      ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
+-                                      "ril.video_decode" : "ril.video_encode",
++      ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
+                                       &ctx->component);
+       if (ret < 0) {
+-              v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
+-                       __func__, dev->decode ? "decode" : "encode");
++              v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
++                       __func__, components[dev->role]);
+               return -ENOMEM;
+       }
+@@ -1729,13 +1757,7 @@ static int bcm2835_codec_create_componen
+       if (ret < 0)
+               goto destroy_component;
+-      if (dev->decode) {
+-              if (ctx->q_data[V4L2_M2M_DST].sizeimage <
+-                      ctx->component->output[0].minimum_buffer.size)
+-                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
+-                               ctx->q_data[V4L2_M2M_DST].sizeimage,
+-                               ctx->component->output[0].minimum_buffer.size);
+-      } else {
++      if (dev->role == ENCODE) {
+               if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
+                       ctx->component->output[0].minimum_buffer.size)
+                       v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
+@@ -1744,6 +1766,12 @@ static int bcm2835_codec_create_componen
+               /* Now we have a component we can set all the ctrls */
+               bcm2835_codec_set_ctrls(ctx);
++      } else {
++              if (ctx->q_data[V4L2_M2M_DST].sizeimage <
++                      ctx->component->output[0].minimum_buffer.size)
++                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
++                               ctx->q_data[V4L2_M2M_DST].sizeimage,
++                               ctx->component->output[0].minimum_buffer.size);
+       }
+       return 0;
+@@ -2090,8 +2118,6 @@ static int bcm2835_codec_open(struct fil
+       struct v4l2_ctrl_handler *hdl;
+       int rc = 0;
+-      v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
+-               dev->decode ? "decode" : "encode");
+       if (mutex_lock_interruptible(&dev->dev_mutex)) {
+               v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
+               return -ERESTARTSYS;
+@@ -2104,7 +2130,8 @@ static int bcm2835_codec_open(struct fil
+       ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
+       ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
+-      if (dev->decode) {
++      switch (dev->role) {
++      case DECODE:
+               /*
+                * Input width and height are irrelevant as they will be defined
+                * by the bitstream not the format. Required by V4L2 though.
+@@ -2126,7 +2153,8 @@ static int bcm2835_codec_open(struct fil
+                       get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
+                                     ctx->q_data[V4L2_M2M_DST].height,
+                                     ctx->q_data[V4L2_M2M_DST].fmt);
+-      } else {
++              break;
++      case ENCODE:
+               ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
+               ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
+               ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
+@@ -2144,6 +2172,9 @@ static int bcm2835_codec_open(struct fil
+               ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
+               ctx->q_data[V4L2_M2M_DST].sizeimage =
+                                               DEF_COMP_BUF_SIZE_720P_OR_LESS;
++              break;
++      case ISP:
++              break;
+       }
+       ctx->colorspace = V4L2_COLORSPACE_REC709;
+@@ -2154,7 +2185,7 @@ static int bcm2835_codec_open(struct fil
+       file->private_data = &ctx->fh;
+       ctx->dev = dev;
+       hdl = &ctx->hdl;
+-      if (!dev->decode) {
++      if (dev->role == ENCODE) {
+               /* Encode controls */
+               v4l2_ctrl_handler_init(hdl, 6);
+@@ -2303,14 +2334,11 @@ static int bcm2835_codec_get_supported_f
+       unsigned int i, j, num_encodings;
+       int ret;
+-      ret = vchiq_mmal_component_init(dev->instance,
+-                                      dev->decode ?
+-                                              "ril.video_decode" :
+-                                              "ril.video_encode",
++      ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
+                                       &component);
+       if (ret < 0) {
+-              v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
+-                       __func__);
++              v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
++                       __func__, components[dev->role]);
+               return -ENOMEM;
+       }
+@@ -2406,12 +2434,13 @@ destroy_component:
+ static int bcm2835_codec_create(struct platform_device *pdev,
+                               struct bcm2835_codec_dev **new_dev,
+-                              bool decode)
++                              enum bcm2835_codec_role role)
+ {
+       struct bcm2835_codec_dev *dev;
+       struct video_device *vfd;
+       int video_nr;
+       int ret;
++      const static char *roles[] = {"decode", "encode", "isp"};
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+@@ -2419,7 +2448,7 @@ static int bcm2835_codec_create(struct p
+       dev->pdev = pdev;
+-      dev->decode = decode;
++      dev->role = role;
+       ret = vchiq_mmal_init(&dev->instance);
+       if (ret)
+@@ -2441,14 +2470,27 @@ static int bcm2835_codec_create(struct p
+       vfd->lock = &dev->dev_mutex;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+-      if (dev->decode) {
++      switch (role) {
++      case DECODE:
+               v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+               video_nr = decode_video_nr;
+-      } else {
++              break;
++      case ENCODE:
+               v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
+               video_nr = encode_video_nr;
++              break;
++      case ISP:
++              v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
++              v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
++              v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
++              v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
++              video_nr = isp_video_nr;
++              break;
++      default:
++              ret = -EINVAL;
++              goto unreg_dev;
+       }
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+@@ -2473,7 +2515,7 @@ static int bcm2835_codec_create(struct p
+       }
+       v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
+-                dev->decode ? "decode" : "encode");
++                roles[role]);
+       return 0;
+ err_m2m:
+@@ -2509,11 +2551,15 @@ static int bcm2835_codec_probe(struct pl
+       if (!drv)
+               return -ENOMEM;
+-      ret = bcm2835_codec_create(pdev, &drv->encode, false);
++      ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
+       if (ret)
+               goto out;
+-      ret = bcm2835_codec_create(pdev, &drv->decode, true);
++      ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
++      if (ret)
++              goto out;
++
++      ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
+       if (ret)
+               goto out;
+@@ -2526,6 +2572,10 @@ out:
+               bcm2835_codec_destroy(drv->encode);
+               drv->encode = NULL;
+       }
++      if (drv->decode) {
++              bcm2835_codec_destroy(drv->decode);
++              drv->decode = NULL;
++      }
+       return ret;
+ }
+@@ -2533,6 +2583,8 @@ static int bcm2835_codec_remove(struct p
+ {
+       struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
++      bcm2835_codec_destroy(drv->isp);
++
+       bcm2835_codec_destroy(drv->encode);
+       bcm2835_codec_destroy(drv->decode);
diff --git a/target/linux/brcm2708/patches-4.19/950-0308-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch b/target/linux/brcm2708/patches-4.19/950-0308-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch
deleted file mode 100644 (file)
index 603b394..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 78c34cf60b9ae8bf8aa797c72d2f1abdc0a0bb9d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 12:51:03 +0000
-Subject: [PATCH] staging: mmal-vchiq: If the VPU returns an error,
- don't negate it
-
-There is an enum for the errors that the VPU can return.
-port_parameter_get was negating that value, but also using -EINVAL
-from the Linux error codes.
-Pass the VPU error code as positive values. Should the function
-need to pass a Linux failure, then return that as negative.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1401,7 +1401,8 @@ static int port_parameter_get(struct vch
-               goto release_msg;
-       }
--      ret = -rmsg->u.port_parameter_get_reply.status;
-+      ret = rmsg->u.port_parameter_get_reply.status;
-+
-       /* port_parameter_get_reply.size includes the header,
-        * whilst *value_size doesn't.
-        */
diff --git a/target/linux/brcm2708/patches-4.19/950-0309-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch b/target/linux/brcm2708/patches-4.19/950-0309-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch
new file mode 100644 (file)
index 0000000..fcdcc4a
--- /dev/null
@@ -0,0 +1,179 @@
+From a126fcc4ff38718e2e714fbb78db3ca1c4f8e564 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 15 Feb 2019 11:36:14 +0000
+Subject: [PATCH] staging: bcm2835_codec: Add an option for ignoring
+ Bayer formats.
+
+This is a workaround for GStreamer currently not identifying Bayer
+as a raw format, therefore any device that supports it does not
+match the criteria for v4l2convert.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 29 ++++++++++++++++++-
+ 1 file changed, 28 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
+@@ -58,6 +58,15 @@ static int isp_video_nr = 12;
+ module_param(isp_video_nr, int, 0644);
+ MODULE_PARM_DESC(isp_video_nr, "isp video device number");
++/*
++ * Workaround for GStreamer v4l2convert component not considering Bayer formats
++ * as raw, and therefore not considering a V4L2 device that supports them as
++ * as a suitable candidate.
++ */
++static bool disable_bayer;
++module_param(disable_bayer, bool, 0644);
++MODULE_PARM_DESC(disable_bayer, "Disable support for Bayer formats");
++
+ static unsigned int debug;
+ module_param(debug, uint, 0644);
+ MODULE_PARM_DESC(debug, "activates debug info (0-3)");
+@@ -105,6 +114,7 @@ struct bcm2835_codec_fmt {
+       u32     flags;
+       u32     mmal_fmt;
+       int     size_multiplier_x2;
++      bool    is_bayer;
+ };
+ static const struct bcm2835_codec_fmt supported_formats[] = {
+@@ -203,6 +213,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB8,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SBGGR8,
+               .depth                  = 8,
+@@ -210,6 +221,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR8,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGRBG8,
+               .depth                  = 8,
+@@ -217,6 +229,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG8,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGBRG8,
+               .depth                  = 8,
+@@ -224,6 +237,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG8,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               /* 10 bit */
+               .fourcc                 = V4L2_PIX_FMT_SRGGB10P,
+@@ -232,6 +246,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB10P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SBGGR10P,
+               .depth                  = 10,
+@@ -239,6 +254,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR10P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGRBG10P,
+               .depth                  = 10,
+@@ -246,6 +262,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG10P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGBRG10P,
+               .depth                  = 10,
+@@ -253,6 +270,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG10P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               /* 12 bit */
+               .fourcc                 = V4L2_PIX_FMT_SRGGB12P,
+@@ -261,6 +279,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB12P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SBGGR12P,
+               .depth                  = 12,
+@@ -268,6 +287,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR12P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGRBG12P,
+               .depth                  = 12,
+@@ -275,6 +295,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG12P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGBRG12P,
+               .depth                  = 12,
+@@ -282,6 +303,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG12P,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               /* 16 bit */
+               .fourcc                 = V4L2_PIX_FMT_SRGGB16,
+@@ -290,6 +312,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB16,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SBGGR16,
+               .depth                  = 16,
+@@ -297,6 +320,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR16,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGRBG16,
+               .depth                  = 16,
+@@ -304,6 +328,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG16,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               .fourcc                 = V4L2_PIX_FMT_SGBRG16,
+               .depth                  = 16,
+@@ -311,6 +336,7 @@ static const struct bcm2835_codec_fmt su
+               .flags                  = 0,
+               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG16,
+               .size_multiplier_x2     = 2,
++              .is_bayer               = true,
+       }, {
+               /* Compressed formats */
+               .fourcc                 = V4L2_PIX_FMT_H264,
+@@ -438,7 +464,8 @@ static const struct bcm2835_codec_fmt *g
+       unsigned int i;
+       for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+-              if (supported_formats[i].mmal_fmt == mmal_fmt)
++              if (supported_formats[i].mmal_fmt == mmal_fmt &&
++                  (!disable_bayer || !supported_formats[i].is_bayer))
+                       return &supported_formats[i];
+       }
+       return NULL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0309-staging-bcm2835_codec-Query-supported-formats-from-t.patch b/target/linux/brcm2708/patches-4.19/950-0309-staging-bcm2835_codec-Query-supported-formats-from-t.patch
deleted file mode 100644 (file)
index 5eec74e..0000000
+++ /dev/null
@@ -1,727 +0,0 @@
-From ce8cc7a85839af588b753ce4af0832db9c467f45 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 13:44:00 +0000
-Subject: [PATCH] staging: bcm2835_codec: Query supported formats from
- the component
-
-The driver was previously working with hard coded tables of
-which video formats were supported by each component.
-The components advertise this information via a MMAL parameter,
-so retrieve the information from there during probe, and store
-in the state structure for that device.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 455 +++++++++++++-----
- 1 file changed, 327 insertions(+), 128 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -88,17 +88,12 @@ struct bcm2835_codec_fmt {
-       int     bytesperline_align;
-       u32     flags;
-       u32     mmal_fmt;
--      bool    decode_only;
--      bool    encode_only;
-       int     size_multiplier_x2;
- };
--/* Supported raw pixel formats. Those supported for both encode and decode
-- * must come first, with those only supported for decode coming after (there
-- * are no formats supported for encode only).
-- */
--static struct bcm2835_codec_fmt raw_formats[] = {
-+static const struct bcm2835_codec_fmt supported_formats[] = {
-       {
-+              /* YUV formats */
-               .fourcc                 = V4L2_PIX_FMT_YUV420,
-               .depth                  = 8,
-               .bytesperline_align     = 32,
-@@ -139,7 +134,6 @@ static struct bcm2835_codec_fmt raw_form
-               .bytesperline_align     = 32,
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_YUYV,
--              .encode_only            = true,
-               .size_multiplier_x2     = 2,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_UYVY,
-@@ -147,7 +141,6 @@ static struct bcm2835_codec_fmt raw_form
-               .bytesperline_align     = 32,
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_UYVY,
--              .encode_only            = true,
-               .size_multiplier_x2     = 2,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_YVYU,
-@@ -155,7 +148,6 @@ static struct bcm2835_codec_fmt raw_form
-               .bytesperline_align     = 32,
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_YVYU,
--              .encode_only            = true,
-               .size_multiplier_x2     = 2,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_VYUY,
-@@ -163,15 +155,14 @@ static struct bcm2835_codec_fmt raw_form
-               .bytesperline_align     = 32,
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_VYUY,
--              .encode_only            = true,
-               .size_multiplier_x2     = 2,
-       }, {
-+              /* RGB formats */
-               .fourcc                 = V4L2_PIX_FMT_RGB24,
-               .depth                  = 24,
-               .bytesperline_align     = 32,
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_RGB24,
--              .encode_only            = true,
-               .size_multiplier_x2     = 2,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_BGR24,
-@@ -179,7 +170,6 @@ static struct bcm2835_codec_fmt raw_form
-               .bytesperline_align     = 32,
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BGR24,
--              .encode_only            = true,
-               .size_multiplier_x2     = 2,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_BGR32,
-@@ -187,17 +177,126 @@ static struct bcm2835_codec_fmt raw_form
-               .bytesperline_align     = 32,
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BGRA,
--              .encode_only            = true,
-               .size_multiplier_x2     = 2,
--      },
--};
--
--/* Supported encoded formats. Those supported for both encode and decode
-- * must come first, with those only supported for decode coming after (there
-- * are no formats supported for encode only).
-- */
--static struct bcm2835_codec_fmt encoded_formats[] = {
--      {
-+      }, {
-+              /* Bayer formats */
-+              /* 8 bit */
-+              .fourcc                 = V4L2_PIX_FMT_SRGGB8,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB8,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SBGGR8,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR8,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGRBG8,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG8,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGBRG8,
-+              .depth                  = 8,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG8,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              /* 10 bit */
-+              .fourcc                 = V4L2_PIX_FMT_SRGGB10P,
-+              .depth                  = 10,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB10P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SBGGR10P,
-+              .depth                  = 10,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR10P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGRBG10P,
-+              .depth                  = 10,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG10P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGBRG10P,
-+              .depth                  = 10,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG10P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              /* 12 bit */
-+              .fourcc                 = V4L2_PIX_FMT_SRGGB12P,
-+              .depth                  = 12,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB12P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SBGGR12P,
-+              .depth                  = 12,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR12P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGRBG12P,
-+              .depth                  = 12,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG12P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGBRG12P,
-+              .depth                  = 12,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG12P,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              /* 16 bit */
-+              .fourcc                 = V4L2_PIX_FMT_SRGGB16,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB16,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SBGGR16,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR16,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGRBG16,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG16,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              .fourcc                 = V4L2_PIX_FMT_SGBRG16,
-+              .depth                  = 16,
-+              .bytesperline_align     = 32,
-+              .flags                  = 0,
-+              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG16,
-+              .size_multiplier_x2     = 2,
-+      }, {
-+              /* Compressed formats */
-               .fourcc                 = V4L2_PIX_FMT_H264,
-               .depth                  = 0,
-               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-@@ -212,30 +311,22 @@ static struct bcm2835_codec_fmt encoded_
-               .depth                  = 0,
-               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-               .mmal_fmt               = MMAL_ENCODING_MP4V,
--              .decode_only            = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_H263,
-               .depth                  = 0,
-               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-               .mmal_fmt               = MMAL_ENCODING_H263,
--              .decode_only            = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_MPEG2,
-               .depth                  = 0,
-               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-               .mmal_fmt               = MMAL_ENCODING_MP2V,
--              .decode_only            = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_VP8,
-               .depth                  = 0,
-               .flags                  = V4L2_FMT_FLAG_COMPRESSED,
-               .mmal_fmt               = MMAL_ENCODING_VP8,
--              .decode_only            = true,
-       },
--      /*
--       * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
--       * support them.
--       */
- };
- struct bcm2835_codec_fmt_list {
-@@ -243,19 +334,6 @@ struct bcm2835_codec_fmt_list {
-       unsigned int num_entries;
- };
--#define RAW_LIST      0
--#define ENCODED_LIST  1
--
--struct bcm2835_codec_fmt_list formats[] = {
--      {
--              .list = raw_formats,
--              .num_entries = ARRAY_SIZE(raw_formats),
--      }, {
--              .list = encoded_formats,
--              .num_entries = ARRAY_SIZE(encoded_formats),
--      },
--};
--
- struct m2m_mmal_buffer {
-       struct v4l2_m2m_buffer  m2m;
-       struct mmal_buffer      mmal;
-@@ -284,52 +362,6 @@ struct bcm2835_codec_q_data {
-       bool                    eos_buffer_in_use;      /* debug only */
- };
--enum {
--      V4L2_M2M_SRC = 0,
--      V4L2_M2M_DST = 1,
--};
--
--static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
--                                                           bool capture)
--{
--      return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
--}
--
--static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
--{
--      return &get_format_list(decode, capture)->list[0];
--}
--
--static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
--                                           bool capture)
--{
--      struct bcm2835_codec_fmt *fmt;
--      unsigned int k;
--      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
--
--      for (k = 0; k < fmts->num_entries; k++) {
--              fmt = &fmts->list[k];
--              if (fmt->fourcc == f->fmt.pix.pixelformat)
--                      break;
--      }
--
--      /*
--       * Some compressed formats are only supported for decoding, not
--       * encoding.
--       */
--      if (!decode && fmts->list[k].decode_only)
--              return NULL;
--
--      /* Some pixel formats are only supported for encoding, not decoding. */
--      if (decode && fmts->list[k].encode_only)
--              return NULL;
--
--      if (k == fmts->num_entries)
--              return NULL;
--
--      return &fmts->list[k];
--}
--
- struct bcm2835_codec_dev {
-       struct platform_device *pdev;
-@@ -342,6 +374,9 @@ struct bcm2835_codec_dev {
-       /* allocated mmal instance and components */
-       bool                    decode;  /* Is this instance a decoder? */
-+      /* The list of formats supported on input and output queues. */
-+      struct bcm2835_codec_fmt_list   supported_fmts[2];
-+
-       struct vchiq_mmal_instance      *instance;
-       struct v4l2_m2m_dev     *m2m_dev;
-@@ -374,8 +409,59 @@ struct bcm2835_codec_ctx {
- struct bcm2835_codec_driver {
-       struct bcm2835_codec_dev *encode;
-       struct bcm2835_codec_dev *decode;
-+      struct bcm2835_codec_dev *isp;
-+};
-+
-+enum {
-+      V4L2_M2M_SRC = 0,
-+      V4L2_M2M_DST = 1,
- };
-+static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
-+{
-+      unsigned int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
-+              if (supported_formats[i].mmal_fmt == mmal_fmt)
-+                      return &supported_formats[i];
-+      }
-+      return NULL;
-+}
-+
-+static inline
-+struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
-+                                             bool capture)
-+{
-+      return &dev->supported_fmts[capture ? 1 : 0];
-+}
-+
-+static
-+struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
-+                                           bool capture)
-+{
-+      return &dev->supported_fmts[capture ? 1 : 0].list[0];
-+}
-+
-+static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
-+                                           struct bcm2835_codec_dev *dev,
-+                                           bool capture)
-+{
-+      struct bcm2835_codec_fmt *fmt;
-+      unsigned int k;
-+      struct bcm2835_codec_fmt_list *fmts =
-+                                      &dev->supported_fmts[capture ? 1 : 0];
-+
-+      for (k = 0; k < fmts->num_entries; k++) {
-+              fmt = &fmts->list[k];
-+              if (fmt->fourcc == f->fmt.pix.pixelformat)
-+                      break;
-+      }
-+      if (k == fmts->num_entries)
-+              return NULL;
-+
-+      return &fmts->list[k];
-+}
-+
- static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
- {
-       return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
-@@ -456,7 +542,6 @@ static inline unsigned int get_bytesperl
- }
- static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
--                                 bool decode,
-                                  struct bcm2835_codec_q_data *q_data,
-                                  struct vchiq_mmal_port *port)
- {
-@@ -473,7 +558,7 @@ static void setup_mmal_port_format(struc
-               port->es.video.frame_rate.den = 1;
-       } else {
-               /* Compressed format - leave resolution as 0 for decode */
--              if (decode) {
-+              if (ctx->dev->decode) {
-                       port->es.video.width = 0;
-                       port->es.video.height = 0;
-                       port->es.video.crop.width = 0;
-@@ -802,22 +887,15 @@ static int vidioc_querycap(struct file *
-       return 0;
- }
--static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
-+static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
-+                  bool capture)
- {
-       struct bcm2835_codec_fmt *fmt;
--      struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
-+      struct bcm2835_codec_fmt_list *fmts =
-+                                      get_format_list(ctx->dev, capture);
-       if (f->index < fmts->num_entries) {
-               /* Format found */
--              /* Check format isn't a decode only format when encoding */
--              if (!decode &&
--                  fmts->list[f->index].decode_only)
--                      return -EINVAL;
--              /* Check format isn't a decode only format when encoding */
--              if (decode &&
--                  fmts->list[f->index].encode_only)
--                      return -EINVAL;
--
-               fmt = &fmts->list[f->index];
-               f->pixelformat = fmt->fourcc;
-               f->flags = fmt->flags;
-@@ -833,7 +911,7 @@ static int vidioc_enum_fmt_vid_cap(struc
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      return enum_fmt(f, ctx->dev->decode, true);
-+      return enum_fmt(f, ctx, true);
- }
- static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
-@@ -841,7 +919,7 @@ static int vidioc_enum_fmt_vid_out(struc
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      return enum_fmt(f, ctx->dev->decode, false);
-+      return enum_fmt(f, ctx, false);
- }
- static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
-@@ -933,11 +1011,11 @@ static int vidioc_try_fmt_vid_cap(struct
-       struct bcm2835_codec_fmt *fmt;
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      fmt = find_format(f, ctx->dev->decode, true);
-+      fmt = find_format(f, ctx->dev, true);
-       if (!fmt) {
--              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
-                                                           true)->fourcc;
--              fmt = find_format(f, ctx->dev->decode, true);
-+              fmt = find_format(f, ctx->dev, true);
-       }
-       return vidioc_try_fmt(f, fmt);
-@@ -949,11 +1027,11 @@ static int vidioc_try_fmt_vid_out(struct
-       struct bcm2835_codec_fmt *fmt;
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      fmt = find_format(f, ctx->dev->decode, false);
-+      fmt = find_format(f, ctx->dev, false);
-       if (!fmt) {
--              f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
-                                                           false)->fourcc;
--              fmt = find_format(f, ctx->dev->decode, false);
-+              fmt = find_format(f, ctx->dev, false);
-       }
-       if (!f->fmt.pix.colorspace)
-@@ -988,7 +1066,7 @@ static int vidioc_s_fmt(struct bcm2835_c
-               return -EBUSY;
-       }
--      q_data->fmt = find_format(f, ctx->dev->decode,
-+      q_data->fmt = find_format(f, ctx->dev,
-                                 f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       q_data->crop_width = f->fmt.pix.width;
-       q_data->height = f->fmt.pix.height;
-@@ -1041,7 +1119,7 @@ static int vidioc_s_fmt(struct bcm2835_c
-       if (!port)
-               return 0;
--      setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
-+      setup_mmal_port_format(ctx, q_data, port);
-       ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
-       if (ret) {
-               v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
-@@ -1064,8 +1142,7 @@ static int vidioc_s_fmt(struct bcm2835_c
-               struct bcm2835_codec_q_data *q_data_dst =
-                                               &ctx->q_data[V4L2_M2M_DST];
--              setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
--                                     port_dst);
-+              setup_mmal_port_format(ctx, q_data_dst, port_dst);
-               ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
-               if (ret) {
-                       v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
-@@ -1636,10 +1713,10 @@ static int bcm2835_codec_create_componen
-                                     MMAL_PARAMETER_ZERO_COPY, &enable,
-                                     sizeof(enable));
--      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
-+      setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
-                              &ctx->component->input[0]);
--      setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
-+      setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
-                              &ctx->component->output[0]);
-       ret = vchiq_mmal_port_set_format(dev->instance,
-@@ -2025,8 +2102,8 @@ static int bcm2835_codec_open(struct fil
-               goto open_unlock;
-       }
--      ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
--      ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
-+      ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
-+      ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
-       if (dev->decode) {
-               /*
-                * Input width and height are irrelevant as they will be defined
-@@ -2209,13 +2286,130 @@ static const struct v4l2_m2m_ops m2m_ops
-       .job_abort      = job_abort,
- };
-+/* 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
-+ * overhead on that.
-+ */
-+#define MAX_SUPPORTED_ENCODINGS 40
-+
-+/* Populate dev->supported_fmts with the formats supported by those ports. */
-+static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
-+{
-+      struct bcm2835_codec_fmt *list;
-+      struct vchiq_mmal_component *component;
-+      u32 fourccs[MAX_SUPPORTED_ENCODINGS];
-+      u32 param_size = sizeof(fourccs);
-+      unsigned int i, j, num_encodings;
-+      int ret;
-+
-+      ret = vchiq_mmal_component_init(dev->instance,
-+                                      dev->decode ?
-+                                              "ril.video_decode" :
-+                                              "ril.video_encode",
-+                                      &component);
-+      if (ret < 0) {
-+              v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
-+                       __func__);
-+              return -ENOMEM;
-+      }
-+
-+      ret = vchiq_mmal_port_parameter_get(dev->instance,
-+                                          &component->input[0],
-+                                          MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+                                          &fourccs,
-+                                          &param_size);
-+
-+      if (ret) {
-+              if (ret == MMAL_MSG_STATUS_ENOSPC) {
-+                      v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
-+                               __func__);
-+                      num_encodings = MAX_SUPPORTED_ENCODINGS;
-+              } else {
-+                      v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
-+                               __func__, ret);
-+                      ret = -EINVAL;
-+                      goto destroy_component;
-+              }
-+      } else {
-+              num_encodings = param_size / sizeof(u32);
-+      }
-+
-+      /* Assume at this stage that all encodings will be supported in V4L2.
-+       * Any that aren't supported will waste a very small amount of memory.
-+       */
-+      list = devm_kzalloc(&dev->pdev->dev,
-+                          sizeof(struct bcm2835_codec_fmt) * num_encodings,
-+                          GFP_KERNEL);
-+      if (!list) {
-+              ret = -ENOMEM;
-+              goto destroy_component;
-+      }
-+      dev->supported_fmts[0].list = list;
-+
-+      for (i = 0, j = 0; i < num_encodings; i++) {
-+              const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
-+
-+              if (fmt) {
-+                      list[j] = *fmt;
-+                      j++;
-+              }
-+      }
-+      dev->supported_fmts[0].num_entries = j;
-+
-+      param_size = sizeof(fourccs);
-+      ret = vchiq_mmal_port_parameter_get(dev->instance,
-+                                          &component->output[0],
-+                                          MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+                                          &fourccs,
-+                                          &param_size);
-+
-+      if (ret) {
-+              if (ret == MMAL_MSG_STATUS_ENOSPC) {
-+                      v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
-+                               __func__);
-+                      num_encodings = MAX_SUPPORTED_ENCODINGS;
-+              } else {
-+                      ret = -EINVAL;
-+                      goto destroy_component;
-+              }
-+      } else {
-+              num_encodings = param_size / sizeof(u32);
-+      }
-+      /* Assume at this stage that all encodings will be supported in V4L2. */
-+      list = devm_kzalloc(&dev->pdev->dev,
-+                          sizeof(struct bcm2835_codec_fmt) * num_encodings,
-+                          GFP_KERNEL);
-+      if (!list) {
-+              ret = -ENOMEM;
-+              goto destroy_component;
-+      }
-+      dev->supported_fmts[1].list = list;
-+
-+      for (i = 0, j = 0; i < num_encodings; i++) {
-+              const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
-+
-+              if (fmt) {
-+                      list[j] = *fmt;
-+                      j++;
-+              }
-+      }
-+      dev->supported_fmts[1].num_entries = j;
-+
-+      ret = 0;
-+
-+destroy_component:
-+      vchiq_mmal_component_finalise(dev->instance, component);
-+
-+      return ret;
-+}
-+
- static int bcm2835_codec_create(struct platform_device *pdev,
-                               struct bcm2835_codec_dev **new_dev,
-                               bool decode)
- {
-       struct bcm2835_codec_dev *dev;
-       struct video_device *vfd;
--      struct vchiq_mmal_instance *instance = NULL;
-       int video_nr;
-       int ret;
-@@ -2227,10 +2421,18 @@ static int bcm2835_codec_create(struct p
-       dev->decode = decode;
--      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-+      ret = vchiq_mmal_init(&dev->instance);
-       if (ret)
-               return ret;
-+      ret = bcm2835_codec_get_supported_fmts(dev);
-+      if (ret)
-+              goto vchiq_finalise;
-+
-+      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-+      if (ret)
-+              goto vchiq_finalise;
-+
-       atomic_set(&dev->num_inst, 0);
-       mutex_init(&dev->dev_mutex);
-@@ -2270,12 +2472,7 @@ static int bcm2835_codec_create(struct p
-               goto err_m2m;
-       }
--      ret = vchiq_mmal_init(&instance);
--      if (ret < 0)
--              goto err_m2m;
--      dev->instance = instance;
--
--      v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
-+      v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
-                 dev->decode ? "decode" : "encode");
-       return 0;
-@@ -2284,7 +2481,8 @@ err_m2m:
-       video_unregister_device(&dev->vfd);
- unreg_dev:
-       v4l2_device_unregister(&dev->v4l2_dev);
--
-+vchiq_finalise:
-+      vchiq_mmal_finalise(dev->instance);
-       return ret;
- }
-@@ -2297,6 +2495,7 @@ static int bcm2835_codec_destroy(struct
-       v4l2_m2m_release(dev->m2m_dev);
-       video_unregister_device(&dev->vfd);
-       v4l2_device_unregister(&dev->v4l2_dev);
-+      vchiq_mmal_finalise(dev->instance);
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0310-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch b/target/linux/brcm2708/patches-4.19/950-0310-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch
deleted file mode 100644 (file)
index df59acd..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-From 7afce6566802bcaa468f92b9e06da8b899161128 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 14:07:52 +0000
-Subject: [PATCH] staging: bcm2835_codec: Add support for the ISP as an
- M2M device
-
-The MMAL ISP component can also use this same V4L2 wrapper to
-provide a M2M format conversion and resizer.
-Instantiate 3 V4L2 devices now, one for each of decode, encode,
-and isp.
-The ISP currently doesn't expose any controls via V4L2, but this
-can be extended in the future.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 132 ++++++++++++------
- 1 file changed, 92 insertions(+), 40 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -54,10 +54,26 @@ static int encode_video_nr = 11;
- module_param(encode_video_nr, int, 0644);
- MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
-+static int isp_video_nr = 12;
-+module_param(isp_video_nr, int, 0644);
-+MODULE_PARM_DESC(isp_video_nr, "isp video device number");
-+
- static unsigned int debug;
- module_param(debug, uint, 0644);
- MODULE_PARM_DESC(debug, "activates debug info (0-3)");
-+enum bcm2835_codec_role {
-+      DECODE,
-+      ENCODE,
-+      ISP,
-+};
-+
-+static const char * const components[] = {
-+      "ril.video_decode",
-+      "ril.video_encode",
-+      "ril.isp",
-+};
-+
- #define MIN_W         32
- #define MIN_H         32
- #define MAX_W         1920
-@@ -373,7 +389,7 @@ struct bcm2835_codec_dev {
-       atomic_t                num_inst;
-       /* allocated mmal instance and components */
--      bool                    decode;  /* Is this instance a decoder? */
-+      enum bcm2835_codec_role role;
-       /* The list of formats supported on input and output queues. */
-       struct bcm2835_codec_fmt_list   supported_fmts[2];
-@@ -558,7 +574,7 @@ static void setup_mmal_port_format(struc
-               port->es.video.frame_rate.den = 1;
-       } else {
-               /* Compressed format - leave resolution as 0 for decode */
--              if (ctx->dev->decode) {
-+              if (ctx->dev->role == DECODE) {
-                       port->es.video.width = 0;
-                       port->es.video.height = 0;
-                       port->es.video.crop.width = 0;
-@@ -1089,7 +1105,8 @@ static int vidioc_s_fmt(struct bcm2835_c
-       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
-                q_data->bytesperline, q_data->sizeimage);
--      if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
-+      if (ctx->dev->role == DECODE &&
-+          q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
-           f->fmt.pix.width && f->fmt.pix.height) {
-               /*
-                * On the decoder, if provided with a resolution on the input
-@@ -1188,7 +1205,8 @@ static int vidioc_g_selection(struct fil
-       bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
-                                                               true : false;
--      if (capture_queue ^ ctx->dev->decode)
-+      if ((ctx->dev->role == DECODE && !capture_queue) ||
-+          (ctx->dev->role == ENCODE && capture_queue))
-               /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
-               return -EINVAL;
-@@ -1196,7 +1214,8 @@ static int vidioc_g_selection(struct fil
-       if (!q_data)
-               return -EINVAL;
--      if (ctx->dev->decode) {
-+      switch (ctx->dev->role) {
-+      case DECODE:
-               switch (s->target) {
-               case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-               case V4L2_SEL_TGT_COMPOSE:
-@@ -1214,7 +1233,8 @@ static int vidioc_g_selection(struct fil
-               default:
-                       return -EINVAL;
-               }
--      } else {
-+              break;
-+      case ENCODE:
-               switch (s->target) {
-               case V4L2_SEL_TGT_CROP_DEFAULT:
-               case V4L2_SEL_TGT_CROP_BOUNDS:
-@@ -1232,6 +1252,9 @@ static int vidioc_g_selection(struct fil
-               default:
-                       return -EINVAL;
-               }
-+              break;
-+      case ISP:
-+              break;
-       }
-       return 0;
-@@ -1249,7 +1272,8 @@ static int vidioc_s_selection(struct fil
-                __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
-                s->r.width, s->r.height);
--      if (capture_queue ^ ctx->dev->decode)
-+      if ((ctx->dev->role == DECODE && !capture_queue) ||
-+          (ctx->dev->role == ENCODE && capture_queue))
-               /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
-               return -EINVAL;
-@@ -1257,7 +1281,8 @@ static int vidioc_s_selection(struct fil
-       if (!q_data)
-               return -EINVAL;
--      if (ctx->dev->decode) {
-+      switch (ctx->dev->role) {
-+      case DECODE:
-               switch (s->target) {
-               case V4L2_SEL_TGT_COMPOSE:
-                       /* Accept cropped image */
-@@ -1272,7 +1297,8 @@ static int vidioc_s_selection(struct fil
-               default:
-                       return -EINVAL;
-               }
--      } else {
-+              break;
-+      case ENCODE:
-               switch (s->target) {
-               case V4L2_SEL_TGT_CROP:
-                       /* Only support crop from (0,0) */
-@@ -1287,6 +1313,9 @@ static int vidioc_s_selection(struct fil
-               default:
-                       return -EINVAL;
-               }
-+              break;
-+      case ISP:
-+              break;
-       }
-       return 0;
-@@ -1490,7 +1519,7 @@ static int vidioc_try_decoder_cmd(struct
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      if (!ctx->dev->decode)
-+      if (ctx->dev->role != DECODE)
-               return -EINVAL;
-       switch (cmd->cmd) {
-@@ -1564,7 +1593,7 @@ static int vidioc_try_encoder_cmd(struct
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      if (ctx->dev->decode)
-+      if (ctx->dev->role != ENCODE)
-               return -EINVAL;
-       switch (cmd->cmd) {
-@@ -1697,12 +1726,11 @@ static int bcm2835_codec_create_componen
-       unsigned int enable = 1;
-       int ret;
--      ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
--                                      "ril.video_decode" : "ril.video_encode",
-+      ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
-                                       &ctx->component);
-       if (ret < 0) {
--              v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
--                       __func__, dev->decode ? "decode" : "encode");
-+              v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
-+                       __func__, components[dev->role]);
-               return -ENOMEM;
-       }
-@@ -1729,13 +1757,7 @@ static int bcm2835_codec_create_componen
-       if (ret < 0)
-               goto destroy_component;
--      if (dev->decode) {
--              if (ctx->q_data[V4L2_M2M_DST].sizeimage <
--                      ctx->component->output[0].minimum_buffer.size)
--                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
--                               ctx->q_data[V4L2_M2M_DST].sizeimage,
--                               ctx->component->output[0].minimum_buffer.size);
--      } else {
-+      if (dev->role == ENCODE) {
-               if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
-                       ctx->component->output[0].minimum_buffer.size)
-                       v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-@@ -1744,6 +1766,12 @@ static int bcm2835_codec_create_componen
-               /* Now we have a component we can set all the ctrls */
-               bcm2835_codec_set_ctrls(ctx);
-+      } else {
-+              if (ctx->q_data[V4L2_M2M_DST].sizeimage <
-+                      ctx->component->output[0].minimum_buffer.size)
-+                      v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-+                               ctx->q_data[V4L2_M2M_DST].sizeimage,
-+                               ctx->component->output[0].minimum_buffer.size);
-       }
-       return 0;
-@@ -2090,8 +2118,6 @@ static int bcm2835_codec_open(struct fil
-       struct v4l2_ctrl_handler *hdl;
-       int rc = 0;
--      v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
--               dev->decode ? "decode" : "encode");
-       if (mutex_lock_interruptible(&dev->dev_mutex)) {
-               v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
-               return -ERESTARTSYS;
-@@ -2104,7 +2130,8 @@ static int bcm2835_codec_open(struct fil
-       ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
-       ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
--      if (dev->decode) {
-+      switch (dev->role) {
-+      case DECODE:
-               /*
-                * Input width and height are irrelevant as they will be defined
-                * by the bitstream not the format. Required by V4L2 though.
-@@ -2126,7 +2153,8 @@ static int bcm2835_codec_open(struct fil
-                       get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
-                                     ctx->q_data[V4L2_M2M_DST].height,
-                                     ctx->q_data[V4L2_M2M_DST].fmt);
--      } else {
-+              break;
-+      case ENCODE:
-               ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-               ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-               ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-@@ -2144,6 +2172,9 @@ static int bcm2835_codec_open(struct fil
-               ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-               ctx->q_data[V4L2_M2M_DST].sizeimage =
-                                               DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+              break;
-+      case ISP:
-+              break;
-       }
-       ctx->colorspace = V4L2_COLORSPACE_REC709;
-@@ -2154,7 +2185,7 @@ static int bcm2835_codec_open(struct fil
-       file->private_data = &ctx->fh;
-       ctx->dev = dev;
-       hdl = &ctx->hdl;
--      if (!dev->decode) {
-+      if (dev->role == ENCODE) {
-               /* Encode controls */
-               v4l2_ctrl_handler_init(hdl, 6);
-@@ -2303,14 +2334,11 @@ static int bcm2835_codec_get_supported_f
-       unsigned int i, j, num_encodings;
-       int ret;
--      ret = vchiq_mmal_component_init(dev->instance,
--                                      dev->decode ?
--                                              "ril.video_decode" :
--                                              "ril.video_encode",
-+      ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
-                                       &component);
-       if (ret < 0) {
--              v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
--                       __func__);
-+              v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
-+                       __func__, components[dev->role]);
-               return -ENOMEM;
-       }
-@@ -2406,12 +2434,13 @@ destroy_component:
- static int bcm2835_codec_create(struct platform_device *pdev,
-                               struct bcm2835_codec_dev **new_dev,
--                              bool decode)
-+                              enum bcm2835_codec_role role)
- {
-       struct bcm2835_codec_dev *dev;
-       struct video_device *vfd;
-       int video_nr;
-       int ret;
-+      const static char *roles[] = {"decode", "encode", "isp"};
-       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-@@ -2419,7 +2448,7 @@ static int bcm2835_codec_create(struct p
-       dev->pdev = pdev;
--      dev->decode = decode;
-+      dev->role = role;
-       ret = vchiq_mmal_init(&dev->instance);
-       if (ret)
-@@ -2441,14 +2470,27 @@ static int bcm2835_codec_create(struct p
-       vfd->lock = &dev->dev_mutex;
-       vfd->v4l2_dev = &dev->v4l2_dev;
--      if (dev->decode) {
-+      switch (role) {
-+      case DECODE:
-               v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-               video_nr = decode_video_nr;
--      } else {
-+              break;
-+      case ENCODE:
-               v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-               video_nr = encode_video_nr;
-+              break;
-+      case ISP:
-+              v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
-+              v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-+              v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-+              v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-+              video_nr = isp_video_nr;
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              goto unreg_dev;
-       }
-       ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-@@ -2473,7 +2515,7 @@ static int bcm2835_codec_create(struct p
-       }
-       v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
--                dev->decode ? "decode" : "encode");
-+                roles[role]);
-       return 0;
- err_m2m:
-@@ -2509,11 +2551,15 @@ static int bcm2835_codec_probe(struct pl
-       if (!drv)
-               return -ENOMEM;
--      ret = bcm2835_codec_create(pdev, &drv->encode, false);
-+      ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
-       if (ret)
-               goto out;
--      ret = bcm2835_codec_create(pdev, &drv->decode, true);
-+      ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
-+      if (ret)
-+              goto out;
-+
-+      ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
-       if (ret)
-               goto out;
-@@ -2526,6 +2572,10 @@ out:
-               bcm2835_codec_destroy(drv->encode);
-               drv->encode = NULL;
-       }
-+      if (drv->decode) {
-+              bcm2835_codec_destroy(drv->decode);
-+              drv->decode = NULL;
-+      }
-       return ret;
- }
-@@ -2533,6 +2583,8 @@ static int bcm2835_codec_remove(struct p
- {
-       struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
-+      bcm2835_codec_destroy(drv->isp);
-+
-       bcm2835_codec_destroy(drv->encode);
-       bcm2835_codec_destroy(drv->decode);
diff --git a/target/linux/brcm2708/patches-4.19/950-0310-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch b/target/linux/brcm2708/patches-4.19/950-0310-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch
new file mode 100644 (file)
index 0000000..7e3373e
--- /dev/null
@@ -0,0 +1,186 @@
+From 0df32e2f563123166c20677f022d4a0f825c5df2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 15 Feb 2019 11:38:45 +0000
+Subject: [PATCH] staging: bcm2835_codec: Fix handling of
+ VB2_MEMORY_DMABUF buffers
+
+If the queue is configured as VB2_MEMORY_DMABUF then vb2_core_expbuf
+fails as it ensures the queue is defined as VB2_MEMORY_MMAP.
+
+Correct the handling so that we unmap the buffer from vcsm and the
+VPU on cleanup, and then correctly get the dma buf of the new buffer.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 80 +++++++++++++------
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 21 +++--
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  2 +
+ 3 files changed, 73 insertions(+), 30 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1852,6 +1852,18 @@ static int bcm2835_codec_queue_setup(str
+       return 0;
+ }
++static int bcm2835_codec_mmal_buf_cleanup(struct mmal_buffer *mmal_buf)
++{
++      mmal_vchi_buffer_cleanup(mmal_buf);
++
++      if (mmal_buf->dma_buf) {
++              dma_buf_put(mmal_buf->dma_buf);
++              mmal_buf->dma_buf = NULL;
++      }
++
++      return 0;
++}
++
+ static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
+ {
+       struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+@@ -1880,6 +1892,7 @@ static int bcm2835_codec_buf_prepare(str
+                                                  vb);
+       struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
+                                                  m2m);
++      struct dma_buf *dma_buf;
+       int ret;
+       v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
+@@ -1906,20 +1919,48 @@ static int bcm2835_codec_buf_prepare(str
+       if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
+               vb2_set_plane_payload(vb, 0, q_data->sizeimage);
+-      /*
+-       * We want to do this at init, but vb2_core_expbuf checks that the
+-       * index < q->num_buffers, and q->num_buffers only gets updated once
+-       * all the buffers are allocated.
+-       */
+-      if (!buf->mmal.dma_buf) {
+-              ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
+-                                           vb->vb2_queue->type, vb->index, 0,
+-                                           O_CLOEXEC, &buf->mmal.dma_buf);
+-              if (ret)
+-                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
+-                               __func__, vb->index, ret);
+-      } else {
++      switch (vb->memory) {
++      case VB2_MEMORY_DMABUF:
++              dma_buf = dma_buf_get(vb->planes[0].m.fd);
++
++              if (dma_buf != buf->mmal.dma_buf) {
++                      /* dmabuf either hasn't already been mapped, or it has
++                       * changed.
++                       */
++                      if (buf->mmal.dma_buf) {
++                              v4l2_err(&ctx->dev->v4l2_dev,
++                                       "%s Buffer changed - why did the core not call cleanup?\n",
++                                       __func__);
++                              bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
++                      }
++
++                      buf->mmal.dma_buf = dma_buf;
++              }
+               ret = 0;
++              break;
++      case VB2_MEMORY_MMAP:
++              /*
++               * We want to do this at init, but vb2_core_expbuf checks that
++               * the index < q->num_buffers, and q->num_buffers only gets
++               * updated once all the buffers are allocated.
++               */
++              if (!buf->mmal.dma_buf) {
++                      ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
++                                                   vb->vb2_queue->type,
++                                                   vb->index, 0,
++                                                   O_CLOEXEC,
++                                                   &buf->mmal.dma_buf);
++                      if (ret)
++                              v4l2_err(&ctx->dev->v4l2_dev,
++                                       "%s: Failed to expbuf idx %d, ret %d\n",
++                                       __func__, vb->index, ret);
++              } else {
++                      ret = 0;
++              }
++              break;
++      default:
++              ret = -EINVAL;
++              break;
+       }
+       return ret;
+@@ -1948,12 +1989,7 @@ static void bcm2835_codec_buffer_cleanup
+       v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
+                __func__, ctx, vb);
+-      mmal_vchi_buffer_cleanup(&buf->mmal);
+-
+-      if (buf->mmal.dma_buf) {
+-              dma_buf_put(buf->mmal.dma_buf);
+-              buf->mmal.dma_buf = NULL;
+-      }
++      bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
+ }
+ static int bcm2835_codec_start_streaming(struct vb2_queue *q,
+@@ -2067,11 +2103,7 @@ static void bcm2835_codec_stop_streaming
+               m2m = container_of(vb2, struct v4l2_m2m_buffer, vb);
+               buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
+-              mmal_vchi_buffer_cleanup(&buf->mmal);
+-              if (buf->mmal.dma_buf) {
+-                      dma_buf_put(buf->mmal.dma_buf);
+-                      buf->mmal.dma_buf = NULL;
+-              }
++              bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
+       }
+       /* If both ports disabled, then disable the component */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1785,13 +1785,9 @@ int mmal_vchi_buffer_init(struct vchiq_m
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
++int mmal_vchi_buffer_unmap(struct mmal_buffer *buf)
+ {
+-      struct mmal_msg_context *msg_context = buf->msg_context;
+-
+-      if (msg_context)
+-              release_msg_context(msg_context);
+-      buf->msg_context = NULL;
++      int ret = 0;
+       if (buf->vcsm_handle) {
+               int ret;
+@@ -1803,6 +1799,19 @@ int mmal_vchi_buffer_cleanup(struct mmal
+                       pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
+               buf->vcsm_handle = 0;
+       }
++      return ret;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_unmap);
++
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
++{
++      struct mmal_msg_context *msg_context = buf->msg_context;
++
++      if (msg_context)
++              release_msg_context(msg_context);
++      buf->msg_context = NULL;
++
++      mmal_vchi_buffer_unmap(buf);
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -167,6 +167,8 @@ int vchiq_mmal_submit_buffer(struct vchi
+                            struct vchiq_mmal_port *port,
+                            struct mmal_buffer *buf);
++int mmal_vchi_buffer_unmap(struct mmal_buffer *buf);
++
+ int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+                         struct mmal_buffer *buf);
+ int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
diff --git a/target/linux/brcm2708/patches-4.19/950-0311-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch b/target/linux/brcm2708/patches-4.19/950-0311-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch
deleted file mode 100644 (file)
index fcdcc4a..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-From a126fcc4ff38718e2e714fbb78db3ca1c4f8e564 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 15 Feb 2019 11:36:14 +0000
-Subject: [PATCH] staging: bcm2835_codec: Add an option for ignoring
- Bayer formats.
-
-This is a workaround for GStreamer currently not identifying Bayer
-as a raw format, therefore any device that supports it does not
-match the criteria for v4l2convert.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 29 ++++++++++++++++++-
- 1 file changed, 28 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
-@@ -58,6 +58,15 @@ static int isp_video_nr = 12;
- module_param(isp_video_nr, int, 0644);
- MODULE_PARM_DESC(isp_video_nr, "isp video device number");
-+/*
-+ * Workaround for GStreamer v4l2convert component not considering Bayer formats
-+ * as raw, and therefore not considering a V4L2 device that supports them as
-+ * as a suitable candidate.
-+ */
-+static bool disable_bayer;
-+module_param(disable_bayer, bool, 0644);
-+MODULE_PARM_DESC(disable_bayer, "Disable support for Bayer formats");
-+
- static unsigned int debug;
- module_param(debug, uint, 0644);
- MODULE_PARM_DESC(debug, "activates debug info (0-3)");
-@@ -105,6 +114,7 @@ struct bcm2835_codec_fmt {
-       u32     flags;
-       u32     mmal_fmt;
-       int     size_multiplier_x2;
-+      bool    is_bayer;
- };
- static const struct bcm2835_codec_fmt supported_formats[] = {
-@@ -203,6 +213,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB8,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SBGGR8,
-               .depth                  = 8,
-@@ -210,6 +221,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR8,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGRBG8,
-               .depth                  = 8,
-@@ -217,6 +229,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG8,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGBRG8,
-               .depth                  = 8,
-@@ -224,6 +237,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG8,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               /* 10 bit */
-               .fourcc                 = V4L2_PIX_FMT_SRGGB10P,
-@@ -232,6 +246,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB10P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SBGGR10P,
-               .depth                  = 10,
-@@ -239,6 +254,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR10P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGRBG10P,
-               .depth                  = 10,
-@@ -246,6 +262,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG10P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGBRG10P,
-               .depth                  = 10,
-@@ -253,6 +270,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG10P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               /* 12 bit */
-               .fourcc                 = V4L2_PIX_FMT_SRGGB12P,
-@@ -261,6 +279,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB12P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SBGGR12P,
-               .depth                  = 12,
-@@ -268,6 +287,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR12P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGRBG12P,
-               .depth                  = 12,
-@@ -275,6 +295,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG12P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGBRG12P,
-               .depth                  = 12,
-@@ -282,6 +303,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG12P,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               /* 16 bit */
-               .fourcc                 = V4L2_PIX_FMT_SRGGB16,
-@@ -290,6 +312,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB16,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SBGGR16,
-               .depth                  = 16,
-@@ -297,6 +320,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR16,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGRBG16,
-               .depth                  = 16,
-@@ -304,6 +328,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG16,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               .fourcc                 = V4L2_PIX_FMT_SGBRG16,
-               .depth                  = 16,
-@@ -311,6 +336,7 @@ static const struct bcm2835_codec_fmt su
-               .flags                  = 0,
-               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG16,
-               .size_multiplier_x2     = 2,
-+              .is_bayer               = true,
-       }, {
-               /* Compressed formats */
-               .fourcc                 = V4L2_PIX_FMT_H264,
-@@ -438,7 +464,8 @@ static const struct bcm2835_codec_fmt *g
-       unsigned int i;
-       for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
--              if (supported_formats[i].mmal_fmt == mmal_fmt)
-+              if (supported_formats[i].mmal_fmt == mmal_fmt &&
-+                  (!disable_bayer || !supported_formats[i].is_bayer))
-                       return &supported_formats[i];
-       }
-       return NULL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0311-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch b/target/linux/brcm2708/patches-4.19/950-0311-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch
new file mode 100644 (file)
index 0000000..98162a0
--- /dev/null
@@ -0,0 +1,56 @@
+From f51a6ed76f6a59e65fe06d1f2e06e824f38ae604 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 18 Feb 2019 15:52:29 +0000
+Subject: [PATCH] staging: mmal-vchiq: Update mmal_parameters.h with
+ recently defined params
+
+mmal_parameters.h hasn't been updated to reflect additions made
+over the last few years. Update it to reflect the currently
+supported parameters.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vchiq-mmal/mmal-parameters.h              | 32 ++++++++++++++++++-
+ 1 file changed, 31 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
+@@ -580,7 +580,37 @@ enum mmal_parameter_video_type {
+       MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
+       /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
++      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
++
++      /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_SEI_ENABLE,
++
++      /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS,
++
++      /**< Take a @ref MMAL_PARAMETER_VIDEO_RENDER_STATS_T. */
++      MMAL_PARAMETER_VIDEO_RENDER_STATS,
++
++      /**< Take a @ref MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T. */
++      MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
++
++      /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS,
++
++      /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
++
++      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
++
++      /**< Takes a @ref MMAL_PARAMETER_SOURCE_PATTERN_T */
++      MMAL_PARAMETER_VIDEO_SOURCE_PATTERN,
++
++      /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_SEPARATE_NAL_BUFS,
++
++      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAME_LENGTH,
+ };
+ /** Valid mirror modes */
diff --git a/target/linux/brcm2708/patches-4.19/950-0312-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch b/target/linux/brcm2708/patches-4.19/950-0312-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch
deleted file mode 100644 (file)
index 7e3373e..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-From 0df32e2f563123166c20677f022d4a0f825c5df2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 15 Feb 2019 11:38:45 +0000
-Subject: [PATCH] staging: bcm2835_codec: Fix handling of
- VB2_MEMORY_DMABUF buffers
-
-If the queue is configured as VB2_MEMORY_DMABUF then vb2_core_expbuf
-fails as it ensures the queue is defined as VB2_MEMORY_MMAP.
-
-Correct the handling so that we unmap the buffer from vcsm and the
-VPU on cleanup, and then correctly get the dma buf of the new buffer.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 80 +++++++++++++------
- .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 21 +++--
- .../vc04_services/vchiq-mmal/mmal-vchiq.h     |  2 +
- 3 files changed, 73 insertions(+), 30 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1852,6 +1852,18 @@ static int bcm2835_codec_queue_setup(str
-       return 0;
- }
-+static int bcm2835_codec_mmal_buf_cleanup(struct mmal_buffer *mmal_buf)
-+{
-+      mmal_vchi_buffer_cleanup(mmal_buf);
-+
-+      if (mmal_buf->dma_buf) {
-+              dma_buf_put(mmal_buf->dma_buf);
-+              mmal_buf->dma_buf = NULL;
-+      }
-+
-+      return 0;
-+}
-+
- static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
- {
-       struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-@@ -1880,6 +1892,7 @@ static int bcm2835_codec_buf_prepare(str
-                                                  vb);
-       struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
-                                                  m2m);
-+      struct dma_buf *dma_buf;
-       int ret;
-       v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
-@@ -1906,20 +1919,48 @@ static int bcm2835_codec_buf_prepare(str
-       if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
-               vb2_set_plane_payload(vb, 0, q_data->sizeimage);
--      /*
--       * We want to do this at init, but vb2_core_expbuf checks that the
--       * index < q->num_buffers, and q->num_buffers only gets updated once
--       * all the buffers are allocated.
--       */
--      if (!buf->mmal.dma_buf) {
--              ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
--                                           vb->vb2_queue->type, vb->index, 0,
--                                           O_CLOEXEC, &buf->mmal.dma_buf);
--              if (ret)
--                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
--                               __func__, vb->index, ret);
--      } else {
-+      switch (vb->memory) {
-+      case VB2_MEMORY_DMABUF:
-+              dma_buf = dma_buf_get(vb->planes[0].m.fd);
-+
-+              if (dma_buf != buf->mmal.dma_buf) {
-+                      /* dmabuf either hasn't already been mapped, or it has
-+                       * changed.
-+                       */
-+                      if (buf->mmal.dma_buf) {
-+                              v4l2_err(&ctx->dev->v4l2_dev,
-+                                       "%s Buffer changed - why did the core not call cleanup?\n",
-+                                       __func__);
-+                              bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
-+                      }
-+
-+                      buf->mmal.dma_buf = dma_buf;
-+              }
-               ret = 0;
-+              break;
-+      case VB2_MEMORY_MMAP:
-+              /*
-+               * We want to do this at init, but vb2_core_expbuf checks that
-+               * the index < q->num_buffers, and q->num_buffers only gets
-+               * updated once all the buffers are allocated.
-+               */
-+              if (!buf->mmal.dma_buf) {
-+                      ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
-+                                                   vb->vb2_queue->type,
-+                                                   vb->index, 0,
-+                                                   O_CLOEXEC,
-+                                                   &buf->mmal.dma_buf);
-+                      if (ret)
-+                              v4l2_err(&ctx->dev->v4l2_dev,
-+                                       "%s: Failed to expbuf idx %d, ret %d\n",
-+                                       __func__, vb->index, ret);
-+              } else {
-+                      ret = 0;
-+              }
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-       }
-       return ret;
-@@ -1948,12 +1989,7 @@ static void bcm2835_codec_buffer_cleanup
-       v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
-                __func__, ctx, vb);
--      mmal_vchi_buffer_cleanup(&buf->mmal);
--
--      if (buf->mmal.dma_buf) {
--              dma_buf_put(buf->mmal.dma_buf);
--              buf->mmal.dma_buf = NULL;
--      }
-+      bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
- }
- static int bcm2835_codec_start_streaming(struct vb2_queue *q,
-@@ -2067,11 +2103,7 @@ static void bcm2835_codec_stop_streaming
-               m2m = container_of(vb2, struct v4l2_m2m_buffer, vb);
-               buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
--              mmal_vchi_buffer_cleanup(&buf->mmal);
--              if (buf->mmal.dma_buf) {
--                      dma_buf_put(buf->mmal.dma_buf);
--                      buf->mmal.dma_buf = NULL;
--              }
-+              bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
-       }
-       /* If both ports disabled, then disable the component */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1785,13 +1785,9 @@ int mmal_vchi_buffer_init(struct vchiq_m
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
--int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
-+int mmal_vchi_buffer_unmap(struct mmal_buffer *buf)
- {
--      struct mmal_msg_context *msg_context = buf->msg_context;
--
--      if (msg_context)
--              release_msg_context(msg_context);
--      buf->msg_context = NULL;
-+      int ret = 0;
-       if (buf->vcsm_handle) {
-               int ret;
-@@ -1803,6 +1799,19 @@ int mmal_vchi_buffer_cleanup(struct mmal
-                       pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
-               buf->vcsm_handle = 0;
-       }
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(mmal_vchi_buffer_unmap);
-+
-+int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
-+{
-+      struct mmal_msg_context *msg_context = buf->msg_context;
-+
-+      if (msg_context)
-+              release_msg_context(msg_context);
-+      buf->msg_context = NULL;
-+
-+      mmal_vchi_buffer_unmap(buf);
-       return 0;
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -167,6 +167,8 @@ int vchiq_mmal_submit_buffer(struct vchi
-                            struct vchiq_mmal_port *port,
-                            struct mmal_buffer *buf);
-+int mmal_vchi_buffer_unmap(struct mmal_buffer *buf);
-+
- int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
-                         struct mmal_buffer *buf);
- int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
diff --git a/target/linux/brcm2708/patches-4.19/950-0312-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch b/target/linux/brcm2708/patches-4.19/950-0312-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch
new file mode 100644 (file)
index 0000000..5e5f1a7
--- /dev/null
@@ -0,0 +1,44 @@
+From 7f9fd2338e3a9d7b46b6904bbd7f97851e9b3f52 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 18 Feb 2019 15:56:42 +0000
+Subject: [PATCH] staging: bcm2835_codec: Include timing info in SPS
+ headers
+
+Inserting timing information into the VUI block of the SPS is
+optional with the VPU encoder.
+GStreamer appears to require them when using V4L2 M2M, therefore
+set the option to enable them from the encoder.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1785,6 +1785,8 @@ static int bcm2835_codec_create_componen
+               goto destroy_component;
+       if (dev->role == ENCODE) {
++              u32 param = 1;
++
+               if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
+                       ctx->component->output[0].minimum_buffer.size)
+                       v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
+@@ -1793,6 +1795,16 @@ static int bcm2835_codec_create_componen
+               /* Now we have a component we can set all the ctrls */
+               bcm2835_codec_set_ctrls(ctx);
++
++              /* Enable SPS Timing header so framerate information is encoded
++               * in the H264 header.
++               */
++              vchiq_mmal_port_parameter_set(
++                                      ctx->dev->instance,
++                                      &ctx->component->output[0],
++                                      MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
++                                      &param, sizeof(param));
++
+       } else {
+               if (ctx->q_data[V4L2_M2M_DST].sizeimage <
+                       ctx->component->output[0].minimum_buffer.size)
diff --git a/target/linux/brcm2708/patches-4.19/950-0313-drm-vc4-Don-t-wait-for-vblank-on-fkms-cursor-updates.patch b/target/linux/brcm2708/patches-4.19/950-0313-drm-vc4-Don-t-wait-for-vblank-on-fkms-cursor-updates.patch
new file mode 100644 (file)
index 0000000..545541f
--- /dev/null
@@ -0,0 +1,28 @@
+From dd5fa07672eb01a4d90dfa39a4c54eaa0e086386 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 5 Feb 2018 18:53:18 +0000
+Subject: [PATCH] drm/vc4: Don't wait for vblank on fkms cursor
+ updates.
+
+We don't use the same async update path between fkms and normal kms,
+and the normal kms workaround ended up making us wait.  This became a
+larger problem in rpi-4.14.y, as the USB HID update rate throttling
+got (accidentally?) dropped.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -222,7 +222,8 @@ static int vc4_atomic_commit(struct drm_
+        * drm_atomic_helper_setup_commit() from auto-completing
+        * commit->flip_done.
+        */
+-      state->legacy_cursor_update = false;
++      if (!vc4->firmware_kms)
++              state->legacy_cursor_update = false;
+       ret = drm_atomic_helper_setup_commit(state, nonblock);
+       if (ret)
+               return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0313-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch b/target/linux/brcm2708/patches-4.19/950-0313-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch
deleted file mode 100644 (file)
index 98162a0..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From f51a6ed76f6a59e65fe06d1f2e06e824f38ae604 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 18 Feb 2019 15:52:29 +0000
-Subject: [PATCH] staging: mmal-vchiq: Update mmal_parameters.h with
- recently defined params
-
-mmal_parameters.h hasn't been updated to reflect additions made
-over the last few years. Update it to reflect the currently
-supported parameters.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vchiq-mmal/mmal-parameters.h              | 32 ++++++++++++++++++-
- 1 file changed, 31 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-@@ -580,7 +580,37 @@ enum mmal_parameter_video_type {
-       MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
-       /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
-+      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
-+
-+      /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_SEI_ENABLE,
-+
-+      /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
-+      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS,
-+
-+      /**< Take a @ref MMAL_PARAMETER_VIDEO_RENDER_STATS_T. */
-+      MMAL_PARAMETER_VIDEO_RENDER_STATS,
-+
-+      /**< Take a @ref MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T. */
-+      MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
-+
-+      /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS,
-+
-+      /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
-+
-+      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
-+
-+      /**< Takes a @ref MMAL_PARAMETER_SOURCE_PATTERN_T */
-+      MMAL_PARAMETER_VIDEO_SOURCE_PATTERN,
-+
-+      /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
-+      MMAL_PARAMETER_VIDEO_ENCODE_SEPARATE_NAL_BUFS,
-+
-+      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAME_LENGTH,
- };
- /** Valid mirror modes */
diff --git a/target/linux/brcm2708/patches-4.19/950-0314-Fix-for-Pisound-kernel-module-in-Real-Time-kernel-co.patch b/target/linux/brcm2708/patches-4.19/950-0314-Fix-for-Pisound-kernel-module-in-Real-Time-kernel-co.patch
new file mode 100644 (file)
index 0000000..657d70d
--- /dev/null
@@ -0,0 +1,38 @@
+From c93b0344d24ba63e0e4caeb693a9fcb7320aae3a Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Wed, 27 Feb 2019 14:27:28 +0000
+Subject: [PATCH] Fix for Pisound kernel module in Real Time kernel
+ configuration.
+
+When handler of data_available interrupt is fired, queue_work ends up
+getting called and it can block on a spin lock which is not allowed in
+interrupt context. The fix was to run the handler from a thread context
+instead.
+---
+ sound/soc/bcm/pisound.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/bcm/pisound.c
++++ b/sound/soc/bcm/pisound.c
+@@ -1,6 +1,6 @@
+ /*
+  * Pisound Linux kernel module.
+- * Copyright (C) 2016-2017  Vilniaus Blokas UAB, https://blokas.io/pisound
++ * Copyright (C) 2016-2019  Vilniaus Blokas UAB, https://blokas.io/pisound
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+@@ -532,10 +532,10 @@ static void pisnd_spi_gpio_uninit(void)
+ static int pisnd_spi_gpio_irq_init(struct device *dev)
+ {
+-      return request_irq(
+-              gpiod_to_irq(data_available),
++      return request_threaded_irq(
++              gpiod_to_irq(data_available), NULL,
+               data_available_interrupt_handler,
+-              IRQF_TIMER | IRQF_TRIGGER_RISING,
++              IRQF_TIMER | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+               "data_available_int",
+               NULL
+               );
diff --git a/target/linux/brcm2708/patches-4.19/950-0314-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch b/target/linux/brcm2708/patches-4.19/950-0314-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch
deleted file mode 100644 (file)
index 5e5f1a7..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 7f9fd2338e3a9d7b46b6904bbd7f97851e9b3f52 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 18 Feb 2019 15:56:42 +0000
-Subject: [PATCH] staging: bcm2835_codec: Include timing info in SPS
- headers
-
-Inserting timing information into the VUI block of the SPS is
-optional with the VPU encoder.
-GStreamer appears to require them when using V4L2 M2M, therefore
-set the option to enable them from the encoder.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1785,6 +1785,8 @@ static int bcm2835_codec_create_componen
-               goto destroy_component;
-       if (dev->role == ENCODE) {
-+              u32 param = 1;
-+
-               if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
-                       ctx->component->output[0].minimum_buffer.size)
-                       v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-@@ -1793,6 +1795,16 @@ static int bcm2835_codec_create_componen
-               /* Now we have a component we can set all the ctrls */
-               bcm2835_codec_set_ctrls(ctx);
-+
-+              /* Enable SPS Timing header so framerate information is encoded
-+               * in the H264 header.
-+               */
-+              vchiq_mmal_port_parameter_set(
-+                                      ctx->dev->instance,
-+                                      &ctx->component->output[0],
-+                                      MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
-+                                      &param, sizeof(param));
-+
-       } else {
-               if (ctx->q_data[V4L2_M2M_DST].sizeimage <
-                       ctx->component->output[0].minimum_buffer.size)
diff --git a/target/linux/brcm2708/patches-4.19/950-0315-Added-mute-stream-func.patch b/target/linux/brcm2708/patches-4.19/950-0315-Added-mute-stream-func.patch
new file mode 100644 (file)
index 0000000..7ab46e8
--- /dev/null
@@ -0,0 +1,146 @@
+From 193dc2529db3cfee676aae2b18f059363e151e09 Mon Sep 17 00:00:00 2001
+From: Jaikumar <jaikumar@cem-solutions.net>
+Date: Thu, 7 Jun 2018 21:22:45 +0530
+Subject: [PATCH] Added mute stream func
+
+Signed-off-by: Jaikumar <jaikumar@cem-solutions.net>
+---
+ sound/soc/bcm/allo-katana-codec.c | 60 ++++++++++++++++++++++---------
+ 1 file changed, 44 insertions(+), 16 deletions(-)
+
+--- a/sound/soc/bcm/allo-katana-codec.c
++++ b/sound/soc/bcm/allo-katana-codec.c
+@@ -31,21 +31,23 @@
+ #define KATANA_CODEC_CHIP_ID          0x30
+ #define KATANA_CODEC_VIRT_BASE                0x100
+-#define KATANA_CODEC_PAGE                     0
++#define KATANA_CODEC_PAGE             0
+ #define KATANA_CODEC_CHIP_ID_REG      (KATANA_CODEC_VIRT_BASE + 0)
+-#define KATANA_CODEC_RESET                    (KATANA_CODEC_VIRT_BASE + 1)
++#define KATANA_CODEC_RESET            (KATANA_CODEC_VIRT_BASE + 1)
+ #define KATANA_CODEC_VOLUME_1         (KATANA_CODEC_VIRT_BASE + 2)
+ #define KATANA_CODEC_VOLUME_2         (KATANA_CODEC_VIRT_BASE + 3)
+-#define KATANA_CODEC_MUTE                     (KATANA_CODEC_VIRT_BASE + 4)
++#define KATANA_CODEC_MUTE             (KATANA_CODEC_VIRT_BASE + 4)
+ #define KATANA_CODEC_DSP_PROGRAM      (KATANA_CODEC_VIRT_BASE + 5)
+ #define KATANA_CODEC_DEEMPHASIS               (KATANA_CODEC_VIRT_BASE + 6)
+-#define KATANA_CODEC_DOP                      (KATANA_CODEC_VIRT_BASE + 7)
+-#define KATANA_CODEC_FORMAT                   (KATANA_CODEC_VIRT_BASE + 8)
++#define KATANA_CODEC_DOP              (KATANA_CODEC_VIRT_BASE + 7)
++#define KATANA_CODEC_FORMAT           (KATANA_CODEC_VIRT_BASE + 8)
+ #define KATANA_CODEC_COMMAND          (KATANA_CODEC_VIRT_BASE + 9)
+-#define KATANA_CODEC_MAX_REGISTER     (KATANA_CODEC_VIRT_BASE + 9)
++#define KATANA_CODEC_MUTE_STREAM      (KATANA_CODEC_VIRT_BASE + 10)
+-#define KATANA_CODEC_FMT                      0xff
++#define KATANA_CODEC_MAX_REGISTER     (KATANA_CODEC_VIRT_BASE + 10)
++
++#define KATANA_CODEC_FMT              0xff
+ #define KATANA_CODEC_CHAN_MONO                0x00
+ #define KATANA_CODEC_CHAN_STEREO      0x80
+ #define KATANA_CODEC_ALEN_16          0x10
+@@ -135,7 +137,8 @@ static const struct snd_kcontrol_new kat
+       SOC_SINGLE("DoP Playback Switch", KATANA_CODEC_DOP, 0, 1, 1)
+ };
+-static bool katana_codec_readable_register(struct device *dev, unsigned int reg)
++static bool katana_codec_readable_register(struct device *dev,
++                              unsigned int reg)
+ {
+       switch (reg) {
+       case KATANA_CODEC_CHIP_ID_REG:
+@@ -150,13 +153,15 @@ static int katana_codec_hw_params(struct
+                            struct snd_soc_dai *dai)
+ {
+       struct snd_soc_component *component = dai->component;
+-      struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
++      struct katana_codec_priv *katana_codec =
++              snd_soc_component_get_drvdata(component);
+       int fmt = 0;
+       int ret;
+-      dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
++      dev_dbg(component->card->dev, "hw_params %u Hz, %u channels, %u bits\n",
+                       params_rate(params),
+-                      params_channels(params));
++                      params_channels(params),
++                      params_width(params));
+       switch (katana_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM: // master
+@@ -212,13 +217,17 @@ static int katana_codec_hw_params(struct
+                       return -EINVAL;
+               }
+-              ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT, fmt);
++              ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT,
++                                      fmt);
+               if (ret != 0) {
+                       dev_err(component->card->dev, "Failed to set format: %d\n", ret);
+                       return ret;
+               }
+               break;
++      case SND_SOC_DAIFMT_CBS_CFS:
++              break;
++
+       default:
+               return -EINVAL;
+       }
+@@ -229,14 +238,33 @@ static int katana_codec_hw_params(struct
+ static int katana_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+ {
+       struct snd_soc_component *component = dai->component;
+-      struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
++      struct katana_codec_priv *katana_codec =
++              snd_soc_component_get_drvdata(component);
+       katana_codec->fmt = fmt;
+       return 0;
+ }
++int katana_codec_dai_mute_stream(struct snd_soc_dai *dai, int mute,
++                                              int stream)
++{
++      struct snd_soc_component *component = dai->component;
++      struct katana_codec_priv *katana_codec =
++              snd_soc_component_get_drvdata(component);
++      int ret = 0;
++
++      ret = regmap_write(katana_codec->regmap, KATANA_CODEC_MUTE_STREAM,
++                              mute);
++      if (ret != 0) {
++              dev_err(component->card->dev, "Failed to set mute: %d\n", ret);
++              return ret;
++      }
++      return ret;
++}
++
+ static const struct snd_soc_dai_ops katana_codec_dai_ops = {
++      .mute_stream = katana_codec_dai_mute_stream,
+       .hw_params = katana_codec_hw_params,
+       .set_fmt = katana_codec_set_fmt,
+ };
+@@ -300,7 +328,7 @@ static int allo_katana_component_probe(s
+               return PTR_ERR(regmap);
+       katana_codec = devm_kzalloc(dev, sizeof(struct katana_codec_priv),
+-                                                              GFP_KERNEL);
++                                      GFP_KERNEL);
+       if (!katana_codec)
+               return -ENOMEM;
+@@ -348,8 +376,8 @@ static struct i2c_driver allo_katana_com
+       .remove         = allo_katana_component_remove,
+       .id_table       = allo_katana_component_id,
+       .driver         = {
+-              .name   = "allo-katana-codec",
+-              .of_match_table = allo_katana_codec_of_match,
++      .name           = "allo-katana-codec",
++      .of_match_table = allo_katana_codec_of_match,
+       },
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0315-drm-vc4-Don-t-wait-for-vblank-on-fkms-cursor-updates.patch b/target/linux/brcm2708/patches-4.19/950-0315-drm-vc4-Don-t-wait-for-vblank-on-fkms-cursor-updates.patch
deleted file mode 100644 (file)
index 545541f..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From dd5fa07672eb01a4d90dfa39a4c54eaa0e086386 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 5 Feb 2018 18:53:18 +0000
-Subject: [PATCH] drm/vc4: Don't wait for vblank on fkms cursor
- updates.
-
-We don't use the same async update path between fkms and normal kms,
-and the normal kms workaround ended up making us wait.  This became a
-larger problem in rpi-4.14.y, as the USB HID update rate throttling
-got (accidentally?) dropped.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -222,7 +222,8 @@ static int vc4_atomic_commit(struct drm_
-        * drm_atomic_helper_setup_commit() from auto-completing
-        * commit->flip_done.
-        */
--      state->legacy_cursor_update = false;
-+      if (!vc4->firmware_kms)
-+              state->legacy_cursor_update = false;
-       ret = drm_atomic_helper_setup_commit(state, nonblock);
-       if (ret)
-               return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0316-Fix-for-Pisound-kernel-module-in-Real-Time-kernel-co.patch b/target/linux/brcm2708/patches-4.19/950-0316-Fix-for-Pisound-kernel-module-in-Real-Time-kernel-co.patch
deleted file mode 100644 (file)
index 657d70d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From c93b0344d24ba63e0e4caeb693a9fcb7320aae3a Mon Sep 17 00:00:00 2001
-From: Giedrius <giedrius@blokas.io>
-Date: Wed, 27 Feb 2019 14:27:28 +0000
-Subject: [PATCH] Fix for Pisound kernel module in Real Time kernel
- configuration.
-
-When handler of data_available interrupt is fired, queue_work ends up
-getting called and it can block on a spin lock which is not allowed in
-interrupt context. The fix was to run the handler from a thread context
-instead.
----
- sound/soc/bcm/pisound.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/sound/soc/bcm/pisound.c
-+++ b/sound/soc/bcm/pisound.c
-@@ -1,6 +1,6 @@
- /*
-  * Pisound Linux kernel module.
-- * Copyright (C) 2016-2017  Vilniaus Blokas UAB, https://blokas.io/pisound
-+ * Copyright (C) 2016-2019  Vilniaus Blokas UAB, https://blokas.io/pisound
-  *
-  * This program is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU General Public License
-@@ -532,10 +532,10 @@ static void pisnd_spi_gpio_uninit(void)
- static int pisnd_spi_gpio_irq_init(struct device *dev)
- {
--      return request_irq(
--              gpiod_to_irq(data_available),
-+      return request_threaded_irq(
-+              gpiod_to_irq(data_available), NULL,
-               data_available_interrupt_handler,
--              IRQF_TIMER | IRQF_TRIGGER_RISING,
-+              IRQF_TIMER | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-               "data_available_int",
-               NULL
-               );
diff --git a/target/linux/brcm2708/patches-4.19/950-0316-lan78xx-EEE-support-is-now-a-PHY-property.patch b/target/linux/brcm2708/patches-4.19/950-0316-lan78xx-EEE-support-is-now-a-PHY-property.patch
new file mode 100644 (file)
index 0000000..b37640d
--- /dev/null
@@ -0,0 +1,26 @@
+From 5917a0b0e56928aecd1270c85a79fce77a404629 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 5 Mar 2019 09:51:22 +0000
+Subject: [PATCH] lan78xx: EEE support is now a PHY property
+
+Now that EEE support is a property of the PHY, use the PHY's DT node
+when querying the EEE-related properties.
+
+See: https://github.com/raspberrypi/linux/issues/2882
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/usb/lan78xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2196,7 +2196,7 @@ static int lan78xx_phy_init(struct lan78
+       mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control);
+       phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
+-      if (of_property_read_bool(dev->udev->dev.of_node,
++      if (of_property_read_bool(phydev->mdio.dev.of_node,
+                                 "microchip,eee-enabled")) {
+               struct ethtool_eee edata;
+               memset(&edata, 0, sizeof(edata));
diff --git a/target/linux/brcm2708/patches-4.19/950-0317-Added-mute-stream-func.patch b/target/linux/brcm2708/patches-4.19/950-0317-Added-mute-stream-func.patch
deleted file mode 100644 (file)
index 7ab46e8..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-From 193dc2529db3cfee676aae2b18f059363e151e09 Mon Sep 17 00:00:00 2001
-From: Jaikumar <jaikumar@cem-solutions.net>
-Date: Thu, 7 Jun 2018 21:22:45 +0530
-Subject: [PATCH] Added mute stream func
-
-Signed-off-by: Jaikumar <jaikumar@cem-solutions.net>
----
- sound/soc/bcm/allo-katana-codec.c | 60 ++++++++++++++++++++++---------
- 1 file changed, 44 insertions(+), 16 deletions(-)
-
---- a/sound/soc/bcm/allo-katana-codec.c
-+++ b/sound/soc/bcm/allo-katana-codec.c
-@@ -31,21 +31,23 @@
- #define KATANA_CODEC_CHIP_ID          0x30
- #define KATANA_CODEC_VIRT_BASE                0x100
--#define KATANA_CODEC_PAGE                     0
-+#define KATANA_CODEC_PAGE             0
- #define KATANA_CODEC_CHIP_ID_REG      (KATANA_CODEC_VIRT_BASE + 0)
--#define KATANA_CODEC_RESET                    (KATANA_CODEC_VIRT_BASE + 1)
-+#define KATANA_CODEC_RESET            (KATANA_CODEC_VIRT_BASE + 1)
- #define KATANA_CODEC_VOLUME_1         (KATANA_CODEC_VIRT_BASE + 2)
- #define KATANA_CODEC_VOLUME_2         (KATANA_CODEC_VIRT_BASE + 3)
--#define KATANA_CODEC_MUTE                     (KATANA_CODEC_VIRT_BASE + 4)
-+#define KATANA_CODEC_MUTE             (KATANA_CODEC_VIRT_BASE + 4)
- #define KATANA_CODEC_DSP_PROGRAM      (KATANA_CODEC_VIRT_BASE + 5)
- #define KATANA_CODEC_DEEMPHASIS               (KATANA_CODEC_VIRT_BASE + 6)
--#define KATANA_CODEC_DOP                      (KATANA_CODEC_VIRT_BASE + 7)
--#define KATANA_CODEC_FORMAT                   (KATANA_CODEC_VIRT_BASE + 8)
-+#define KATANA_CODEC_DOP              (KATANA_CODEC_VIRT_BASE + 7)
-+#define KATANA_CODEC_FORMAT           (KATANA_CODEC_VIRT_BASE + 8)
- #define KATANA_CODEC_COMMAND          (KATANA_CODEC_VIRT_BASE + 9)
--#define KATANA_CODEC_MAX_REGISTER     (KATANA_CODEC_VIRT_BASE + 9)
-+#define KATANA_CODEC_MUTE_STREAM      (KATANA_CODEC_VIRT_BASE + 10)
--#define KATANA_CODEC_FMT                      0xff
-+#define KATANA_CODEC_MAX_REGISTER     (KATANA_CODEC_VIRT_BASE + 10)
-+
-+#define KATANA_CODEC_FMT              0xff
- #define KATANA_CODEC_CHAN_MONO                0x00
- #define KATANA_CODEC_CHAN_STEREO      0x80
- #define KATANA_CODEC_ALEN_16          0x10
-@@ -135,7 +137,8 @@ static const struct snd_kcontrol_new kat
-       SOC_SINGLE("DoP Playback Switch", KATANA_CODEC_DOP, 0, 1, 1)
- };
--static bool katana_codec_readable_register(struct device *dev, unsigned int reg)
-+static bool katana_codec_readable_register(struct device *dev,
-+                              unsigned int reg)
- {
-       switch (reg) {
-       case KATANA_CODEC_CHIP_ID_REG:
-@@ -150,13 +153,15 @@ static int katana_codec_hw_params(struct
-                            struct snd_soc_dai *dai)
- {
-       struct snd_soc_component *component = dai->component;
--      struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
-+      struct katana_codec_priv *katana_codec =
-+              snd_soc_component_get_drvdata(component);
-       int fmt = 0;
-       int ret;
--      dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
-+      dev_dbg(component->card->dev, "hw_params %u Hz, %u channels, %u bits\n",
-                       params_rate(params),
--                      params_channels(params));
-+                      params_channels(params),
-+                      params_width(params));
-       switch (katana_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBM_CFM: // master
-@@ -212,13 +217,17 @@ static int katana_codec_hw_params(struct
-                       return -EINVAL;
-               }
--              ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT, fmt);
-+              ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT,
-+                                      fmt);
-               if (ret != 0) {
-                       dev_err(component->card->dev, "Failed to set format: %d\n", ret);
-                       return ret;
-               }
-               break;
-+      case SND_SOC_DAIFMT_CBS_CFS:
-+              break;
-+
-       default:
-               return -EINVAL;
-       }
-@@ -229,14 +238,33 @@ static int katana_codec_hw_params(struct
- static int katana_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
- {
-       struct snd_soc_component *component = dai->component;
--      struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
-+      struct katana_codec_priv *katana_codec =
-+              snd_soc_component_get_drvdata(component);
-       katana_codec->fmt = fmt;
-       return 0;
- }
-+int katana_codec_dai_mute_stream(struct snd_soc_dai *dai, int mute,
-+                                              int stream)
-+{
-+      struct snd_soc_component *component = dai->component;
-+      struct katana_codec_priv *katana_codec =
-+              snd_soc_component_get_drvdata(component);
-+      int ret = 0;
-+
-+      ret = regmap_write(katana_codec->regmap, KATANA_CODEC_MUTE_STREAM,
-+                              mute);
-+      if (ret != 0) {
-+              dev_err(component->card->dev, "Failed to set mute: %d\n", ret);
-+              return ret;
-+      }
-+      return ret;
-+}
-+
- static const struct snd_soc_dai_ops katana_codec_dai_ops = {
-+      .mute_stream = katana_codec_dai_mute_stream,
-       .hw_params = katana_codec_hw_params,
-       .set_fmt = katana_codec_set_fmt,
- };
-@@ -300,7 +328,7 @@ static int allo_katana_component_probe(s
-               return PTR_ERR(regmap);
-       katana_codec = devm_kzalloc(dev, sizeof(struct katana_codec_priv),
--                                                              GFP_KERNEL);
-+                                      GFP_KERNEL);
-       if (!katana_codec)
-               return -ENOMEM;
-@@ -348,8 +376,8 @@ static struct i2c_driver allo_katana_com
-       .remove         = allo_katana_component_remove,
-       .id_table       = allo_katana_component_id,
-       .driver         = {
--              .name   = "allo-katana-codec",
--              .of_match_table = allo_katana_codec_of_match,
-+      .name           = "allo-katana-codec",
-+      .of_match_table = allo_katana_codec_of_match,
-       },
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0317-staging-vc_sm_cma-Remove-erroneous-misc_deregister.patch b/target/linux/brcm2708/patches-4.19/950-0317-staging-vc_sm_cma-Remove-erroneous-misc_deregister.patch
new file mode 100644 (file)
index 0000000..4f49925
--- /dev/null
@@ -0,0 +1,44 @@
+From 7b2fac96ce48939e399707c4b8bd9905d6274a05 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 10:38:59 +0000
+Subject: [PATCH] staging: vc_sm_cma: Remove erroneous misc_deregister
+
+Code from the misc /dev node was still present in
+bcm2835_vc_sm_cma_remove, which caused a NULL deref.
+Remove it.
+
+See #2885.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -25,7 +25,6 @@
+ #include <linux/fs.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+-#include <linux/miscdevice.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/of_device.h>
+@@ -72,7 +71,6 @@ struct sm_pde_t {
+ struct sm_state_t {
+       struct platform_device *pdev;
+-      struct miscdevice dev;
+       struct sm_instance *sm_handle;  /* Handle for videocore service. */
+       spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
+@@ -758,9 +756,6 @@ static int bcm2835_vc_sm_cma_remove(stru
+ {
+       pr_debug("[%s]: start\n", __func__);
+       if (sm_inited) {
+-              /* Remove shared memory device. */
+-              misc_deregister(&sm_state->dev);
+-
+               /* Remove all proc entries. */
+               //debugfs_remove_recursive(sm_state->dir_root);
diff --git a/target/linux/brcm2708/patches-4.19/950-0318-lan78xx-EEE-support-is-now-a-PHY-property.patch b/target/linux/brcm2708/patches-4.19/950-0318-lan78xx-EEE-support-is-now-a-PHY-property.patch
deleted file mode 100644 (file)
index b37640d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 5917a0b0e56928aecd1270c85a79fce77a404629 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 5 Mar 2019 09:51:22 +0000
-Subject: [PATCH] lan78xx: EEE support is now a PHY property
-
-Now that EEE support is a property of the PHY, use the PHY's DT node
-when querying the EEE-related properties.
-
-See: https://github.com/raspberrypi/linux/issues/2882
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/usb/lan78xx.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -2196,7 +2196,7 @@ static int lan78xx_phy_init(struct lan78
-       mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control);
-       phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
--      if (of_property_read_bool(dev->udev->dev.of_node,
-+      if (of_property_read_bool(phydev->mdio.dev.of_node,
-                                 "microchip,eee-enabled")) {
-               struct ethtool_eee edata;
-               memset(&edata, 0, sizeof(edata));
diff --git a/target/linux/brcm2708/patches-4.19/950-0318-vcsm-Fix-makefile-include-on-out-of-tree-builds.patch b/target/linux/brcm2708/patches-4.19/950-0318-vcsm-Fix-makefile-include-on-out-of-tree-builds.patch
new file mode 100644 (file)
index 0000000..962c3de
--- /dev/null
@@ -0,0 +1,27 @@
+From d36a5a94156ebe7e9906574fa8b01b200a15c11d Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Mon, 18 Mar 2019 17:14:51 +0000
+Subject: [PATCH] vcsm: Fix makefile include on out-of-tree builds
+
+The vc_sm module tries to include the 'fs' directory from the
+$(srctree). $(srctree) is already provided by the build system, and
+causes the include path to be duplicated.
+
+With -Werror this fails to compile.
+
+Remove the unnecessary variable.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/char/broadcom/vc_sm/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/broadcom/vc_sm/Makefile
++++ b/drivers/char/broadcom/vc_sm/Makefile
+@@ -1,5 +1,5 @@
+ ccflags-$(CONFIG_BCM_VC_SM) += -Werror -Wall -Wstrict-prototypes -Wno-trigraphs -O2
+-ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"$(srctree)/fs/"
++ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"fs"
+ ccflags-$(CONFIG_BCM_VC_SM) += -DOS_ASSERT_FAILURE -D__STDC_VERSION=199901L -D__STDC_VERSION__=199901L -D__VCCOREVER__=0 -D__KERNEL__ -D__linux__
+ obj-$(CONFIG_BCM_VC_SM) := vc-sm.o
diff --git a/target/linux/brcm2708/patches-4.19/950-0319-staging-vc_sm_cma-Remove-erroneous-misc_deregister.patch b/target/linux/brcm2708/patches-4.19/950-0319-staging-vc_sm_cma-Remove-erroneous-misc_deregister.patch
deleted file mode 100644 (file)
index 4f49925..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 7b2fac96ce48939e399707c4b8bd9905d6274a05 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 10:38:59 +0000
-Subject: [PATCH] staging: vc_sm_cma: Remove erroneous misc_deregister
-
-Code from the misc /dev node was still present in
-bcm2835_vc_sm_cma_remove, which caused a NULL deref.
-Remove it.
-
-See #2885.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -25,7 +25,6 @@
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
--#include <linux/miscdevice.h>
- #include <linux/module.h>
- #include <linux/mm.h>
- #include <linux/of_device.h>
-@@ -72,7 +71,6 @@ struct sm_pde_t {
- struct sm_state_t {
-       struct platform_device *pdev;
--      struct miscdevice dev;
-       struct sm_instance *sm_handle;  /* Handle for videocore service. */
-       spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
-@@ -758,9 +756,6 @@ static int bcm2835_vc_sm_cma_remove(stru
- {
-       pr_debug("[%s]: start\n", __func__);
-       if (sm_inited) {
--              /* Remove shared memory device. */
--              misc_deregister(&sm_state->dev);
--
-               /* Remove all proc entries. */
-               //debugfs_remove_recursive(sm_state->dir_root);
diff --git a/target/linux/brcm2708/patches-4.19/950-0319-vcsm-Remove-set-but-unused-variable.patch b/target/linux/brcm2708/patches-4.19/950-0319-vcsm-Remove-set-but-unused-variable.patch
new file mode 100644 (file)
index 0000000..267cad4
--- /dev/null
@@ -0,0 +1,28 @@
+From 5a58b2bb907d57dc2b1cc2619bd5f1d948509e3e Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Mon, 18 Mar 2019 17:16:41 +0000
+Subject: [PATCH] vcsm: Remove set but unused variable
+
+The 'success' variable is set by the call to vchi_service_close() but never checked.
+Remove it, keeping the call in place.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
++++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
+@@ -361,11 +361,9 @@ int vc_vchi_sm_stop(struct sm_instance *
+       /* Close all VCHI service connections */
+       for (i = 0; i < instance->num_connections; i++) {
+-              int32_t success;
+-
+               vchi_service_use(instance->vchi_handle[i]);
+-              success = vchi_service_close(instance->vchi_handle[i]);
++              vchi_service_close(instance->vchi_handle[i]);
+       }
+       kfree(instance);
diff --git a/target/linux/brcm2708/patches-4.19/950-0320-vcsm-Fix-makefile-include-on-out-of-tree-builds.patch b/target/linux/brcm2708/patches-4.19/950-0320-vcsm-Fix-makefile-include-on-out-of-tree-builds.patch
deleted file mode 100644 (file)
index 962c3de..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From d36a5a94156ebe7e9906574fa8b01b200a15c11d Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Mon, 18 Mar 2019 17:14:51 +0000
-Subject: [PATCH] vcsm: Fix makefile include on out-of-tree builds
-
-The vc_sm module tries to include the 'fs' directory from the
-$(srctree). $(srctree) is already provided by the build system, and
-causes the include path to be duplicated.
-
-With -Werror this fails to compile.
-
-Remove the unnecessary variable.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/char/broadcom/vc_sm/Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/char/broadcom/vc_sm/Makefile
-+++ b/drivers/char/broadcom/vc_sm/Makefile
-@@ -1,5 +1,5 @@
- ccflags-$(CONFIG_BCM_VC_SM) += -Werror -Wall -Wstrict-prototypes -Wno-trigraphs -O2
--ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"$(srctree)/fs/"
-+ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"fs"
- ccflags-$(CONFIG_BCM_VC_SM) += -DOS_ASSERT_FAILURE -D__STDC_VERSION=199901L -D__STDC_VERSION__=199901L -D__VCCOREVER__=0 -D__KERNEL__ -D__linux__
- obj-$(CONFIG_BCM_VC_SM) := vc-sm.o
diff --git a/target/linux/brcm2708/patches-4.19/950-0320-vcsm-Reduce-scope-of-local-functions.patch b/target/linux/brcm2708/patches-4.19/950-0320-vcsm-Reduce-scope-of-local-functions.patch
new file mode 100644 (file)
index 0000000..311ae66
--- /dev/null
@@ -0,0 +1,69 @@
+From 2a1fd1a32b7355c6ae8c5fc1654a96fa42e00586 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Mon, 18 Mar 2019 17:17:40 +0000
+Subject: [PATCH] vcsm: Reduce scope of local functions
+
+The functions:
+
+  vc_vchi_sm_send_msg
+  vc_sm_ioctl_alloc
+  vc_sm_ioctl_alloc_share
+  vc_sm_ioctl_import_dmabuf
+
+Are declared without a prototype. They are not used outside of this
+module, thus - convert them to static functions.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/char/broadcom/vc_sm/vc_vchi_sm.c |  2 +-
+ drivers/char/broadcom/vc_sm/vmcs_sm.c    | 14 +++++++-------
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
++++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
+@@ -375,7 +375,7 @@ lock:
+       return -EINVAL;
+ }
+-int vc_vchi_sm_send_msg(struct sm_instance *handle,
++static int vc_vchi_sm_send_msg(struct sm_instance *handle,
+                       enum vc_sm_msg_type msg_id,
+                       void *msg, uint32_t msg_size,
+                       void *result, uint32_t result_size,
+--- a/drivers/char/broadcom/vc_sm/vmcs_sm.c
++++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c
+@@ -1574,8 +1574,8 @@ error:
+ }
+ /* Allocate a shared memory handle and block. */
+-int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
+-                    struct vmcs_sm_ioctl_alloc *ioparam)
++static int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
++                           struct vmcs_sm_ioctl_alloc *ioparam)
+ {
+       int ret = 0;
+       int status;
+@@ -1685,8 +1685,8 @@ error:
+ }
+ /* Share an allocate memory handle and block.*/
+-int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
+-                          struct vmcs_sm_ioctl_alloc_share *ioparam)
++static int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
++                                 struct vmcs_sm_ioctl_alloc_share *ioparam)
+ {
+       struct sm_resource_t *resource, *shared_resource;
+       int ret = 0;
+@@ -2200,9 +2200,9 @@ error:
+ }
+ /* Import a contiguous block of memory to be shared with VC. */
+-int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
+-                            struct vmcs_sm_ioctl_import_dmabuf *ioparam,
+-                            struct dma_buf *src_dma_buf)
++static int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
++                                   struct vmcs_sm_ioctl_import_dmabuf *ioparam,
++                                   struct dma_buf *src_dma_buf)
+ {
+       int ret = 0;
+       int status;
diff --git a/target/linux/brcm2708/patches-4.19/950-0321-staging-bcm2835-codec-NULL-component-handle-on-queue.patch b/target/linux/brcm2708/patches-4.19/950-0321-staging-bcm2835-codec-NULL-component-handle-on-queue.patch
new file mode 100644 (file)
index 0000000..ee5d01d
--- /dev/null
@@ -0,0 +1,59 @@
+From 140c118a9886b0386d748e6aa7cbd8ba9f9b0ede Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 19 Mar 2019 17:55:09 +0000
+Subject: [PATCH] staging: bcm2835-codec: NULL component handle on
+ queue_setup failure
+
+queue_setup tries creating the relevant MMAL component and configures
+the input and output ports as we're expecting to start streaming.
+If the port configuration failed then it destroyed the component,
+but failed to clear the component handle, therefore release tried
+destroying the component again.
+Adds some logging should the port config fail as well.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c            | 15 +++++++++++++--
+ 1 file changed, 13 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
+@@ -1776,13 +1776,21 @@ static int bcm2835_codec_create_componen
+       ret = vchiq_mmal_port_set_format(dev->instance,
+                                        &ctx->component->input[0]);
+-      if (ret < 0)
++      if (ret < 0) {
++              v4l2_dbg(1, debug, &dev->v4l2_dev,
++                       "%s: vchiq_mmal_port_set_format ip port failed\n",
++                       __func__);
+               goto destroy_component;
++      }
+       ret = vchiq_mmal_port_set_format(dev->instance,
+                                        &ctx->component->output[0]);
+-      if (ret < 0)
++      if (ret < 0) {
++              v4l2_dbg(1, debug, &dev->v4l2_dev,
++                       "%s: vchiq_mmal_port_set_format op port failed\n",
++                       __func__);
+               goto destroy_component;
++      }
+       if (dev->role == ENCODE) {
+               u32 param = 1;
+@@ -1812,11 +1820,14 @@ static int bcm2835_codec_create_componen
+                                ctx->q_data[V4L2_M2M_DST].sizeimage,
+                                ctx->component->output[0].minimum_buffer.size);
+       }
++      v4l2_dbg(2, debug, &dev->v4l2_dev, "%s: component created as %s\n",
++               __func__, components[dev->role]);
+       return 0;
+ destroy_component:
+       vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
++      ctx->component = NULL;
+       return ret;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0321-vcsm-Remove-set-but-unused-variable.patch b/target/linux/brcm2708/patches-4.19/950-0321-vcsm-Remove-set-but-unused-variable.patch
deleted file mode 100644 (file)
index 267cad4..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 5a58b2bb907d57dc2b1cc2619bd5f1d948509e3e Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Mon, 18 Mar 2019 17:16:41 +0000
-Subject: [PATCH] vcsm: Remove set but unused variable
-
-The 'success' variable is set by the call to vchi_service_close() but never checked.
-Remove it, keeping the call in place.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
---- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-+++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-@@ -361,11 +361,9 @@ int vc_vchi_sm_stop(struct sm_instance *
-       /* Close all VCHI service connections */
-       for (i = 0; i < instance->num_connections; i++) {
--              int32_t success;
--
-               vchi_service_use(instance->vchi_handle[i]);
--              success = vchi_service_close(instance->vchi_handle[i]);
-+              vchi_service_close(instance->vchi_handle[i]);
-       }
-       kfree(instance);
diff --git a/target/linux/brcm2708/patches-4.19/950-0322-staging-vc-sm-cma-Remove-the-debugfs-directory-on-re.patch b/target/linux/brcm2708/patches-4.19/950-0322-staging-vc-sm-cma-Remove-the-debugfs-directory-on-re.patch
new file mode 100644 (file)
index 0000000..aeea6c8
--- /dev/null
@@ -0,0 +1,24 @@
+From 4857371a7cc5d371b1e4221fa38848716a779eb1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 10:49:17 +0000
+Subject: [PATCH] staging: vc-sm-cma: Remove the debugfs directory on
+ remove
+
+Without removing that, reloading the driver fails.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -757,7 +757,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+       pr_debug("[%s]: start\n", __func__);
+       if (sm_inited) {
+               /* Remove all proc entries. */
+-              //debugfs_remove_recursive(sm_state->dir_root);
++              debugfs_remove_recursive(sm_state->dir_root);
+               /* Stop the videocore shared memory service. */
+               vc_sm_cma_vchi_stop(&sm_state->sm_handle);
diff --git a/target/linux/brcm2708/patches-4.19/950-0322-vcsm-Reduce-scope-of-local-functions.patch b/target/linux/brcm2708/patches-4.19/950-0322-vcsm-Reduce-scope-of-local-functions.patch
deleted file mode 100644 (file)
index 311ae66..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From 2a1fd1a32b7355c6ae8c5fc1654a96fa42e00586 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Mon, 18 Mar 2019 17:17:40 +0000
-Subject: [PATCH] vcsm: Reduce scope of local functions
-
-The functions:
-
-  vc_vchi_sm_send_msg
-  vc_sm_ioctl_alloc
-  vc_sm_ioctl_alloc_share
-  vc_sm_ioctl_import_dmabuf
-
-Are declared without a prototype. They are not used outside of this
-module, thus - convert them to static functions.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/char/broadcom/vc_sm/vc_vchi_sm.c |  2 +-
- drivers/char/broadcom/vc_sm/vmcs_sm.c    | 14 +++++++-------
- 2 files changed, 8 insertions(+), 8 deletions(-)
-
---- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-+++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-@@ -375,7 +375,7 @@ lock:
-       return -EINVAL;
- }
--int vc_vchi_sm_send_msg(struct sm_instance *handle,
-+static int vc_vchi_sm_send_msg(struct sm_instance *handle,
-                       enum vc_sm_msg_type msg_id,
-                       void *msg, uint32_t msg_size,
-                       void *result, uint32_t result_size,
---- a/drivers/char/broadcom/vc_sm/vmcs_sm.c
-+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c
-@@ -1574,8 +1574,8 @@ error:
- }
- /* Allocate a shared memory handle and block. */
--int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
--                    struct vmcs_sm_ioctl_alloc *ioparam)
-+static int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
-+                           struct vmcs_sm_ioctl_alloc *ioparam)
- {
-       int ret = 0;
-       int status;
-@@ -1685,8 +1685,8 @@ error:
- }
- /* Share an allocate memory handle and block.*/
--int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
--                          struct vmcs_sm_ioctl_alloc_share *ioparam)
-+static int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
-+                                 struct vmcs_sm_ioctl_alloc_share *ioparam)
- {
-       struct sm_resource_t *resource, *shared_resource;
-       int ret = 0;
-@@ -2200,9 +2200,9 @@ error:
- }
- /* Import a contiguous block of memory to be shared with VC. */
--int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
--                            struct vmcs_sm_ioctl_import_dmabuf *ioparam,
--                            struct dma_buf *src_dma_buf)
-+static int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
-+                                   struct vmcs_sm_ioctl_import_dmabuf *ioparam,
-+                                   struct dma_buf *src_dma_buf)
- {
-       int ret = 0;
-       int status;
diff --git a/target/linux/brcm2708/patches-4.19/950-0323-staging-bcm2835-codec-NULL-component-handle-on-queue.patch b/target/linux/brcm2708/patches-4.19/950-0323-staging-bcm2835-codec-NULL-component-handle-on-queue.patch
deleted file mode 100644 (file)
index ee5d01d..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 140c118a9886b0386d748e6aa7cbd8ba9f9b0ede Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 19 Mar 2019 17:55:09 +0000
-Subject: [PATCH] staging: bcm2835-codec: NULL component handle on
- queue_setup failure
-
-queue_setup tries creating the relevant MMAL component and configures
-the input and output ports as we're expecting to start streaming.
-If the port configuration failed then it destroyed the component,
-but failed to clear the component handle, therefore release tried
-destroying the component again.
-Adds some logging should the port config fail as well.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c            | 15 +++++++++++++--
- 1 file changed, 13 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
-@@ -1776,13 +1776,21 @@ static int bcm2835_codec_create_componen
-       ret = vchiq_mmal_port_set_format(dev->instance,
-                                        &ctx->component->input[0]);
--      if (ret < 0)
-+      if (ret < 0) {
-+              v4l2_dbg(1, debug, &dev->v4l2_dev,
-+                       "%s: vchiq_mmal_port_set_format ip port failed\n",
-+                       __func__);
-               goto destroy_component;
-+      }
-       ret = vchiq_mmal_port_set_format(dev->instance,
-                                        &ctx->component->output[0]);
--      if (ret < 0)
-+      if (ret < 0) {
-+              v4l2_dbg(1, debug, &dev->v4l2_dev,
-+                       "%s: vchiq_mmal_port_set_format op port failed\n",
-+                       __func__);
-               goto destroy_component;
-+      }
-       if (dev->role == ENCODE) {
-               u32 param = 1;
-@@ -1812,11 +1820,14 @@ static int bcm2835_codec_create_componen
-                                ctx->q_data[V4L2_M2M_DST].sizeimage,
-                                ctx->component->output[0].minimum_buffer.size);
-       }
-+      v4l2_dbg(2, debug, &dev->v4l2_dev, "%s: component created as %s\n",
-+               __func__, components[dev->role]);
-       return 0;
- destroy_component:
-       vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
-+      ctx->component = NULL;
-       return ret;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0323-staging-vc-sm-cma-Use-devm_-allocs-for-sm_state.patch b/target/linux/brcm2708/patches-4.19/950-0323-staging-vc-sm-cma-Use-devm_-allocs-for-sm_state.patch
new file mode 100644 (file)
index 0000000..70b73dd
--- /dev/null
@@ -0,0 +1,69 @@
+From 6214831525192a9eb665c67fe8c93006c17acbad Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:06:41 +0000
+Subject: [PATCH] staging: vc-sm-cma: Use devm_ allocs for sm_state.
+
+Use managed allocations for sm_state, removing reliance on
+manual management.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -656,7 +656,7 @@ static void vc_sm_connected_init(void)
+                      __func__, ret);
+               ret = -EIO;
+-              goto err_free_mem;
++              goto err_failed;
+       }
+       ret = vchi_connect(NULL, 0, vchi_instance);
+@@ -665,7 +665,7 @@ static void vc_sm_connected_init(void)
+                      __func__, ret);
+               ret = -EIO;
+-              goto err_free_mem;
++              goto err_failed;
+       }
+       /* Initialize an instance of the shared memory service. */
+@@ -676,7 +676,7 @@ static void vc_sm_connected_init(void)
+                      __func__);
+               ret = -EPERM;
+-              goto err_free_mem;
++              goto err_failed;
+       }
+       /* Create a debug fs directory entry (root). */
+@@ -722,8 +722,7 @@ err_remove_shared_memory:
+       debugfs_remove_recursive(sm_state->dir_root);
+ err_stop_sm_service:
+       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+-err_free_mem:
+-      kfree(sm_state);
++err_failed:
+       pr_info("[%s]: failed, ret %d\n", __func__, ret);
+ }
+@@ -732,7 +731,7 @@ static int bcm2835_vc_sm_cma_probe(struc
+ {
+       pr_info("%s: Videocore shared memory driver\n", __func__);
+-      sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
++      sm_state = devm_kzalloc(&pdev->dev, sizeof(*sm_state), GFP_KERNEL);
+       if (!sm_state)
+               return -ENOMEM;
+       sm_state->pdev = pdev;
+@@ -766,7 +765,6 @@ static int bcm2835_vc_sm_cma_remove(stru
+               /* Free the memory for the state structure. */
+               mutex_destroy(&sm_state->map_lock);
+-              kfree(sm_state);
+       }
+       pr_debug("[%s]: end\n", __func__);
diff --git a/target/linux/brcm2708/patches-4.19/950-0324-staging-vc-sm-cma-Don-t-fail-if-debugfs-calls-fail.patch b/target/linux/brcm2708/patches-4.19/950-0324-staging-vc-sm-cma-Don-t-fail-if-debugfs-calls-fail.patch
new file mode 100644 (file)
index 0000000..f8b7ca2
--- /dev/null
@@ -0,0 +1,37 @@
+From 13572df6bba85d8fc91a212faa89b5b6147bdf94 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:09:49 +0000
+Subject: [PATCH] staging: vc-sm-cma: Don't fail if debugfs calls fail.
+
+Return codes from debugfs calls should never alter the
+flow of the main code.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -681,13 +681,6 @@ static void vc_sm_connected_init(void)
+       /* Create a debug fs directory entry (root). */
+       sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
+-      if (!sm_state->dir_root) {
+-              pr_err("[%s]: failed to create \'%s\' directory entry\n",
+-                     __func__, VC_SM_DIR_ROOT_NAME);
+-
+-              ret = -EPERM;
+-              goto err_stop_sm_service;
+-      }
+       sm_state->dir_state.show = &vc_sm_cma_global_state_show;
+       sm_state->dir_state.dir_entry =
+@@ -720,7 +713,6 @@ static void vc_sm_connected_init(void)
+ err_remove_shared_memory:
+       debugfs_remove_recursive(sm_state->dir_root);
+-err_stop_sm_service:
+       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+ err_failed:
+       pr_info("[%s]: failed, ret %d\n", __func__, ret);
diff --git a/target/linux/brcm2708/patches-4.19/950-0324-staging-vc-sm-cma-Remove-the-debugfs-directory-on-re.patch b/target/linux/brcm2708/patches-4.19/950-0324-staging-vc-sm-cma-Remove-the-debugfs-directory-on-re.patch
deleted file mode 100644 (file)
index aeea6c8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 4857371a7cc5d371b1e4221fa38848716a779eb1 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 10:49:17 +0000
-Subject: [PATCH] staging: vc-sm-cma: Remove the debugfs directory on
- remove
-
-Without removing that, reloading the driver fails.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -757,7 +757,7 @@ static int bcm2835_vc_sm_cma_remove(stru
-       pr_debug("[%s]: start\n", __func__);
-       if (sm_inited) {
-               /* Remove all proc entries. */
--              //debugfs_remove_recursive(sm_state->dir_root);
-+              debugfs_remove_recursive(sm_state->dir_root);
-               /* Stop the videocore shared memory service. */
-               vc_sm_cma_vchi_stop(&sm_state->sm_handle);
diff --git a/target/linux/brcm2708/patches-4.19/950-0325-staging-vc-sm-cma-Ensure-mutex-and-idr-are-destroyed.patch b/target/linux/brcm2708/patches-4.19/950-0325-staging-vc-sm-cma-Ensure-mutex-and-idr-are-destroyed.patch
new file mode 100644 (file)
index 0000000..6133840
--- /dev/null
@@ -0,0 +1,27 @@
+From 4027b08d96c68919f51c768a23877283ef5aefb9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:11:46 +0000
+Subject: [PATCH] staging: vc-sm-cma: Ensure mutex and idr are
+ destroyed
+
+map_lock and kernelid_map are created in probe, but not released
+in release should the vcsm service not connect (eg running the
+cutdown firmware).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -752,7 +752,9 @@ static int bcm2835_vc_sm_cma_remove(stru
+               /* Stop the videocore shared memory service. */
+               vc_sm_cma_vchi_stop(&sm_state->sm_handle);
++      }
++      if (sm_state) {
+               idr_destroy(&sm_state->kernelid_map);
+               /* Free the memory for the state structure. */
diff --git a/target/linux/brcm2708/patches-4.19/950-0325-staging-vc-sm-cma-Use-devm_-allocs-for-sm_state.patch b/target/linux/brcm2708/patches-4.19/950-0325-staging-vc-sm-cma-Use-devm_-allocs-for-sm_state.patch
deleted file mode 100644 (file)
index 70b73dd..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From 6214831525192a9eb665c67fe8c93006c17acbad Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:06:41 +0000
-Subject: [PATCH] staging: vc-sm-cma: Use devm_ allocs for sm_state.
-
-Use managed allocations for sm_state, removing reliance on
-manual management.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 12 +++++-------
- 1 file changed, 5 insertions(+), 7 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -656,7 +656,7 @@ static void vc_sm_connected_init(void)
-                      __func__, ret);
-               ret = -EIO;
--              goto err_free_mem;
-+              goto err_failed;
-       }
-       ret = vchi_connect(NULL, 0, vchi_instance);
-@@ -665,7 +665,7 @@ static void vc_sm_connected_init(void)
-                      __func__, ret);
-               ret = -EIO;
--              goto err_free_mem;
-+              goto err_failed;
-       }
-       /* Initialize an instance of the shared memory service. */
-@@ -676,7 +676,7 @@ static void vc_sm_connected_init(void)
-                      __func__);
-               ret = -EPERM;
--              goto err_free_mem;
-+              goto err_failed;
-       }
-       /* Create a debug fs directory entry (root). */
-@@ -722,8 +722,7 @@ err_remove_shared_memory:
-       debugfs_remove_recursive(sm_state->dir_root);
- err_stop_sm_service:
-       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
--err_free_mem:
--      kfree(sm_state);
-+err_failed:
-       pr_info("[%s]: failed, ret %d\n", __func__, ret);
- }
-@@ -732,7 +731,7 @@ static int bcm2835_vc_sm_cma_probe(struc
- {
-       pr_info("%s: Videocore shared memory driver\n", __func__);
--      sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
-+      sm_state = devm_kzalloc(&pdev->dev, sizeof(*sm_state), GFP_KERNEL);
-       if (!sm_state)
-               return -ENOMEM;
-       sm_state->pdev = pdev;
-@@ -766,7 +765,6 @@ static int bcm2835_vc_sm_cma_remove(stru
-               /* Free the memory for the state structure. */
-               mutex_destroy(&sm_state->map_lock);
--              kfree(sm_state);
-       }
-       pr_debug("[%s]: end\n", __func__);
diff --git a/target/linux/brcm2708/patches-4.19/950-0326-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch b/target/linux/brcm2708/patches-4.19/950-0326-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch
new file mode 100644 (file)
index 0000000..4bf0c78
--- /dev/null
@@ -0,0 +1,49 @@
+From c42ae04bb6ed5be61d3b3e2e2c6004ae252ee34a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:26:00 +0000
+Subject: [PATCH] staging: bcm2835_codec: Clean up logging on unloading
+ the driver
+
+The log line was missing a closing \n, so wasn't added to the
+log immediately.
+Adds the function of the V4L2 device that is being unregistered
+too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c   | 10 ++++++++--
+ 1 file changed, 8 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
+@@ -77,6 +77,12 @@ enum bcm2835_codec_role {
+       ISP,
+ };
++const static char *roles[] = {
++      "decode",
++      "encode",
++      "isp"
++};
++
+ static const char * const components[] = {
+       "ril.video_decode",
+       "ril.video_encode",
+@@ -2522,7 +2528,6 @@ static int bcm2835_codec_create(struct p
+       struct video_device *vfd;
+       int video_nr;
+       int ret;
+-      const static char *roles[] = {"decode", "encode", "isp"};
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+@@ -2615,7 +2620,8 @@ static int bcm2835_codec_destroy(struct
+       if (!dev)
+               return -ENODEV;
+-      v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
++      v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
++                roles[dev->role]);
+       v4l2_m2m_release(dev->m2m_dev);
+       video_unregister_device(&dev->vfd);
+       v4l2_device_unregister(&dev->v4l2_dev);
diff --git a/target/linux/brcm2708/patches-4.19/950-0326-staging-vc-sm-cma-Don-t-fail-if-debugfs-calls-fail.patch b/target/linux/brcm2708/patches-4.19/950-0326-staging-vc-sm-cma-Don-t-fail-if-debugfs-calls-fail.patch
deleted file mode 100644 (file)
index f8b7ca2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 13572df6bba85d8fc91a212faa89b5b6147bdf94 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:09:49 +0000
-Subject: [PATCH] staging: vc-sm-cma: Don't fail if debugfs calls fail.
-
-Return codes from debugfs calls should never alter the
-flow of the main code.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 --------
- 1 file changed, 8 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -681,13 +681,6 @@ static void vc_sm_connected_init(void)
-       /* Create a debug fs directory entry (root). */
-       sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
--      if (!sm_state->dir_root) {
--              pr_err("[%s]: failed to create \'%s\' directory entry\n",
--                     __func__, VC_SM_DIR_ROOT_NAME);
--
--              ret = -EPERM;
--              goto err_stop_sm_service;
--      }
-       sm_state->dir_state.show = &vc_sm_cma_global_state_show;
-       sm_state->dir_state.dir_entry =
-@@ -720,7 +713,6 @@ static void vc_sm_connected_init(void)
- err_remove_shared_memory:
-       debugfs_remove_recursive(sm_state->dir_root);
--err_stop_sm_service:
-       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
- err_failed:
-       pr_info("[%s]: failed, ret %d\n", __func__, ret);
diff --git a/target/linux/brcm2708/patches-4.19/950-0327-bcm2835-sdhost-Allow-for-sg-entries-that-cross-pages.patch b/target/linux/brcm2708/patches-4.19/950-0327-bcm2835-sdhost-Allow-for-sg-entries-that-cross-pages.patch
new file mode 100644 (file)
index 0000000..e16e12d
--- /dev/null
@@ -0,0 +1,32 @@
+From 44db7882be675cdf2d89741af5bbeba41b3e25af Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 13 Mar 2019 14:19:11 +0000
+Subject: [PATCH] bcm2835-sdhost: Allow for sg entries that cross pages
+
+The dma_complete handling code calculates a virtual address for a page
+then adds an offset, but if the offset is more than a page and HIGHMEM
+is in use then the summed address could be in an unmapped (or just
+incorrect) page.
+
+The upstream SDHOST driver allows for this possibility - copy the code
+that does so.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/bcm2835-sdhost.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mmc/host/bcm2835-sdhost.c
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -543,6 +543,11 @@ static void bcm2835_sdhost_dma_complete(
+               void *page;
+               u32 *buf;
++              if (host->drain_offset & PAGE_MASK) {
++                      host->drain_page += host->drain_offset >> PAGE_SHIFT;
++                      host->drain_offset &= ~PAGE_MASK;
++              }
++
+               page = kmap_atomic(host->drain_page);
+               buf = page + host->drain_offset;
diff --git a/target/linux/brcm2708/patches-4.19/950-0327-staging-vc-sm-cma-Ensure-mutex-and-idr-are-destroyed.patch b/target/linux/brcm2708/patches-4.19/950-0327-staging-vc-sm-cma-Ensure-mutex-and-idr-are-destroyed.patch
deleted file mode 100644 (file)
index 6133840..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 4027b08d96c68919f51c768a23877283ef5aefb9 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:11:46 +0000
-Subject: [PATCH] staging: vc-sm-cma: Ensure mutex and idr are
- destroyed
-
-map_lock and kernelid_map are created in probe, but not released
-in release should the vcsm service not connect (eg running the
-cutdown firmware).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -752,7 +752,9 @@ static int bcm2835_vc_sm_cma_remove(stru
-               /* Stop the videocore shared memory service. */
-               vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-+      }
-+      if (sm_state) {
-               idr_destroy(&sm_state->kernelid_map);
-               /* Free the memory for the state structure. */
diff --git a/target/linux/brcm2708/patches-4.19/950-0328-overlays-sdio-Added-4-bit-support-on-GPIOs-34-39.-29.patch b/target/linux/brcm2708/patches-4.19/950-0328-overlays-sdio-Added-4-bit-support-on-GPIOs-34-39.-29.patch
new file mode 100644 (file)
index 0000000..f823f67
--- /dev/null
@@ -0,0 +1,47 @@
+From 7c23c772289fa31960b9e6969499aa93c92d842b Mon Sep 17 00:00:00 2001
+From: Adrien RICCIARDI <RICCIARDI-Adrien@users.noreply.github.com>
+Date: Fri, 22 Mar 2019 11:35:30 +0100
+Subject: [PATCH] overlays: sdio: Added 4-bit support on GPIOs 34-39.
+ (#2903)
+
+---
+ arch/arm/boot/dts/overlays/README           | 3 +++
+ arch/arm/boot/dts/overlays/sdio-overlay.dts | 9 +++++++++
+ 2 files changed, 12 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1785,6 +1785,9 @@ Params: sdio_overclock          SDIO Clo
+         gpios_34_37             Select GPIOs 34-37 for 1-bit mode. Must be used
+                                 with bus_width=1.
++        gpios_34_39             Select GPIOs 34-39 for 4-bit mode. Must be used
++                                with bus_width=4 (the default).
++
+ Name:   sdio-1bit
+ Info:   This overlay is now deprecated. Use
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -64,6 +64,14 @@
+               };
+       };
++      fragment@5 {
++              target = <&sdio_ovl_pins>;
++              __dormant__ {
++                      brcm,pins = <34 35 36 37 38 39>;
++                      brcm,pull = <0 2 2 2 2 2>;
++              };
++      };
++
+       fragment@6 {
+               target-path = "/aliases";
+               __overlay__ {
+@@ -77,5 +85,6 @@
+               sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
+               gpios_22_25 = <0>,"=3";
+               gpios_34_37 = <0>,"=4";
++              gpios_34_39 = <0>,"=5";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0328-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch b/target/linux/brcm2708/patches-4.19/950-0328-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch
deleted file mode 100644 (file)
index 4bf0c78..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From c42ae04bb6ed5be61d3b3e2e2c6004ae252ee34a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:26:00 +0000
-Subject: [PATCH] staging: bcm2835_codec: Clean up logging on unloading
- the driver
-
-The log line was missing a closing \n, so wasn't added to the
-log immediately.
-Adds the function of the V4L2 device that is being unregistered
-too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c   | 10 ++++++++--
- 1 file changed, 8 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
-@@ -77,6 +77,12 @@ enum bcm2835_codec_role {
-       ISP,
- };
-+const static char *roles[] = {
-+      "decode",
-+      "encode",
-+      "isp"
-+};
-+
- static const char * const components[] = {
-       "ril.video_decode",
-       "ril.video_encode",
-@@ -2522,7 +2528,6 @@ static int bcm2835_codec_create(struct p
-       struct video_device *vfd;
-       int video_nr;
-       int ret;
--      const static char *roles[] = {"decode", "encode", "isp"};
-       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-@@ -2615,7 +2620,8 @@ static int bcm2835_codec_destroy(struct
-       if (!dev)
-               return -ENODEV;
--      v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
-+      v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
-+                roles[dev->role]);
-       v4l2_m2m_release(dev->m2m_dev);
-       video_unregister_device(&dev->vfd);
-       v4l2_device_unregister(&dev->v4l2_dev);
diff --git a/target/linux/brcm2708/patches-4.19/950-0329-bcm2835-sdhost-Allow-for-sg-entries-that-cross-pages.patch b/target/linux/brcm2708/patches-4.19/950-0329-bcm2835-sdhost-Allow-for-sg-entries-that-cross-pages.patch
deleted file mode 100644 (file)
index e16e12d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From 44db7882be675cdf2d89741af5bbeba41b3e25af Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 13 Mar 2019 14:19:11 +0000
-Subject: [PATCH] bcm2835-sdhost: Allow for sg entries that cross pages
-
-The dma_complete handling code calculates a virtual address for a page
-then adds an offset, but if the offset is more than a page and HIGHMEM
-is in use then the summed address could be in an unmapped (or just
-incorrect) page.
-
-The upstream SDHOST driver allows for this possibility - copy the code
-that does so.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/bcm2835-sdhost.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/mmc/host/bcm2835-sdhost.c
-+++ b/drivers/mmc/host/bcm2835-sdhost.c
-@@ -543,6 +543,11 @@ static void bcm2835_sdhost_dma_complete(
-               void *page;
-               u32 *buf;
-+              if (host->drain_offset & PAGE_MASK) {
-+                      host->drain_page += host->drain_offset >> PAGE_SHIFT;
-+                      host->drain_offset &= ~PAGE_MASK;
-+              }
-+
-               page = kmap_atomic(host->drain_page);
-               buf = page + host->drain_offset;
diff --git a/target/linux/brcm2708/patches-4.19/950-0329-overlays-Fix-multiple-instantiation-of-sc16is7xx.patch b/target/linux/brcm2708/patches-4.19/950-0329-overlays-Fix-multiple-instantiation-of-sc16is7xx.patch
new file mode 100644 (file)
index 0000000..86fd110
--- /dev/null
@@ -0,0 +1,57 @@
+From 649efe5db3900ed3bbfd3c3daa3b96d8fc0b9d68 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 22 Mar 2019 16:44:47 +0000
+Subject: [PATCH] overlays: Fix multiple-instantiation of sc16is7xx*
+
+The registration of the fixed clocks uses the node name as the clock
+name, causing a clash if two clock nodes have the same name, regardless
+of the path to the node. Fix the issue by overwriting the clock node
+names using the value of the "addr" parameter, providing a crude
+disambiguation. (A bit of string pasting to form "sc16is752_clk_<addr>"
+would have been nice, but that is outside the abilities of the overlay
+parameter mechanism.)
+
+Also give the sc16is750-i2c overlay the xtal parameter for symmetry.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=235650
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README                    | 1 +
+ arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts | 3 ++-
+ arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts | 2 +-
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1725,6 +1725,7 @@ Info:   Overlay for the NXP SC16IS750 UA
+ Load:   dtoverlay=sc16is750-i2c,<param>=<val>
+ Params: int_pin                 GPIO used for IRQ (default 24)
+         addr                    Address (default 0x48)
++        xtal                    On-board crystal frequency (default 14745600)
+ Name:   sc16is752-i2c
+--- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
+@@ -31,7 +31,8 @@
+       __overrides__ {
+               int_pin = <&sc16is750>,"interrupts:0";
+-              addr = <&sc16is750>,"reg:0";
++              addr = <&sc16is750>,"reg:0",<&sc16is750_clk>,"name";
++              xtal = <&sc16is750>,"clock-frequency:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
+@@ -34,7 +34,7 @@
+       __overrides__ {
+               int_pin = <&sc16is752>,"interrupts:0";
+-              addr = <&sc16is752>,"reg:0";
++              addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name";
+               xtal = <&sc16is752>,"clock-frequency:0";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0330-bcm2835-mmc-Fix-DMA-channel-leak.patch b/target/linux/brcm2708/patches-4.19/950-0330-bcm2835-mmc-Fix-DMA-channel-leak.patch
new file mode 100644 (file)
index 0000000..1122e3c
--- /dev/null
@@ -0,0 +1,42 @@
+From 7458efc95816cc9d716d94a4894172c2a9d9fba7 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Wed, 16 Jan 2019 12:22:32 +0100
+Subject: [PATCH] bcm2835-mmc: Fix DMA channel leak
+
+The BCM2835 MMC host driver requests a DMA channel on probe but neglects
+to release the channel in the probe error path and on driver unbind.
+
+I'm seeing this happen on every boot of the Compute Module 3: On first
+driver probe, DMA channel 2 is allocated and then leaked with a "could
+not get clk, deferring probe" message. On second driver probe, channel 4
+is allocated.
+
+Fix it.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1503,6 +1503,8 @@ static int bcm2835_mmc_probe(struct plat
+       return 0;
+ err:
++      if (host->dma_chan_rxtx)
++              dma_release_channel(host->dma_chan_rxtx);
+       mmc_free_host(mmc);
+       return ret;
+@@ -1548,6 +1550,9 @@ static int bcm2835_mmc_remove(struct pla
+       tasklet_kill(&host->finish_tasklet);
++      if (host->dma_chan_rxtx)
++              dma_release_channel(host->dma_chan_rxtx);
++
+       mmc_free_host(host->mmc);
+       platform_set_drvdata(pdev, NULL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0330-overlays-sdio-Added-4-bit-support-on-GPIOs-34-39.-29.patch b/target/linux/brcm2708/patches-4.19/950-0330-overlays-sdio-Added-4-bit-support-on-GPIOs-34-39.-29.patch
deleted file mode 100644 (file)
index f823f67..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From 7c23c772289fa31960b9e6969499aa93c92d842b Mon Sep 17 00:00:00 2001
-From: Adrien RICCIARDI <RICCIARDI-Adrien@users.noreply.github.com>
-Date: Fri, 22 Mar 2019 11:35:30 +0100
-Subject: [PATCH] overlays: sdio: Added 4-bit support on GPIOs 34-39.
- (#2903)
-
----
- arch/arm/boot/dts/overlays/README           | 3 +++
- arch/arm/boot/dts/overlays/sdio-overlay.dts | 9 +++++++++
- 2 files changed, 12 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1785,6 +1785,9 @@ Params: sdio_overclock          SDIO Clo
-         gpios_34_37             Select GPIOs 34-37 for 1-bit mode. Must be used
-                                 with bus_width=1.
-+        gpios_34_39             Select GPIOs 34-39 for 4-bit mode. Must be used
-+                                with bus_width=4 (the default).
-+
- Name:   sdio-1bit
- Info:   This overlay is now deprecated. Use
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -64,6 +64,14 @@
-               };
-       };
-+      fragment@5 {
-+              target = <&sdio_ovl_pins>;
-+              __dormant__ {
-+                      brcm,pins = <34 35 36 37 38 39>;
-+                      brcm,pull = <0 2 2 2 2 2>;
-+              };
-+      };
-+
-       fragment@6 {
-               target-path = "/aliases";
-               __overlay__ {
-@@ -77,5 +85,6 @@
-               sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
-               gpios_22_25 = <0>,"=3";
-               gpios_34_37 = <0>,"=4";
-+              gpios_34_39 = <0>,"=5";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0331-bcm2835-mmc-Fix-struct-mmc_host-leak-on-probe.patch b/target/linux/brcm2708/patches-4.19/950-0331-bcm2835-mmc-Fix-struct-mmc_host-leak-on-probe.patch
new file mode 100644 (file)
index 0000000..9ec4404
--- /dev/null
@@ -0,0 +1,29 @@
+From 82ced13dc5805f6e49e2182269e672b20d8394bc Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 08:06:48 +0100
+Subject: [PATCH] bcm2835-mmc: Fix struct mmc_host leak on probe
+
+The BCM2835 MMC host driver requests the bus address of the host's
+register map on probe.  If that fails, the driver leaks the struct
+mmc_host allocated earlier.
+
+Fix it.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1439,7 +1439,8 @@ static int bcm2835_mmc_probe(struct plat
+       addr = of_get_address(node, 0, NULL, NULL);
+       if (!addr) {
+               dev_err(dev, "could not get DMA-register address\n");
+-              return -ENODEV;
++              ret = -ENODEV;
++              goto err;
+       }
+       host->bus_addr = be32_to_cpup(addr);
+       pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
diff --git a/target/linux/brcm2708/patches-4.19/950-0331-overlays-Fix-multiple-instantiation-of-sc16is7xx.patch b/target/linux/brcm2708/patches-4.19/950-0331-overlays-Fix-multiple-instantiation-of-sc16is7xx.patch
deleted file mode 100644 (file)
index 86fd110..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From 649efe5db3900ed3bbfd3c3daa3b96d8fc0b9d68 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 22 Mar 2019 16:44:47 +0000
-Subject: [PATCH] overlays: Fix multiple-instantiation of sc16is7xx*
-
-The registration of the fixed clocks uses the node name as the clock
-name, causing a clash if two clock nodes have the same name, regardless
-of the path to the node. Fix the issue by overwriting the clock node
-names using the value of the "addr" parameter, providing a crude
-disambiguation. (A bit of string pasting to form "sc16is752_clk_<addr>"
-would have been nice, but that is outside the abilities of the overlay
-parameter mechanism.)
-
-Also give the sc16is750-i2c overlay the xtal parameter for symmetry.
-
-See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=235650
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README                    | 1 +
- arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts | 3 ++-
- arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts | 2 +-
- 3 files changed, 4 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1725,6 +1725,7 @@ Info:   Overlay for the NXP SC16IS750 UA
- Load:   dtoverlay=sc16is750-i2c,<param>=<val>
- Params: int_pin                 GPIO used for IRQ (default 24)
-         addr                    Address (default 0x48)
-+        xtal                    On-board crystal frequency (default 14745600)
- Name:   sc16is752-i2c
---- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-@@ -31,7 +31,8 @@
-       __overrides__ {
-               int_pin = <&sc16is750>,"interrupts:0";
--              addr = <&sc16is750>,"reg:0";
-+              addr = <&sc16is750>,"reg:0",<&sc16is750_clk>,"name";
-+              xtal = <&sc16is750>,"clock-frequency:0";
-       };
- };
---- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
-@@ -34,7 +34,7 @@
-       __overrides__ {
-               int_pin = <&sc16is752>,"interrupts:0";
--              addr = <&sc16is752>,"reg:0";
-+              addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name";
-               xtal = <&sc16is752>,"clock-frequency:0";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0332-bcm2835-mmc-Fix-DMA-channel-leak.patch b/target/linux/brcm2708/patches-4.19/950-0332-bcm2835-mmc-Fix-DMA-channel-leak.patch
deleted file mode 100644 (file)
index 1122e3c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 7458efc95816cc9d716d94a4894172c2a9d9fba7 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Wed, 16 Jan 2019 12:22:32 +0100
-Subject: [PATCH] bcm2835-mmc: Fix DMA channel leak
-
-The BCM2835 MMC host driver requests a DMA channel on probe but neglects
-to release the channel in the probe error path and on driver unbind.
-
-I'm seeing this happen on every boot of the Compute Module 3: On first
-driver probe, DMA channel 2 is allocated and then leaked with a "could
-not get clk, deferring probe" message. On second driver probe, channel 4
-is allocated.
-
-Fix it.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1503,6 +1503,8 @@ static int bcm2835_mmc_probe(struct plat
-       return 0;
- err:
-+      if (host->dma_chan_rxtx)
-+              dma_release_channel(host->dma_chan_rxtx);
-       mmc_free_host(mmc);
-       return ret;
-@@ -1548,6 +1550,9 @@ static int bcm2835_mmc_remove(struct pla
-       tasklet_kill(&host->finish_tasklet);
-+      if (host->dma_chan_rxtx)
-+              dma_release_channel(host->dma_chan_rxtx);
-+
-       mmc_free_host(host->mmc);
-       platform_set_drvdata(pdev, NULL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0332-bcm2835-mmc-Fix-duplicate-free_irq-on-remove.patch b/target/linux/brcm2708/patches-4.19/950-0332-bcm2835-mmc-Fix-duplicate-free_irq-on-remove.patch
new file mode 100644 (file)
index 0000000..0ca7c11
--- /dev/null
@@ -0,0 +1,38 @@
+From 4a15e086fa9531f808c15b8fb8d7ed1fdb411b74 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 09:00:26 +0100
+Subject: [PATCH] bcm2835-mmc: Fix duplicate free_irq() on remove
+
+The BCM2835 MMC host driver requests its interrupt as a device-managed
+resource, so the interrupt is automatically freed after the driver is
+unbound.
+
+However on driver unbind, bcm2835_mmc_remove() frees the interrupt
+explicitly to avoid invocation of the interrupt handler after driver
+structures have been torn down.
+
+The interrupt is thus freed twice, leading to a WARN splat in
+__free_irq().  Fix by not requesting the interrupt as a device-managed
+resource.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1389,9 +1389,9 @@ static int bcm2835_mmc_add_host(struct b
+       init_waitqueue_head(&host->buf_ready_int);
+       bcm2835_mmc_init(host, 0);
+-      ret = devm_request_threaded_irq(dev, host->irq, bcm2835_mmc_irq,
+-                                      bcm2835_mmc_thread_irq, IRQF_SHARED,
+-                                      mmc_hostname(mmc), host);
++      ret = request_threaded_irq(host->irq, bcm2835_mmc_irq,
++                                 bcm2835_mmc_thread_irq, IRQF_SHARED,
++                                 mmc_hostname(mmc), host);
+       if (ret) {
+               dev_err(dev, "Failed to request IRQ %d: %d\n", host->irq, ret);
+               goto untasklet;
diff --git a/target/linux/brcm2708/patches-4.19/950-0333-bcm2835-mmc-Fix-struct-mmc_host-leak-on-probe.patch b/target/linux/brcm2708/patches-4.19/950-0333-bcm2835-mmc-Fix-struct-mmc_host-leak-on-probe.patch
deleted file mode 100644 (file)
index 9ec4404..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 82ced13dc5805f6e49e2182269e672b20d8394bc Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Sat, 19 Jan 2019 08:06:48 +0100
-Subject: [PATCH] bcm2835-mmc: Fix struct mmc_host leak on probe
-
-The BCM2835 MMC host driver requests the bus address of the host's
-register map on probe.  If that fails, the driver leaks the struct
-mmc_host allocated earlier.
-
-Fix it.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1439,7 +1439,8 @@ static int bcm2835_mmc_probe(struct plat
-       addr = of_get_address(node, 0, NULL, NULL);
-       if (!addr) {
-               dev_err(dev, "could not get DMA-register address\n");
--              return -ENODEV;
-+              ret = -ENODEV;
-+              goto err;
-       }
-       host->bus_addr = be32_to_cpup(addr);
-       pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
diff --git a/target/linux/brcm2708/patches-4.19/950-0333-bcm2835-mmc-Handle-mmc_add_host-errors.patch b/target/linux/brcm2708/patches-4.19/950-0333-bcm2835-mmc-Handle-mmc_add_host-errors.patch
new file mode 100644 (file)
index 0000000..3762f4b
--- /dev/null
@@ -0,0 +1,35 @@
+From 2e2f57e09e1ace18ae01a87d9fc4378c96c54370 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Tue, 22 Jan 2019 12:29:45 +0100
+Subject: [PATCH] bcm2835-mmc: Handle mmc_add_host() errors
+
+The BCM2835 MMC host driver calls mmc_add_host() but doesn't check its
+return value.  Errors occurring in that function are therefore not
+handled.  Fix it.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1398,10 +1398,16 @@ static int bcm2835_mmc_add_host(struct b
+       }
+       mmiowb();
+-      mmc_add_host(mmc);
++      ret = mmc_add_host(mmc);
++      if (ret) {
++              dev_err(dev, "could not add MMC host\n");
++              goto free_irq;
++      }
+       return 0;
++free_irq:
++      free_irq(host->irq, host);
+ untasklet:
+       tasklet_kill(&host->finish_tasklet);
diff --git a/target/linux/brcm2708/patches-4.19/950-0334-bcm2835-mmc-Deduplicate-reset-of-driver-data-on-remo.patch b/target/linux/brcm2708/patches-4.19/950-0334-bcm2835-mmc-Deduplicate-reset-of-driver-data-on-remo.patch
new file mode 100644 (file)
index 0000000..ed3910d
--- /dev/null
@@ -0,0 +1,26 @@
+From 3f6e190df3989e10a9baf591a7bf67d754842533 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 08:42:40 +0100
+Subject: [PATCH] bcm2835-mmc: Deduplicate reset of driver data on
+ remove
+
+The BCM2835 MMC host driver sets the device's driver data pointer to
+NULL on ->remove() even though the driver core subsequently does the
+same in __device_release_driver().  Drop the duplicate assignment.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1561,7 +1561,6 @@ static int bcm2835_mmc_remove(struct pla
+               dma_release_channel(host->dma_chan_rxtx);
+       mmc_free_host(host->mmc);
+-      platform_set_drvdata(pdev, NULL);
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0334-bcm2835-mmc-Fix-duplicate-free_irq-on-remove.patch b/target/linux/brcm2708/patches-4.19/950-0334-bcm2835-mmc-Fix-duplicate-free_irq-on-remove.patch
deleted file mode 100644 (file)
index 0ca7c11..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 4a15e086fa9531f808c15b8fb8d7ed1fdb411b74 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Sat, 19 Jan 2019 09:00:26 +0100
-Subject: [PATCH] bcm2835-mmc: Fix duplicate free_irq() on remove
-
-The BCM2835 MMC host driver requests its interrupt as a device-managed
-resource, so the interrupt is automatically freed after the driver is
-unbound.
-
-However on driver unbind, bcm2835_mmc_remove() frees the interrupt
-explicitly to avoid invocation of the interrupt handler after driver
-structures have been torn down.
-
-The interrupt is thus freed twice, leading to a WARN splat in
-__free_irq().  Fix by not requesting the interrupt as a device-managed
-resource.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1389,9 +1389,9 @@ static int bcm2835_mmc_add_host(struct b
-       init_waitqueue_head(&host->buf_ready_int);
-       bcm2835_mmc_init(host, 0);
--      ret = devm_request_threaded_irq(dev, host->irq, bcm2835_mmc_irq,
--                                      bcm2835_mmc_thread_irq, IRQF_SHARED,
--                                      mmc_hostname(mmc), host);
-+      ret = request_threaded_irq(host->irq, bcm2835_mmc_irq,
-+                                 bcm2835_mmc_thread_irq, IRQF_SHARED,
-+                                 mmc_hostname(mmc), host);
-       if (ret) {
-               dev_err(dev, "Failed to request IRQ %d: %d\n", host->irq, ret);
-               goto untasklet;
diff --git a/target/linux/brcm2708/patches-4.19/950-0335-bcm2835-mmc-Handle-mmc_add_host-errors.patch b/target/linux/brcm2708/patches-4.19/950-0335-bcm2835-mmc-Handle-mmc_add_host-errors.patch
deleted file mode 100644 (file)
index 3762f4b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From 2e2f57e09e1ace18ae01a87d9fc4378c96c54370 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Tue, 22 Jan 2019 12:29:45 +0100
-Subject: [PATCH] bcm2835-mmc: Handle mmc_add_host() errors
-
-The BCM2835 MMC host driver calls mmc_add_host() but doesn't check its
-return value.  Errors occurring in that function are therefore not
-handled.  Fix it.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1398,10 +1398,16 @@ static int bcm2835_mmc_add_host(struct b
-       }
-       mmiowb();
--      mmc_add_host(mmc);
-+      ret = mmc_add_host(mmc);
-+      if (ret) {
-+              dev_err(dev, "could not add MMC host\n");
-+              goto free_irq;
-+      }
-       return 0;
-+free_irq:
-+      free_irq(host->irq, host);
- untasklet:
-       tasklet_kill(&host->finish_tasklet);
diff --git a/target/linux/brcm2708/patches-4.19/950-0335-overlays-Add-max17040-support-to-i2c-sensor.patch b/target/linux/brcm2708/patches-4.19/950-0335-overlays-Add-max17040-support-to-i2c-sensor.patch
new file mode 100644 (file)
index 0000000..e87cf1a
--- /dev/null
@@ -0,0 +1,56 @@
+From fe6ccc8df700133615716df211f183c9c27d1e2e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 25 Mar 2019 18:03:48 +0000
+Subject: [PATCH] overlays: Add max17040 support to i2c-sensor
+
+See: https://github.com/raspberrypi/linux/issues/2906
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README                |  3 +++
+ .../arm/boot/dts/overlays/i2c-sensor-overlay.dts | 16 ++++++++++++++++
+ 2 files changed, 19 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1030,6 +1030,9 @@ Params: addr                    Set the
+         lm75addr                Deprecated - use addr parameter instead
++        max17040                Select the Maxim Integrated MAX17040 battery
++                                monitor
++
+         sht3x                   Select the Sensiron SHT3x temperature and
+                                 humidity sensor. Valid addresses 0x44-0x45,
+                                 default 0x44
+--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
+@@ -201,6 +201,21 @@
+               };
+       };
++      fragment@13 {
++              target = <&i2c_arm>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      max17040: max17040@36 {
++                              compatible = "maxim,max17040";
++                              reg = <0x36>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               addr =  <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0",
+                       <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0",
+@@ -219,5 +234,6 @@
+               veml6070 = <0>,"+10";
+               sht3x = <0>,"+11";
+               ds1621 = <0>,"+12";
++              max17040 = <0>,"+13";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0336-bcm2835-mmc-Deduplicate-reset-of-driver-data-on-remo.patch b/target/linux/brcm2708/patches-4.19/950-0336-bcm2835-mmc-Deduplicate-reset-of-driver-data-on-remo.patch
deleted file mode 100644 (file)
index ed3910d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 3f6e190df3989e10a9baf591a7bf67d754842533 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Sat, 19 Jan 2019 08:42:40 +0100
-Subject: [PATCH] bcm2835-mmc: Deduplicate reset of driver data on
- remove
-
-The BCM2835 MMC host driver sets the device's driver data pointer to
-NULL on ->remove() even though the driver core subsequently does the
-same in __device_release_driver().  Drop the duplicate assignment.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1561,7 +1561,6 @@ static int bcm2835_mmc_remove(struct pla
-               dma_release_channel(host->dma_chan_rxtx);
-       mmc_free_host(host->mmc);
--      platform_set_drvdata(pdev, NULL);
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0336-media-bcm2835-unicam-Add-support-for-enum-framesizes.patch b/target/linux/brcm2708/patches-4.19/950-0336-media-bcm2835-unicam-Add-support-for-enum-framesizes.patch
new file mode 100644 (file)
index 0000000..c1686f5
--- /dev/null
@@ -0,0 +1,133 @@
+From 7c876909bc0a6d23124689d5fca89657a4fcb5a5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 5 Mar 2019 15:43:27 +0000
+Subject: [PATCH] media: bcm2835-unicam: Add support for enum
+ framesizes and frameintervals
+
+vidioc_enum_framesizes and vidioc_enum_frameintervals weren't implemented,
+therefore clients couldn't enumerate the supported resolutions.
+
+Implement them by forwarding on to the sensor driver.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 94 +++++++++++++++++++
+ 1 file changed, 94 insertions(+)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1406,6 +1406,84 @@ static int unicam_g_edid(struct file *fi
+       return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
+ }
++static int unicam_enum_framesizes(struct file *file, void *priv,
++                                struct v4l2_frmsizeenum *fsize)
++{
++      struct unicam_device *dev = video_drvdata(file);
++      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.index = fsize->index;
++      fse.pad = 0;
++      fse.code = fmt->code;
++
++      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_device *dev = video_drvdata(file);
++      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_device *dev = video_drvdata(file);
++
++      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_device *dev = video_drvdata(file);
++
++      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)
+ {
+@@ -1613,6 +1691,12 @@ static const struct v4l2_ioctl_ops unica
+       .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_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,
+@@ -1850,6 +1934,16 @@ static int unicam_probe_complete(struct
+               v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_DV_TIMINGS);
+               v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_QUERY_DV_TIMINGS);
+       }
++      if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
++              v4l2_disable_ioctl(&unicam->video_dev,
++                                 VIDIOC_ENUM_FRAMEINTERVALS);
++      if (!v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
++              v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_G_PARM);
++      if (!v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
++              v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_S_PARM);
++
++      if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
++              v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_FRAMESIZES);
+       ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev);
+       if (ret) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0337-overlays-Add-max17040-support-to-i2c-sensor.patch b/target/linux/brcm2708/patches-4.19/950-0337-overlays-Add-max17040-support-to-i2c-sensor.patch
deleted file mode 100644 (file)
index e87cf1a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From fe6ccc8df700133615716df211f183c9c27d1e2e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 25 Mar 2019 18:03:48 +0000
-Subject: [PATCH] overlays: Add max17040 support to i2c-sensor
-
-See: https://github.com/raspberrypi/linux/issues/2906
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README                |  3 +++
- .../arm/boot/dts/overlays/i2c-sensor-overlay.dts | 16 ++++++++++++++++
- 2 files changed, 19 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1030,6 +1030,9 @@ Params: addr                    Set the
-         lm75addr                Deprecated - use addr parameter instead
-+        max17040                Select the Maxim Integrated MAX17040 battery
-+                                monitor
-+
-         sht3x                   Select the Sensiron SHT3x temperature and
-                                 humidity sensor. Valid addresses 0x44-0x45,
-                                 default 0x44
---- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-@@ -201,6 +201,21 @@
-               };
-       };
-+      fragment@13 {
-+              target = <&i2c_arm>;
-+              __dormant__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      max17040: max17040@36 {
-+                              compatible = "maxim,max17040";
-+                              reg = <0x36>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-       __overrides__ {
-               addr =  <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0",
-                       <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0",
-@@ -219,5 +234,6 @@
-               veml6070 = <0>,"+10";
-               sht3x = <0>,"+11";
-               ds1621 = <0>,"+12";
-+              max17040 = <0>,"+13";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0337-staging-bcm2835-codec-Refactor-default-resolution-co.patch b/target/linux/brcm2708/patches-4.19/950-0337-staging-bcm2835-codec-Refactor-default-resolution-co.patch
new file mode 100644 (file)
index 0000000..cd592e2
--- /dev/null
@@ -0,0 +1,154 @@
+From a97baa799a8069fe965a4d194935c025e21acf8e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 20 Mar 2019 10:06:51 +0000
+Subject: [PATCH] staging: bcm2835-codec: Refactor default resolution
+ code
+
+The default resolution code was different for each role
+as compressed formats need to pass bytesperline as 0 and
+set up customised buffer sizes.
+This is common setup, therefore amend get_sizeimage and
+get_bytesperline to do the correct thing whether compressed
+or uncompressed.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 103 +++++++-----------
+ 1 file changed, 40 insertions(+), 63 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -578,10 +578,17 @@ static void job_abort(void *priv)
+       ctx->aborting = 1;
+ }
+-static inline unsigned int get_sizeimage(int bpl, int height,
++static inline unsigned int get_sizeimage(int bpl, int width, int height,
+                                        struct bcm2835_codec_fmt *fmt)
+ {
+-      return (bpl * height * fmt->size_multiplier_x2) >> 1;
++      if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
++              if (width * height > 1280 * 720)
++                      return DEF_COMP_BUF_SIZE_GREATER_720P;
++              else
++                      return DEF_COMP_BUF_SIZE_720P_OR_LESS;
++      } else {
++              return (bpl * height * fmt->size_multiplier_x2) >> 1;
++      }
+ }
+ static inline unsigned int get_bytesperline(int width,
+@@ -1032,22 +1039,13 @@ static int vidioc_try_fmt(struct v4l2_fo
+                * some of the pixels are active.
+                */
+               f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
+-
+-              f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
+-                                                         fmt);
+-              f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
+-                                                   f->fmt.pix.height,
+-                                                   fmt);
+-      } else {
+-              u32 min_size = f->fmt.pix.width > 1280 ||
+-                             f->fmt.pix.height > 720 ?
+-                             DEF_COMP_BUF_SIZE_GREATER_720P :
+-                             DEF_COMP_BUF_SIZE_720P_OR_LESS;
+-
+-              f->fmt.pix.bytesperline = 0;
+-              if (f->fmt.pix.sizeimage < min_size)
+-                      f->fmt.pix.sizeimage = min_size;
+       }
++      f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
++                                                 fmt);
++      f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
++                                           f->fmt.pix.width,
++                                           f->fmt.pix.height,
++                                           fmt);
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+@@ -1159,6 +1157,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+               q_data_dst->bytesperline =
+                       get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
+               q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
++                                                    q_data_dst->crop_width,
+                                                     q_data_dst->height,
+                                                     q_data_dst->fmt);
+               update_capture_port = true;
+@@ -2218,52 +2217,30 @@ static int bcm2835_codec_open(struct fil
+       ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
+       ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
+-      switch (dev->role) {
+-      case DECODE:
+-              /*
+-               * Input width and height are irrelevant as they will be defined
+-               * by the bitstream not the format. Required by V4L2 though.
+-               */
+-              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
+-              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
+-              ctx->q_data[V4L2_M2M_SRC].sizeimage =
+-                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
+-
+-              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
+-              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_DST].bytesperline =
+-                              get_bytesperline(DEFAULT_WIDTH,
+-                                               ctx->q_data[V4L2_M2M_DST].fmt);
+-              ctx->q_data[V4L2_M2M_DST].sizeimage =
+-                      get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
+-                                    ctx->q_data[V4L2_M2M_DST].height,
+-                                    ctx->q_data[V4L2_M2M_DST].fmt);
+-              break;
+-      case ENCODE:
+-              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
+-              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_SRC].bytesperline =
+-                              get_bytesperline(DEFAULT_WIDTH,
+-                                               ctx->q_data[V4L2_M2M_SRC].fmt);
+-              ctx->q_data[V4L2_M2M_SRC].sizeimage =
+-                      get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
+-                                    ctx->q_data[V4L2_M2M_SRC].height,
+-                                    ctx->q_data[V4L2_M2M_SRC].fmt);
+-
+-              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
+-              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
+-              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
+-              ctx->q_data[V4L2_M2M_DST].sizeimage =
+-                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
+-              break;
+-      case ISP:
+-              break;
+-      }
++
++      ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
++      ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
++      ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
++      ctx->q_data[V4L2_M2M_SRC].bytesperline =
++                      get_bytesperline(DEFAULT_WIDTH,
++                                       ctx->q_data[V4L2_M2M_SRC].fmt);
++      ctx->q_data[V4L2_M2M_SRC].sizeimage =
++              get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
++                            ctx->q_data[V4L2_M2M_SRC].crop_width,
++                            ctx->q_data[V4L2_M2M_SRC].height,
++                            ctx->q_data[V4L2_M2M_SRC].fmt);
++
++      ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
++      ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
++      ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
++      ctx->q_data[V4L2_M2M_DST].bytesperline =
++                      get_bytesperline(DEFAULT_WIDTH,
++                                       ctx->q_data[V4L2_M2M_DST].fmt);
++      ctx->q_data[V4L2_M2M_DST].sizeimage =
++              get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
++                            ctx->q_data[V4L2_M2M_DST].crop_width,
++                            ctx->q_data[V4L2_M2M_DST].height,
++                            ctx->q_data[V4L2_M2M_DST].fmt);
+       ctx->colorspace = V4L2_COLORSPACE_REC709;
+       ctx->bitrate = 10 * 1000 * 1000;
diff --git a/target/linux/brcm2708/patches-4.19/950-0338-media-bcm2835-unicam-Add-support-for-enum-framesizes.patch b/target/linux/brcm2708/patches-4.19/950-0338-media-bcm2835-unicam-Add-support-for-enum-framesizes.patch
deleted file mode 100644 (file)
index c1686f5..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-From 7c876909bc0a6d23124689d5fca89657a4fcb5a5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 5 Mar 2019 15:43:27 +0000
-Subject: [PATCH] media: bcm2835-unicam: Add support for enum
- framesizes and frameintervals
-
-vidioc_enum_framesizes and vidioc_enum_frameintervals weren't implemented,
-therefore clients couldn't enumerate the supported resolutions.
-
-Implement them by forwarding on to the sensor driver.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c   | 94 +++++++++++++++++++
- 1 file changed, 94 insertions(+)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -1406,6 +1406,84 @@ static int unicam_g_edid(struct file *fi
-       return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
- }
-+static int unicam_enum_framesizes(struct file *file, void *priv,
-+                                struct v4l2_frmsizeenum *fsize)
-+{
-+      struct unicam_device *dev = video_drvdata(file);
-+      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.index = fsize->index;
-+      fse.pad = 0;
-+      fse.code = fmt->code;
-+
-+      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_device *dev = video_drvdata(file);
-+      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_device *dev = video_drvdata(file);
-+
-+      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_device *dev = video_drvdata(file);
-+
-+      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)
- {
-@@ -1613,6 +1691,12 @@ static const struct v4l2_ioctl_ops unica
-       .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_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,
-@@ -1850,6 +1934,16 @@ static int unicam_probe_complete(struct
-               v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_DV_TIMINGS);
-               v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_QUERY_DV_TIMINGS);
-       }
-+      if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
-+              v4l2_disable_ioctl(&unicam->video_dev,
-+                                 VIDIOC_ENUM_FRAMEINTERVALS);
-+      if (!v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
-+              v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_G_PARM);
-+      if (!v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
-+              v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_S_PARM);
-+
-+      if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
-+              v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_FRAMESIZES);
-       ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev);
-       if (ret) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0338-nvmem-add-type-attribute.patch b/target/linux/brcm2708/patches-4.19/950-0338-nvmem-add-type-attribute.patch
new file mode 100644 (file)
index 0000000..661ba8e
--- /dev/null
@@ -0,0 +1,131 @@
+From c9e76146066660a2884e61216c1ce227cf509bf8 Mon Sep 17 00:00:00 2001
+From: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Date: Fri, 30 Nov 2018 11:53:20 +0000
+Subject: [PATCH] nvmem: add type attribute
+
+commit 16688453661b6d5159be558a1f8c1f54463a420f upstream.
+
+Add a type attribute so userspace is able to know how the data is stored as
+this can help taking the correct decision when selecting which device to
+use. This will also help program display the proper warnings when burning
+fuses for example.
+
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c           | 21 +++++++++++++++++++++
+ include/linux/nvmem-provider.h | 16 ++++++++++++++++
+ 2 files changed, 37 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -36,6 +36,7 @@ struct nvmem_device {
+       size_t                  size;
+       bool                    read_only;
+       int                     flags;
++      enum nvmem_type         type;
+       struct bin_attribute    eeprom;
+       struct device           *base_dev;
+       nvmem_reg_read_t        reg_read;
+@@ -84,6 +85,21 @@ static int nvmem_reg_write(struct nvmem_
+       return -EINVAL;
+ }
++static ssize_t type_show(struct device *dev,
++                       struct device_attribute *attr, char *buf)
++{
++      struct nvmem_device *nvmem = to_nvmem_device(dev);
++
++      return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
++}
++
++static DEVICE_ATTR_RO(type);
++
++static struct attribute *nvmem_attrs[] = {
++      &dev_attr_type.attr,
++      NULL,
++};
++
+ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
+                                   struct bin_attribute *attr,
+                                   char *buf, loff_t pos, size_t count)
+@@ -169,6 +185,7 @@ static struct bin_attribute *nvmem_bin_r
+ static const struct attribute_group nvmem_bin_rw_group = {
+       .bin_attrs      = nvmem_bin_rw_attributes,
++      .attrs          = nvmem_attrs,
+ };
+ static const struct attribute_group *nvmem_rw_dev_groups[] = {
+@@ -192,6 +209,7 @@ static struct bin_attribute *nvmem_bin_r
+ static const struct attribute_group nvmem_bin_ro_group = {
+       .bin_attrs      = nvmem_bin_ro_attributes,
++      .attrs          = nvmem_attrs,
+ };
+ static const struct attribute_group *nvmem_ro_dev_groups[] = {
+@@ -216,6 +234,7 @@ static struct bin_attribute *nvmem_bin_r
+ static const struct attribute_group nvmem_bin_rw_root_group = {
+       .bin_attrs      = nvmem_bin_rw_root_attributes,
++      .attrs          = nvmem_attrs,
+ };
+ static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
+@@ -239,6 +258,7 @@ static struct bin_attribute *nvmem_bin_r
+ static const struct attribute_group nvmem_bin_ro_root_group = {
+       .bin_attrs      = nvmem_bin_ro_root_attributes,
++      .attrs          = nvmem_attrs,
+ };
+ static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
+@@ -485,6 +505,7 @@ struct nvmem_device *nvmem_register(cons
+       nvmem->dev.bus = &nvmem_bus_type;
+       nvmem->dev.parent = config->dev;
+       nvmem->priv = config->priv;
++      nvmem->type = config->type;
+       nvmem->reg_read = config->reg_read;
+       nvmem->reg_write = config->reg_write;
+       nvmem->dev.of_node = config->dev->of_node;
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -22,6 +22,20 @@ typedef int (*nvmem_reg_read_t)(void *pr
+ typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
+                                void *val, size_t bytes);
++enum nvmem_type {
++      NVMEM_TYPE_UNKNOWN = 0,
++      NVMEM_TYPE_EEPROM,
++      NVMEM_TYPE_OTP,
++      NVMEM_TYPE_BATTERY_BACKED,
++};
++
++static const char * const nvmem_type_str[] = {
++      [NVMEM_TYPE_UNKNOWN] = "Unknown",
++      [NVMEM_TYPE_EEPROM] = "EEPROM",
++      [NVMEM_TYPE_OTP] = "OTP",
++      [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
++};
++
+ /**
+  * struct nvmem_config - NVMEM device configuration
+  *
+@@ -31,6 +45,7 @@ typedef int (*nvmem_reg_write_t)(void *p
+  * @owner:    Pointer to exporter module. Used for refcounting.
+  * @cells:    Optional array of pre-defined NVMEM cells.
+  * @ncells:   Number of elements in cells.
++ * @type:     Type of the nvmem storage
+  * @read_only:        Device is read-only.
+  * @root_only:        Device is accessibly to root only.
+  * @reg_read: Callback to read data.
+@@ -54,6 +69,7 @@ struct nvmem_config {
+       struct module           *owner;
+       const struct nvmem_cell_info    *cells;
+       int                     ncells;
++      enum nvmem_type         type;
+       bool                    read_only;
+       bool                    root_only;
+       nvmem_reg_read_t        reg_read;
diff --git a/target/linux/brcm2708/patches-4.19/950-0339-rtc-rv3028-add-new-driver.patch b/target/linux/brcm2708/patches-4.19/950-0339-rtc-rv3028-add-new-driver.patch
new file mode 100644 (file)
index 0000000..6a00e82
--- /dev/null
@@ -0,0 +1,860 @@
+From bb0e317bfc453877805a12f975490ad38b6413f1 Mon Sep 17 00:00:00 2001
+From: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Date: Wed, 13 Feb 2019 00:21:36 +0100
+Subject: [PATCH] rtc: rv3028: add new driver
+
+upstream commit e6e7376cfd7b3f9b63de3a22792f64d9bfb2ab53.
+
+Add a driver for the MicroCrystal RV-3028. It is a SMT Real-Time Clock
+Module that incorporates an integrated CMOS circuit together with an XTAL.
+It has an i2c interface.
+
+The driver handles date/time, alarms, trickle charging, timestamping,
+frequency offset correction, EEPROM and NVRAM.
+
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+---
+ Documentation/devicetree/bindings/rtc/rtc.txt |  69 ++
+ drivers/rtc/Kconfig                           |   9 +
+ drivers/rtc/Makefile                          |   1 +
+ drivers/rtc/rtc-rv3028.c                      | 733 ++++++++++++++++++
+ 4 files changed, 812 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/rtc/rtc.txt
+ create mode 100644 drivers/rtc/rtc-rv3028.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/rtc/rtc.txt
+@@ -0,0 +1,69 @@
++Generic device tree bindings for Real Time Clock devices
++========================================================
++
++This document describes generic bindings which can be used to describe Real Time
++Clock devices in a device tree.
++
++Required properties
++-------------------
++
++- compatible : name of RTC device following generic names recommended practice.
++
++For other required properties e.g. to describe register sets,
++clocks, etc. check the binding documentation of the specific driver.
++
++Optional properties
++-------------------
++
++- start-year : if provided, the default hardware range supported by the RTC is
++               shifted so the first usable year is the specified one.
++
++The following properties may not be supported by all drivers. However, if a
++driver wants to support one of the below features, it should adapt the bindings
++below.
++- trickle-resistor-ohms :   Selected resistor for trickle charger. Should be given
++                            if trickle charger should be enabled
++- trickle-diode-disable :   Do not use internal trickle charger diode Should be
++                            given if internal trickle charger diode should be
++                            disabled
++- wakeup-source :           Enables wake up of host system on alarm
++- quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
++                            expressed in femto Farad (fF).
++                            The default value shall be listed (if optional),
++                            and likewise all valid values.
++
++Trivial RTCs
++------------
++
++This is a list of trivial RTC devices that have simple device tree
++bindings, consisting only of a compatible field, an address and
++possibly an interrupt line.
++
++
++Compatible            Vendor / Chip
++==========            =============
++abracon,abb5zes3      AB-RTCMC-32.768kHz-B5ZE-S3: Real Time Clock/Calendar Module with I2C Interface
++dallas,ds1374         I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
++dallas,ds1672         Dallas DS1672 Real-time Clock
++dallas,ds3232         Extremely Accurate I²C RTC with Integrated Crystal and SRAM
++epson,rx8010          I2C-BUS INTERFACE REAL TIME CLOCK MODULE
++epson,rx8581          I2C-BUS INTERFACE REAL TIME CLOCK MODULE
++emmicro,em3027                EM Microelectronic EM3027 Real-time Clock
++isil,isl1208          Intersil ISL1208 Low Power RTC with Battery Backed SRAM
++isil,isl1218          Intersil ISL1218 Low Power RTC with Battery Backed SRAM
++isil,isl12022         Intersil ISL12022 Real-time Clock
++microcrystal,rv3028   Real Time Clock Module with I2C-Bus
++microcrystal,rv3029   Real Time Clock Module with I2C-Bus
++microcrystal,rv8523   Real Time Clock
++nxp,pcf2127           Real-time clock
++nxp,pcf2129           Real-time clock
++nxp,pcf8563           Real-time clock/calendar
++pericom,pt7c4338      Real-time Clock Module
++ricoh,r2025sd         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,r2221tl         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rs5c372a                I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rs5c372b                I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rv5c386         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rv5c387a                I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++sii,s35390a           2-wire CMOS real-time clock
++whwave,sd3078         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -625,6 +625,15 @@ config RTC_DRV_EM3027
+         This driver can also be built as a module. If so, the module
+         will be called rtc-em3027.
++config RTC_DRV_RV3028
++      tristate "Micro Crystal RV3028"
++      help
++        If you say yes here you get support for the Micro Crystal
++        RV3028.
++
++        This driver can also be built as a module. If so, the module
++        will be called rtc-rv3028.
++
+ config RTC_DRV_RV8803
+       tristate "Micro Crystal RV8803, Epson RX8900"
+       help
+--- a/drivers/rtc/Makefile
++++ b/drivers/rtc/Makefile
+@@ -136,6 +136,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313)      += rtc-rs5
+ obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
+ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
+ obj-$(CONFIG_RTC_DRV_RTD119X) += rtc-rtd119x.o
++obj-$(CONFIG_RTC_DRV_RV3028)  += rtc-rv3028.o
+ obj-$(CONFIG_RTC_DRV_RV3029C2)        += rtc-rv3029c2.o
+ obj-$(CONFIG_RTC_DRV_RV8803)  += rtc-rv8803.o
+ obj-$(CONFIG_RTC_DRV_RX4581)  += rtc-rx4581.o
+--- /dev/null
++++ b/drivers/rtc/rtc-rv3028.c
+@@ -0,0 +1,733 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * RTC driver for the Micro Crystal RV3028
++ *
++ * Copyright (C) 2019 Micro Crystal SA
++ *
++ * Alexandre Belloni <alexandre.belloni@bootlin.com>
++ *
++ */
++
++#include <linux/bcd.h>
++#include <linux/bitops.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/log2.h>
++#include <linux/module.h>
++#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
++#define RV3028_HOUR                   0x02
++#define RV3028_WDAY                   0x03
++#define RV3028_DAY                    0x04
++#define RV3028_MONTH                  0x05
++#define RV3028_YEAR                   0x06
++#define RV3028_ALARM_MIN              0x07
++#define RV3028_ALARM_HOUR             0x08
++#define RV3028_ALARM_DAY              0x09
++#define RV3028_STATUS                 0x0E
++#define RV3028_CTRL1                  0x0F
++#define RV3028_CTRL2                  0x10
++#define RV3028_EVT_CTRL                       0x13
++#define RV3028_TS_COUNT                       0x14
++#define RV3028_TS_SEC                 0x15
++#define RV3028_RAM1                   0x1F
++#define RV3028_EEPROM_ADDR            0x25
++#define RV3028_EEPROM_DATA            0x26
++#define RV3028_EEPROM_CMD             0x27
++#define RV3028_CLKOUT                 0x35
++#define RV3028_OFFSET                 0x36
++#define RV3028_BACKUP                 0x37
++
++#define RV3028_STATUS_PORF            BIT(0)
++#define RV3028_STATUS_EVF             BIT(1)
++#define RV3028_STATUS_AF              BIT(2)
++#define RV3028_STATUS_TF              BIT(3)
++#define RV3028_STATUS_UF              BIT(4)
++#define RV3028_STATUS_BSF             BIT(5)
++#define RV3028_STATUS_CLKF            BIT(6)
++#define RV3028_STATUS_EEBUSY          BIT(7)
++
++#define RV3028_CTRL1_EERD             BIT(3)
++#define RV3028_CTRL1_WADA             BIT(5)
++
++#define RV3028_CTRL2_RESET            BIT(0)
++#define RV3028_CTRL2_12_24            BIT(1)
++#define RV3028_CTRL2_EIE              BIT(2)
++#define RV3028_CTRL2_AIE              BIT(3)
++#define RV3028_CTRL2_TIE              BIT(4)
++#define RV3028_CTRL2_UIE              BIT(5)
++#define RV3028_CTRL2_TSE              BIT(7)
++
++#define RV3028_EVT_CTRL_TSR           BIT(2)
++
++#define RV3028_EEPROM_CMD_WRITE               0x21
++#define RV3028_EEPROM_CMD_READ                0x22
++
++#define RV3028_EEBUSY_POLL            10000
++#define RV3028_EEBUSY_TIMEOUT         100000
++
++#define RV3028_BACKUP_TCE             BIT(5)
++#define RV3028_BACKUP_TCR_MASK                GENMASK(1,0)
++
++#define OFFSET_STEP_PPT                       953674
++
++enum rv3028_type {
++      rv_3028,
++};
++
++struct rv3028_data {
++      struct regmap *regmap;
++      struct rtc_device *rtc;
++      enum rv3028_type type;
++};
++
++static u16 rv3028_trickle_resistors[] = {1000, 3000, 6000, 11000};
++
++static ssize_t timestamp0_store(struct device *dev,
++                              struct device_attribute *attr,
++                              const char *buf, size_t count)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
++
++      regmap_update_bits(rv3028->regmap, RV3028_EVT_CTRL, RV3028_EVT_CTRL_TSR,
++                         RV3028_EVT_CTRL_TSR);
++
++      return count;
++};
++
++static ssize_t timestamp0_show(struct device *dev,
++                             struct device_attribute *attr, char *buf)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
++      struct rtc_time tm;
++      int ret, count;
++      u8 date[6];
++
++      ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
++      if (ret)
++              return ret;
++
++      if (!count)
++              return 0;
++
++      ret = regmap_bulk_read(rv3028->regmap, RV3028_TS_SEC, date,
++                             sizeof(date));
++      if (ret)
++              return ret;
++
++      tm.tm_sec = bcd2bin(date[0]);
++      tm.tm_min = bcd2bin(date[1]);
++      tm.tm_hour = bcd2bin(date[2]);
++      tm.tm_mday = bcd2bin(date[3]);
++      tm.tm_mon = bcd2bin(date[4]) - 1;
++      tm.tm_year = bcd2bin(date[5]) + 100;
++
++      ret = rtc_valid_tm(&tm);
++      if (ret)
++              return ret;
++
++      return sprintf(buf, "%llu\n",
++                     (unsigned long long)rtc_tm_to_time64(&tm));
++};
++
++static DEVICE_ATTR_RW(timestamp0);
++
++static ssize_t timestamp0_count_show(struct device *dev,
++                                   struct device_attribute *attr, char *buf)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
++      int ret, count;
++
++      ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
++      if (ret)
++              return ret;
++
++      return sprintf(buf, "%u\n", count);
++};
++
++static DEVICE_ATTR_RO(timestamp0_count);
++
++static struct attribute *rv3028_attrs[] = {
++      &dev_attr_timestamp0.attr,
++      &dev_attr_timestamp0_count.attr,
++      NULL
++};
++
++static const struct attribute_group rv3028_attr_group = {
++      .attrs  = rv3028_attrs,
++};
++
++static irqreturn_t rv3028_handle_irq(int irq, void *dev_id)
++{
++      struct rv3028_data *rv3028 = dev_id;
++      unsigned long events = 0;
++      u32 status = 0, ctrl = 0;
++
++      if (regmap_read(rv3028->regmap, RV3028_STATUS, &status) < 0 ||
++         status == 0) {
++              return IRQ_NONE;
++      }
++
++      if (status & RV3028_STATUS_PORF)
++              dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
++
++      if (status & RV3028_STATUS_TF) {
++              status |= RV3028_STATUS_TF;
++              ctrl |= RV3028_CTRL2_TIE;
++              events |= RTC_PF;
++      }
++
++      if (status & RV3028_STATUS_AF) {
++              status |= RV3028_STATUS_AF;
++              ctrl |= RV3028_CTRL2_AIE;
++              events |= RTC_AF;
++      }
++
++      if (status & RV3028_STATUS_UF) {
++              status |= RV3028_STATUS_UF;
++              ctrl |= RV3028_CTRL2_UIE;
++              events |= RTC_UF;
++      }
++
++      if (events) {
++              rtc_update_irq(rv3028->rtc, 1, events);
++              regmap_update_bits(rv3028->regmap, RV3028_STATUS, status, 0);
++              regmap_update_bits(rv3028->regmap, RV3028_CTRL2, ctrl, 0);
++      }
++
++      if (status & RV3028_STATUS_EVF) {
++              sysfs_notify(&rv3028->rtc->dev.kobj, NULL,
++                           dev_attr_timestamp0.attr.name);
++              dev_warn(&rv3028->rtc->dev, "event detected");
++      }
++
++      return IRQ_HANDLED;
++}
++
++static int rv3028_get_time(struct device *dev, struct rtc_time *tm)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      u8 date[7];
++      int ret, status;
++
++      ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++      if (ret < 0)
++              return ret;
++
++      if (status & RV3028_STATUS_PORF) {
++              dev_warn(dev, "Voltage low, data is invalid.\n");
++              return -EINVAL;
++      }
++
++      ret = regmap_bulk_read(rv3028->regmap, RV3028_SEC, date, sizeof(date));
++      if (ret)
++              return ret;
++
++      tm->tm_sec  = bcd2bin(date[RV3028_SEC] & 0x7f);
++      tm->tm_min  = bcd2bin(date[RV3028_MIN] & 0x7f);
++      tm->tm_hour = bcd2bin(date[RV3028_HOUR] & 0x3f);
++      tm->tm_wday = ilog2(date[RV3028_WDAY] & 0x7f);
++      tm->tm_mday = bcd2bin(date[RV3028_DAY] & 0x3f);
++      tm->tm_mon  = bcd2bin(date[RV3028_MONTH] & 0x1f) - 1;
++      tm->tm_year = bcd2bin(date[RV3028_YEAR]) + 100;
++
++      return 0;
++}
++
++static int rv3028_set_time(struct device *dev, struct rtc_time *tm)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      u8 date[7];
++      int ret;
++
++      date[RV3028_SEC]   = bin2bcd(tm->tm_sec);
++      date[RV3028_MIN]   = bin2bcd(tm->tm_min);
++      date[RV3028_HOUR]  = bin2bcd(tm->tm_hour);
++      date[RV3028_WDAY]  = 1 << (tm->tm_wday);
++      date[RV3028_DAY]   = bin2bcd(tm->tm_mday);
++      date[RV3028_MONTH] = bin2bcd(tm->tm_mon + 1);
++      date[RV3028_YEAR]  = bin2bcd(tm->tm_year - 100);
++
++      /*
++       * Writing to the Seconds register has the same effect as setting RESET
++       * bit to 1
++       */
++      ret = regmap_bulk_write(rv3028->regmap, RV3028_SEC, date,
++                              sizeof(date));
++      if (ret)
++              return ret;
++
++      ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++                               RV3028_STATUS_PORF, 0);
++
++      return ret;
++}
++
++static int rv3028_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      u8 alarmvals[3];
++      int status, ctrl, ret;
++
++      ret = regmap_bulk_read(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
++                             sizeof(alarmvals));
++      if (ret)
++              return ret;
++
++      ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++      if (ret < 0)
++              return ret;
++
++      ret = regmap_read(rv3028->regmap, RV3028_CTRL2, &ctrl);
++      if (ret < 0)
++              return ret;
++
++      alrm->time.tm_sec  = 0;
++      alrm->time.tm_min  = bcd2bin(alarmvals[0] & 0x7f);
++      alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
++      alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
++
++      alrm->enabled = !!(ctrl & RV3028_CTRL2_AIE);
++      alrm->pending = (status & RV3028_STATUS_AF) && alrm->enabled;
++
++      return 0;
++}
++
++static int rv3028_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      u8 alarmvals[3];
++      u8 ctrl = 0;
++      int ret;
++
++      /* The alarm has no seconds, round up to nearest minute */
++      if (alrm->time.tm_sec) {
++              time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
++
++              alarm_time += 60 - alrm->time.tm_sec;
++              rtc_time64_to_tm(alarm_time, &alrm->time);
++      }
++
++      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++                               RV3028_CTRL2_AIE | RV3028_CTRL2_UIE, 0);
++      if (ret)
++              return ret;
++
++      alarmvals[0] = bin2bcd(alrm->time.tm_min);
++      alarmvals[1] = bin2bcd(alrm->time.tm_hour);
++      alarmvals[2] = bin2bcd(alrm->time.tm_mday);
++
++      ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++                               RV3028_STATUS_AF, 0);
++      if (ret)
++              return ret;
++
++      ret = regmap_bulk_write(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
++                              sizeof(alarmvals));
++      if (ret)
++              return ret;
++
++      if (alrm->enabled) {
++              if (rv3028->rtc->uie_rtctimer.enabled)
++                      ctrl |= RV3028_CTRL2_UIE;
++              if (rv3028->rtc->aie_timer.enabled)
++                      ctrl |= RV3028_CTRL2_AIE;
++      }
++
++      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++                               RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
++
++      return ret;
++}
++
++static int rv3028_alarm_irq_enable(struct device *dev, unsigned int enabled)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      int ctrl = 0, ret;
++
++      if (enabled) {
++              if (rv3028->rtc->uie_rtctimer.enabled)
++                      ctrl |= RV3028_CTRL2_UIE;
++              if (rv3028->rtc->aie_timer.enabled)
++                      ctrl |= RV3028_CTRL2_AIE;
++      }
++
++      ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++                               RV3028_STATUS_AF | RV3028_STATUS_UF, 0);
++      if (ret)
++              return ret;
++
++      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++                               RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
++      if (ret)
++              return ret;
++
++      return 0;
++}
++
++static int rv3028_read_offset(struct device *dev, long *offset)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      int ret, value, steps;
++
++      ret = regmap_read(rv3028->regmap, RV3028_OFFSET, &value);
++      if (ret < 0)
++              return ret;
++
++      steps = sign_extend32(value << 1, 8);
++
++      ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
++      if (ret < 0)
++              return ret;
++
++      steps += value >> 7;
++
++      *offset = DIV_ROUND_CLOSEST(steps * OFFSET_STEP_PPT, 1000);
++
++      return 0;
++}
++
++static int rv3028_set_offset(struct device *dev, long offset)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      int ret;
++
++      offset = clamp(offset, -244141L, 243187L) * 1000;
++      offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT);
++
++      ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1);
++      if (ret < 0)
++              return ret;
++
++      return regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7),
++                                offset << 7);
++}
++
++static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
++{
++      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++      int status, ret = 0;
++
++      switch (cmd) {
++      case RTC_VL_READ:
++              ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++              if (ret < 0)
++                      return ret;
++
++              if (status & RV3028_STATUS_PORF)
++                      dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
++
++              status &= RV3028_STATUS_PORF;
++
++              if (copy_to_user((void __user *)arg, &status, sizeof(int)))
++                      return -EFAULT;
++
++              return 0;
++
++      case RTC_VL_CLR:
++              ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++                                       RV3028_STATUS_PORF, 0);
++
++              return ret;
++
++      default:
++              return -ENOIOCTLCMD;
++      }
++}
++
++static int rv3028_nvram_write(void *priv, unsigned int offset, void *val,
++                            size_t bytes)
++{
++      return regmap_bulk_write(priv, RV3028_RAM1 + offset, val, bytes);
++}
++
++static int rv3028_nvram_read(void *priv, unsigned int offset, void *val,
++                           size_t bytes)
++{
++      return regmap_bulk_read(priv, RV3028_RAM1 + offset, val, bytes);
++}
++
++static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
++                             size_t bytes)
++{
++      u32 status, ctrl1;
++      int i, ret, err;
++      u8 *buf = val;
++
++      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;
++      }
++
++      for (i = 0; i < bytes; i++) {
++              ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
++              if (ret)
++                      goto restore_eerd;
++
++              ret = regmap_write(priv, RV3028_EEPROM_DATA, buf[i]);
++              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_WRITE);
++              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 int rv3028_eeprom_read(void *priv, unsigned int offset, void *val,
++                            size_t bytes)
++{
++      u32 status, ctrl1, data;
++      int i, ret, err;
++      u8 *buf = val;
++
++      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;
++      }
++
++      for (i = 0; i < bytes; i++) {
++              ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
++              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_READ);
++              if (ret)
++                      goto restore_eerd;
++
++              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_read(priv, RV3028_EEPROM_DATA, &data);
++              if (ret)
++                      goto restore_eerd;
++              buf[i] = data;
++      }
++
++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,
++      .read_offset = rv3028_read_offset,
++      .set_offset = rv3028_set_offset,
++      .ioctl = rv3028_ioctl,
++};
++
++static const struct regmap_config regmap_config = {
++        .reg_bits = 8,
++        .val_bits = 8,
++        .max_register = 0x37,
++};
++
++static int rv3028_probe(struct i2c_client *client)
++{
++      struct rv3028_data *rv3028;
++      int ret, status;
++      u32 ohms;
++      struct nvmem_config nvmem_cfg = {
++              .name = "rv3028_nvram",
++              .word_size = 1,
++              .stride = 1,
++              .size = 2,
++              .type = NVMEM_TYPE_BATTERY_BACKED,
++              .reg_read = rv3028_nvram_read,
++              .reg_write = rv3028_nvram_write,
++      };
++      struct nvmem_config eeprom_cfg = {
++              .name = "rv3028_eeprom",
++              .word_size = 1,
++              .stride = 1,
++              .size = 43,
++              .type = NVMEM_TYPE_EEPROM,
++              .reg_read = rv3028_eeprom_read,
++              .reg_write = rv3028_eeprom_write,
++      };
++
++      rv3028 = devm_kzalloc(&client->dev, sizeof(struct rv3028_data),
++                            GFP_KERNEL);
++      if (!rv3028)
++              return -ENOMEM;
++
++      rv3028->regmap = devm_regmap_init_i2c(client, &regmap_config);
++
++      i2c_set_clientdata(client, rv3028);
++
++      ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++      if (ret < 0)
++              return ret;
++
++      if (status & RV3028_STATUS_PORF)
++              dev_warn(&client->dev, "Voltage low, data loss detected.\n");
++
++      if (status & RV3028_STATUS_AF)
++              dev_warn(&client->dev, "An alarm may have been missed.\n");
++
++      rv3028->rtc = devm_rtc_allocate_device(&client->dev);
++      if (IS_ERR(rv3028->rtc)) {
++              return PTR_ERR(rv3028->rtc);
++      }
++
++      if (client->irq > 0) {
++              ret = devm_request_threaded_irq(&client->dev, client->irq,
++                                              NULL, rv3028_handle_irq,
++                                              IRQF_TRIGGER_LOW | IRQF_ONESHOT,
++                                              "rv3028", rv3028);
++              if (ret) {
++                      dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
++                      client->irq = 0;
++              } else {
++                      rv3028_rtc_ops.read_alarm = rv3028_get_alarm;
++                      rv3028_rtc_ops.set_alarm = rv3028_set_alarm;
++                      rv3028_rtc_ops.alarm_irq_enable = rv3028_alarm_irq_enable;
++              }
++      }
++
++      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1,
++                               RV3028_CTRL1_WADA, RV3028_CTRL1_WADA);
++      if (ret)
++              return ret;
++
++      /* setup timestamping */
++      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++                               RV3028_CTRL2_EIE | RV3028_CTRL2_TSE,
++                               RV3028_CTRL2_EIE | RV3028_CTRL2_TSE);
++      if (ret)
++              return ret;
++
++      /* setup trickle charger */
++      if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
++                                    &ohms)) {
++              int i;
++
++              for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
++                      if (ohms == rv3028_trickle_resistors[i])
++                              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;
++              } else {
++                      dev_warn(&client->dev, "invalid trickle resistor value\n");
++              }
++      }
++
++      ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
++      if (ret)
++              return ret;
++
++      rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
++      rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099;
++      rv3028->rtc->ops = &rv3028_rtc_ops;
++      ret = rtc_register_device(rv3028->rtc);
++      if (ret)
++              return ret;
++
++      nvmem_cfg.priv = rv3028->regmap;
++      rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
++      eeprom_cfg.priv = rv3028->regmap;
++      rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
++
++      rv3028->rtc->max_user_freq = 1;
++
++      return 0;
++}
++
++static const struct of_device_id rv3028_of_match[] = {
++      { .compatible = "microcrystal,rv3028", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, rv3028_of_match);
++
++static struct i2c_driver rv3028_driver = {
++      .driver = {
++              .name = "rtc-rv3028",
++              .of_match_table = of_match_ptr(rv3028_of_match),
++      },
++      .probe_new      = rv3028_probe,
++};
++module_i2c_driver(rv3028_driver);
++
++MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
++MODULE_DESCRIPTION("Micro Crystal RV3028 RTC driver");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0339-staging-bcm2835-codec-Refactor-default-resolution-co.patch b/target/linux/brcm2708/patches-4.19/950-0339-staging-bcm2835-codec-Refactor-default-resolution-co.patch
deleted file mode 100644 (file)
index cd592e2..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-From a97baa799a8069fe965a4d194935c025e21acf8e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 20 Mar 2019 10:06:51 +0000
-Subject: [PATCH] staging: bcm2835-codec: Refactor default resolution
- code
-
-The default resolution code was different for each role
-as compressed formats need to pass bytesperline as 0 and
-set up customised buffer sizes.
-This is common setup, therefore amend get_sizeimage and
-get_bytesperline to do the correct thing whether compressed
-or uncompressed.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 103 +++++++-----------
- 1 file changed, 40 insertions(+), 63 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -578,10 +578,17 @@ static void job_abort(void *priv)
-       ctx->aborting = 1;
- }
--static inline unsigned int get_sizeimage(int bpl, int height,
-+static inline unsigned int get_sizeimage(int bpl, int width, int height,
-                                        struct bcm2835_codec_fmt *fmt)
- {
--      return (bpl * height * fmt->size_multiplier_x2) >> 1;
-+      if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
-+              if (width * height > 1280 * 720)
-+                      return DEF_COMP_BUF_SIZE_GREATER_720P;
-+              else
-+                      return DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+      } else {
-+              return (bpl * height * fmt->size_multiplier_x2) >> 1;
-+      }
- }
- static inline unsigned int get_bytesperline(int width,
-@@ -1032,22 +1039,13 @@ static int vidioc_try_fmt(struct v4l2_fo
-                * some of the pixels are active.
-                */
-               f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
--
--              f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
--                                                         fmt);
--              f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
--                                                   f->fmt.pix.height,
--                                                   fmt);
--      } else {
--              u32 min_size = f->fmt.pix.width > 1280 ||
--                             f->fmt.pix.height > 720 ?
--                             DEF_COMP_BUF_SIZE_GREATER_720P :
--                             DEF_COMP_BUF_SIZE_720P_OR_LESS;
--
--              f->fmt.pix.bytesperline = 0;
--              if (f->fmt.pix.sizeimage < min_size)
--                      f->fmt.pix.sizeimage = min_size;
-       }
-+      f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
-+                                                 fmt);
-+      f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
-+                                           f->fmt.pix.width,
-+                                           f->fmt.pix.height,
-+                                           fmt);
-       f->fmt.pix.field = V4L2_FIELD_NONE;
-@@ -1159,6 +1157,7 @@ static int vidioc_s_fmt(struct bcm2835_c
-               q_data_dst->bytesperline =
-                       get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
-               q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
-+                                                    q_data_dst->crop_width,
-                                                     q_data_dst->height,
-                                                     q_data_dst->fmt);
-               update_capture_port = true;
-@@ -2218,52 +2217,30 @@ static int bcm2835_codec_open(struct fil
-       ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
-       ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
--      switch (dev->role) {
--      case DECODE:
--              /*
--               * Input width and height are irrelevant as they will be defined
--               * by the bitstream not the format. Required by V4L2 though.
--               */
--              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
--              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
--              ctx->q_data[V4L2_M2M_SRC].sizeimage =
--                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
--
--              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
--              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_DST].bytesperline =
--                              get_bytesperline(DEFAULT_WIDTH,
--                                               ctx->q_data[V4L2_M2M_DST].fmt);
--              ctx->q_data[V4L2_M2M_DST].sizeimage =
--                      get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
--                                    ctx->q_data[V4L2_M2M_DST].height,
--                                    ctx->q_data[V4L2_M2M_DST].fmt);
--              break;
--      case ENCODE:
--              ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
--              ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_SRC].bytesperline =
--                              get_bytesperline(DEFAULT_WIDTH,
--                                               ctx->q_data[V4L2_M2M_SRC].fmt);
--              ctx->q_data[V4L2_M2M_SRC].sizeimage =
--                      get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
--                                    ctx->q_data[V4L2_M2M_SRC].height,
--                                    ctx->q_data[V4L2_M2M_SRC].fmt);
--
--              ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
--              ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
--              ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
--              ctx->q_data[V4L2_M2M_DST].sizeimage =
--                                              DEF_COMP_BUF_SIZE_720P_OR_LESS;
--              break;
--      case ISP:
--              break;
--      }
-+
-+      ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-+      ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-+      ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-+      ctx->q_data[V4L2_M2M_SRC].bytesperline =
-+                      get_bytesperline(DEFAULT_WIDTH,
-+                                       ctx->q_data[V4L2_M2M_SRC].fmt);
-+      ctx->q_data[V4L2_M2M_SRC].sizeimage =
-+              get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
-+                            ctx->q_data[V4L2_M2M_SRC].crop_width,
-+                            ctx->q_data[V4L2_M2M_SRC].height,
-+                            ctx->q_data[V4L2_M2M_SRC].fmt);
-+
-+      ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-+      ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-+      ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-+      ctx->q_data[V4L2_M2M_DST].bytesperline =
-+                      get_bytesperline(DEFAULT_WIDTH,
-+                                       ctx->q_data[V4L2_M2M_DST].fmt);
-+      ctx->q_data[V4L2_M2M_DST].sizeimage =
-+              get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
-+                            ctx->q_data[V4L2_M2M_DST].crop_width,
-+                            ctx->q_data[V4L2_M2M_DST].height,
-+                            ctx->q_data[V4L2_M2M_DST].fmt);
-       ctx->colorspace = V4L2_COLORSPACE_REC709;
-       ctx->bitrate = 10 * 1000 * 1000;
diff --git a/target/linux/brcm2708/patches-4.19/950-0340-nvmem-add-type-attribute.patch b/target/linux/brcm2708/patches-4.19/950-0340-nvmem-add-type-attribute.patch
deleted file mode 100644 (file)
index 661ba8e..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-From c9e76146066660a2884e61216c1ce227cf509bf8 Mon Sep 17 00:00:00 2001
-From: Alexandre Belloni <alexandre.belloni@bootlin.com>
-Date: Fri, 30 Nov 2018 11:53:20 +0000
-Subject: [PATCH] nvmem: add type attribute
-
-commit 16688453661b6d5159be558a1f8c1f54463a420f upstream.
-
-Add a type attribute so userspace is able to know how the data is stored as
-this can help taking the correct decision when selecting which device to
-use. This will also help program display the proper warnings when burning
-fuses for example.
-
-Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/nvmem/core.c           | 21 +++++++++++++++++++++
- include/linux/nvmem-provider.h | 16 ++++++++++++++++
- 2 files changed, 37 insertions(+)
-
---- a/drivers/nvmem/core.c
-+++ b/drivers/nvmem/core.c
-@@ -36,6 +36,7 @@ struct nvmem_device {
-       size_t                  size;
-       bool                    read_only;
-       int                     flags;
-+      enum nvmem_type         type;
-       struct bin_attribute    eeprom;
-       struct device           *base_dev;
-       nvmem_reg_read_t        reg_read;
-@@ -84,6 +85,21 @@ static int nvmem_reg_write(struct nvmem_
-       return -EINVAL;
- }
-+static ssize_t type_show(struct device *dev,
-+                       struct device_attribute *attr, char *buf)
-+{
-+      struct nvmem_device *nvmem = to_nvmem_device(dev);
-+
-+      return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
-+}
-+
-+static DEVICE_ATTR_RO(type);
-+
-+static struct attribute *nvmem_attrs[] = {
-+      &dev_attr_type.attr,
-+      NULL,
-+};
-+
- static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
-                                   struct bin_attribute *attr,
-                                   char *buf, loff_t pos, size_t count)
-@@ -169,6 +185,7 @@ static struct bin_attribute *nvmem_bin_r
- static const struct attribute_group nvmem_bin_rw_group = {
-       .bin_attrs      = nvmem_bin_rw_attributes,
-+      .attrs          = nvmem_attrs,
- };
- static const struct attribute_group *nvmem_rw_dev_groups[] = {
-@@ -192,6 +209,7 @@ static struct bin_attribute *nvmem_bin_r
- static const struct attribute_group nvmem_bin_ro_group = {
-       .bin_attrs      = nvmem_bin_ro_attributes,
-+      .attrs          = nvmem_attrs,
- };
- static const struct attribute_group *nvmem_ro_dev_groups[] = {
-@@ -216,6 +234,7 @@ static struct bin_attribute *nvmem_bin_r
- static const struct attribute_group nvmem_bin_rw_root_group = {
-       .bin_attrs      = nvmem_bin_rw_root_attributes,
-+      .attrs          = nvmem_attrs,
- };
- static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
-@@ -239,6 +258,7 @@ static struct bin_attribute *nvmem_bin_r
- static const struct attribute_group nvmem_bin_ro_root_group = {
-       .bin_attrs      = nvmem_bin_ro_root_attributes,
-+      .attrs          = nvmem_attrs,
- };
- static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
-@@ -485,6 +505,7 @@ struct nvmem_device *nvmem_register(cons
-       nvmem->dev.bus = &nvmem_bus_type;
-       nvmem->dev.parent = config->dev;
-       nvmem->priv = config->priv;
-+      nvmem->type = config->type;
-       nvmem->reg_read = config->reg_read;
-       nvmem->reg_write = config->reg_write;
-       nvmem->dev.of_node = config->dev->of_node;
---- a/include/linux/nvmem-provider.h
-+++ b/include/linux/nvmem-provider.h
-@@ -22,6 +22,20 @@ typedef int (*nvmem_reg_read_t)(void *pr
- typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
-                                void *val, size_t bytes);
-+enum nvmem_type {
-+      NVMEM_TYPE_UNKNOWN = 0,
-+      NVMEM_TYPE_EEPROM,
-+      NVMEM_TYPE_OTP,
-+      NVMEM_TYPE_BATTERY_BACKED,
-+};
-+
-+static const char * const nvmem_type_str[] = {
-+      [NVMEM_TYPE_UNKNOWN] = "Unknown",
-+      [NVMEM_TYPE_EEPROM] = "EEPROM",
-+      [NVMEM_TYPE_OTP] = "OTP",
-+      [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
-+};
-+
- /**
-  * struct nvmem_config - NVMEM device configuration
-  *
-@@ -31,6 +45,7 @@ typedef int (*nvmem_reg_write_t)(void *p
-  * @owner:    Pointer to exporter module. Used for refcounting.
-  * @cells:    Optional array of pre-defined NVMEM cells.
-  * @ncells:   Number of elements in cells.
-+ * @type:     Type of the nvmem storage
-  * @read_only:        Device is read-only.
-  * @root_only:        Device is accessibly to root only.
-  * @reg_read: Callback to read data.
-@@ -54,6 +69,7 @@ struct nvmem_config {
-       struct module           *owner;
-       const struct nvmem_cell_info    *cells;
-       int                     ncells;
-+      enum nvmem_type         type;
-       bool                    read_only;
-       bool                    root_only;
-       nvmem_reg_read_t        reg_read;
diff --git a/target/linux/brcm2708/patches-4.19/950-0340-overlays-Add-rv3028-to-i2c-rtc.patch b/target/linux/brcm2708/patches-4.19/950-0340-overlays-Add-rv3028-to-i2c-rtc.patch
new file mode 100644 (file)
index 0000000..2228022
--- /dev/null
@@ -0,0 +1,75 @@
+From 67dd8e4c8ccf5d331960c7e936e5b03a9f92496d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 28 Mar 2019 13:26:59 +0000
+Subject: [PATCH] overlays: Add rv3028 to i2c-rtc
+
+See: https://github.com/raspberrypi/linux/issues/2912
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README             |  4 +++-
+ .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 19 ++++++++++++++++++-
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -939,6 +939,8 @@ Params: abx80x                  Select o
+         pcf8563                 Select the PCF8563 device
++        rv3028                  Select the Micro Crystal RV3028 device
++
+         addr                    Sets the address for the RTC. Note that the
+                                 device must be configured to use the specified
+                                 address.
+@@ -947,7 +949,7 @@ Params: abx80x                  Select o
+                                 "schottky" (ABx80x only)
+         trickle-resistor-ohms   Resistor value for trickle charge (DS1339,
+-                                ABx80x)
++                                ABx80x, RV3028)
+         wakeup-source           Specify that the RTC can be used as a wakeup
+                                 source
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -158,6 +158,21 @@
+               };
+       };
++      fragment@10 {
++              target = <&i2c_arm>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      rv3028: rv3028@52 {
++                              compatible = "microcrystal,rv3028";
++                              reg = <0x52>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+0";
+               ds1307 = <0>,"+1";
+@@ -169,6 +184,7 @@
+               pcf8523 = <0>,"+7";
+               pcf8563 = <0>,"+8";
+               m41t62 = <0>,"+9";
++              rv3028 = <0>,"+10";
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
+@@ -182,7 +198,8 @@
+                      <&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",
++                                      <&rv3028>,"trickle-resistor-ohms:0";
+               wakeup-source = <&ds1339>,"wakeup-source?",
+                               <&ds3231>,"wakeup-source?",
+                               <&mcp7940x>,"wakeup-source?",
diff --git a/target/linux/brcm2708/patches-4.19/950-0341-ASoC-tlv320aic32x4-SND_SOC_DAPM_MICBIAS-is-deprecate.patch b/target/linux/brcm2708/patches-4.19/950-0341-ASoC-tlv320aic32x4-SND_SOC_DAPM_MICBIAS-is-deprecate.patch
new file mode 100644 (file)
index 0000000..aa5f12a
--- /dev/null
@@ -0,0 +1,78 @@
+From 053938f67f73773152f70d89aa32e7893ee19694 Mon Sep 17 00:00:00 2001
+From: b-ak <anur.bhargav@gmail.com>
+Date: Wed, 9 Jan 2019 22:41:21 +0530
+Subject: [PATCH] ASoC: tlv320aic32x4: SND_SOC_DAPM_MICBIAS is
+ deprecated
+
+commit 04d979d7a7bac2f645cd827ea37e5ffa5b4e1f97 upstream.
+
+SND_SOC_DAPM_MICBIAS is deprecated, replace it with SND_SOC_DAPM_SUPPLY.
+
+MICBIAS voltage wasn't supplied to the microphone with the older
+SND_SOC_DAPM_MICBIAS widget, hence the microphone wouldn't work.
+
+This patch fixes the problem.
+
+Signed-off-by: b-ak <anur.bhargav@gmail.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 30 +++++++++++++++++++++++++++++-
+ sound/soc/codecs/tlv320aic32x4.h |  1 +
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -79,6 +79,32 @@ struct aic32x4_priv {
+       struct device *dev;
+ };
++static int mic_bias_event(struct snd_soc_dapm_widget *w,
++      struct snd_kcontrol *kcontrol, int event)
++{
++      struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
++
++      switch (event) {
++      case SND_SOC_DAPM_POST_PMU:
++              /* Change Mic Bias Registor */
++              snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
++                              AIC32x4_MICBIAS_MASK,
++                              AIC32X4_MICBIAS_LDOIN |
++                              AIC32X4_MICBIAS_2075V);
++              printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
++              break;
++      case SND_SOC_DAPM_PRE_PMD:
++              snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
++                              AIC32x4_MICBIAS_MASK, 0);
++              printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
++                              __func__);
++              break;
++      }
++
++      return 0;
++}
++
++
+ static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -450,7 +476,9 @@ static const struct snd_soc_dapm_widget
+       SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
+                       in3r_to_lmixer_controls),
+-      SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
++      SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
++                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
++
+       SND_SOC_DAPM_OUTPUT("HPL"),
+       SND_SOC_DAPM_OUTPUT("HPR"),
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -195,6 +195,7 @@ int aic32x4_remove(struct device *dev);
+ /* AIC32X4_MICBIAS */
+ #define AIC32X4_MICBIAS_LDOIN         BIT(3)
+ #define AIC32X4_MICBIAS_2075V         0x60
++#define AIC32x4_MICBIAS_MASK            GENMASK(6, 3)
+ /* AIC32X4_LMICPGANIN */
+ #define AIC32X4_LMICPGANIN_IN2R_10K   0x10
diff --git a/target/linux/brcm2708/patches-4.19/950-0341-rtc-rv3028-add-new-driver.patch b/target/linux/brcm2708/patches-4.19/950-0341-rtc-rv3028-add-new-driver.patch
deleted file mode 100644 (file)
index 6a00e82..0000000
+++ /dev/null
@@ -1,860 +0,0 @@
-From bb0e317bfc453877805a12f975490ad38b6413f1 Mon Sep 17 00:00:00 2001
-From: Alexandre Belloni <alexandre.belloni@bootlin.com>
-Date: Wed, 13 Feb 2019 00:21:36 +0100
-Subject: [PATCH] rtc: rv3028: add new driver
-
-upstream commit e6e7376cfd7b3f9b63de3a22792f64d9bfb2ab53.
-
-Add a driver for the MicroCrystal RV-3028. It is a SMT Real-Time Clock
-Module that incorporates an integrated CMOS circuit together with an XTAL.
-It has an i2c interface.
-
-The driver handles date/time, alarms, trickle charging, timestamping,
-frequency offset correction, EEPROM and NVRAM.
-
-Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
----
- Documentation/devicetree/bindings/rtc/rtc.txt |  69 ++
- drivers/rtc/Kconfig                           |   9 +
- drivers/rtc/Makefile                          |   1 +
- drivers/rtc/rtc-rv3028.c                      | 733 ++++++++++++++++++
- 4 files changed, 812 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/rtc/rtc.txt
- create mode 100644 drivers/rtc/rtc-rv3028.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/rtc/rtc.txt
-@@ -0,0 +1,69 @@
-+Generic device tree bindings for Real Time Clock devices
-+========================================================
-+
-+This document describes generic bindings which can be used to describe Real Time
-+Clock devices in a device tree.
-+
-+Required properties
-+-------------------
-+
-+- compatible : name of RTC device following generic names recommended practice.
-+
-+For other required properties e.g. to describe register sets,
-+clocks, etc. check the binding documentation of the specific driver.
-+
-+Optional properties
-+-------------------
-+
-+- start-year : if provided, the default hardware range supported by the RTC is
-+               shifted so the first usable year is the specified one.
-+
-+The following properties may not be supported by all drivers. However, if a
-+driver wants to support one of the below features, it should adapt the bindings
-+below.
-+- trickle-resistor-ohms :   Selected resistor for trickle charger. Should be given
-+                            if trickle charger should be enabled
-+- trickle-diode-disable :   Do not use internal trickle charger diode Should be
-+                            given if internal trickle charger diode should be
-+                            disabled
-+- wakeup-source :           Enables wake up of host system on alarm
-+- quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
-+                            expressed in femto Farad (fF).
-+                            The default value shall be listed (if optional),
-+                            and likewise all valid values.
-+
-+Trivial RTCs
-+------------
-+
-+This is a list of trivial RTC devices that have simple device tree
-+bindings, consisting only of a compatible field, an address and
-+possibly an interrupt line.
-+
-+
-+Compatible            Vendor / Chip
-+==========            =============
-+abracon,abb5zes3      AB-RTCMC-32.768kHz-B5ZE-S3: Real Time Clock/Calendar Module with I2C Interface
-+dallas,ds1374         I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
-+dallas,ds1672         Dallas DS1672 Real-time Clock
-+dallas,ds3232         Extremely Accurate I²C RTC with Integrated Crystal and SRAM
-+epson,rx8010          I2C-BUS INTERFACE REAL TIME CLOCK MODULE
-+epson,rx8581          I2C-BUS INTERFACE REAL TIME CLOCK MODULE
-+emmicro,em3027                EM Microelectronic EM3027 Real-time Clock
-+isil,isl1208          Intersil ISL1208 Low Power RTC with Battery Backed SRAM
-+isil,isl1218          Intersil ISL1218 Low Power RTC with Battery Backed SRAM
-+isil,isl12022         Intersil ISL12022 Real-time Clock
-+microcrystal,rv3028   Real Time Clock Module with I2C-Bus
-+microcrystal,rv3029   Real Time Clock Module with I2C-Bus
-+microcrystal,rv8523   Real Time Clock
-+nxp,pcf2127           Real-time clock
-+nxp,pcf2129           Real-time clock
-+nxp,pcf8563           Real-time clock/calendar
-+pericom,pt7c4338      Real-time Clock Module
-+ricoh,r2025sd         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,r2221tl         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rs5c372a                I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rs5c372b                I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rv5c386         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rv5c387a                I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+sii,s35390a           2-wire CMOS real-time clock
-+whwave,sd3078         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
---- a/drivers/rtc/Kconfig
-+++ b/drivers/rtc/Kconfig
-@@ -625,6 +625,15 @@ config RTC_DRV_EM3027
-         This driver can also be built as a module. If so, the module
-         will be called rtc-em3027.
-+config RTC_DRV_RV3028
-+      tristate "Micro Crystal RV3028"
-+      help
-+        If you say yes here you get support for the Micro Crystal
-+        RV3028.
-+
-+        This driver can also be built as a module. If so, the module
-+        will be called rtc-rv3028.
-+
- config RTC_DRV_RV8803
-       tristate "Micro Crystal RV8803, Epson RX8900"
-       help
---- a/drivers/rtc/Makefile
-+++ b/drivers/rtc/Makefile
-@@ -136,6 +136,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313)      += rtc-rs5
- obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
- obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
- obj-$(CONFIG_RTC_DRV_RTD119X) += rtc-rtd119x.o
-+obj-$(CONFIG_RTC_DRV_RV3028)  += rtc-rv3028.o
- obj-$(CONFIG_RTC_DRV_RV3029C2)        += rtc-rv3029c2.o
- obj-$(CONFIG_RTC_DRV_RV8803)  += rtc-rv8803.o
- obj-$(CONFIG_RTC_DRV_RX4581)  += rtc-rx4581.o
---- /dev/null
-+++ b/drivers/rtc/rtc-rv3028.c
-@@ -0,0 +1,733 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * RTC driver for the Micro Crystal RV3028
-+ *
-+ * Copyright (C) 2019 Micro Crystal SA
-+ *
-+ * Alexandre Belloni <alexandre.belloni@bootlin.com>
-+ *
-+ */
-+
-+#include <linux/bcd.h>
-+#include <linux/bitops.h>
-+#include <linux/i2c.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/log2.h>
-+#include <linux/module.h>
-+#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
-+#define RV3028_HOUR                   0x02
-+#define RV3028_WDAY                   0x03
-+#define RV3028_DAY                    0x04
-+#define RV3028_MONTH                  0x05
-+#define RV3028_YEAR                   0x06
-+#define RV3028_ALARM_MIN              0x07
-+#define RV3028_ALARM_HOUR             0x08
-+#define RV3028_ALARM_DAY              0x09
-+#define RV3028_STATUS                 0x0E
-+#define RV3028_CTRL1                  0x0F
-+#define RV3028_CTRL2                  0x10
-+#define RV3028_EVT_CTRL                       0x13
-+#define RV3028_TS_COUNT                       0x14
-+#define RV3028_TS_SEC                 0x15
-+#define RV3028_RAM1                   0x1F
-+#define RV3028_EEPROM_ADDR            0x25
-+#define RV3028_EEPROM_DATA            0x26
-+#define RV3028_EEPROM_CMD             0x27
-+#define RV3028_CLKOUT                 0x35
-+#define RV3028_OFFSET                 0x36
-+#define RV3028_BACKUP                 0x37
-+
-+#define RV3028_STATUS_PORF            BIT(0)
-+#define RV3028_STATUS_EVF             BIT(1)
-+#define RV3028_STATUS_AF              BIT(2)
-+#define RV3028_STATUS_TF              BIT(3)
-+#define RV3028_STATUS_UF              BIT(4)
-+#define RV3028_STATUS_BSF             BIT(5)
-+#define RV3028_STATUS_CLKF            BIT(6)
-+#define RV3028_STATUS_EEBUSY          BIT(7)
-+
-+#define RV3028_CTRL1_EERD             BIT(3)
-+#define RV3028_CTRL1_WADA             BIT(5)
-+
-+#define RV3028_CTRL2_RESET            BIT(0)
-+#define RV3028_CTRL2_12_24            BIT(1)
-+#define RV3028_CTRL2_EIE              BIT(2)
-+#define RV3028_CTRL2_AIE              BIT(3)
-+#define RV3028_CTRL2_TIE              BIT(4)
-+#define RV3028_CTRL2_UIE              BIT(5)
-+#define RV3028_CTRL2_TSE              BIT(7)
-+
-+#define RV3028_EVT_CTRL_TSR           BIT(2)
-+
-+#define RV3028_EEPROM_CMD_WRITE               0x21
-+#define RV3028_EEPROM_CMD_READ                0x22
-+
-+#define RV3028_EEBUSY_POLL            10000
-+#define RV3028_EEBUSY_TIMEOUT         100000
-+
-+#define RV3028_BACKUP_TCE             BIT(5)
-+#define RV3028_BACKUP_TCR_MASK                GENMASK(1,0)
-+
-+#define OFFSET_STEP_PPT                       953674
-+
-+enum rv3028_type {
-+      rv_3028,
-+};
-+
-+struct rv3028_data {
-+      struct regmap *regmap;
-+      struct rtc_device *rtc;
-+      enum rv3028_type type;
-+};
-+
-+static u16 rv3028_trickle_resistors[] = {1000, 3000, 6000, 11000};
-+
-+static ssize_t timestamp0_store(struct device *dev,
-+                              struct device_attribute *attr,
-+                              const char *buf, size_t count)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
-+
-+      regmap_update_bits(rv3028->regmap, RV3028_EVT_CTRL, RV3028_EVT_CTRL_TSR,
-+                         RV3028_EVT_CTRL_TSR);
-+
-+      return count;
-+};
-+
-+static ssize_t timestamp0_show(struct device *dev,
-+                             struct device_attribute *attr, char *buf)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
-+      struct rtc_time tm;
-+      int ret, count;
-+      u8 date[6];
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
-+      if (ret)
-+              return ret;
-+
-+      if (!count)
-+              return 0;
-+
-+      ret = regmap_bulk_read(rv3028->regmap, RV3028_TS_SEC, date,
-+                             sizeof(date));
-+      if (ret)
-+              return ret;
-+
-+      tm.tm_sec = bcd2bin(date[0]);
-+      tm.tm_min = bcd2bin(date[1]);
-+      tm.tm_hour = bcd2bin(date[2]);
-+      tm.tm_mday = bcd2bin(date[3]);
-+      tm.tm_mon = bcd2bin(date[4]) - 1;
-+      tm.tm_year = bcd2bin(date[5]) + 100;
-+
-+      ret = rtc_valid_tm(&tm);
-+      if (ret)
-+              return ret;
-+
-+      return sprintf(buf, "%llu\n",
-+                     (unsigned long long)rtc_tm_to_time64(&tm));
-+};
-+
-+static DEVICE_ATTR_RW(timestamp0);
-+
-+static ssize_t timestamp0_count_show(struct device *dev,
-+                                   struct device_attribute *attr, char *buf)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
-+      int ret, count;
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
-+      if (ret)
-+              return ret;
-+
-+      return sprintf(buf, "%u\n", count);
-+};
-+
-+static DEVICE_ATTR_RO(timestamp0_count);
-+
-+static struct attribute *rv3028_attrs[] = {
-+      &dev_attr_timestamp0.attr,
-+      &dev_attr_timestamp0_count.attr,
-+      NULL
-+};
-+
-+static const struct attribute_group rv3028_attr_group = {
-+      .attrs  = rv3028_attrs,
-+};
-+
-+static irqreturn_t rv3028_handle_irq(int irq, void *dev_id)
-+{
-+      struct rv3028_data *rv3028 = dev_id;
-+      unsigned long events = 0;
-+      u32 status = 0, ctrl = 0;
-+
-+      if (regmap_read(rv3028->regmap, RV3028_STATUS, &status) < 0 ||
-+         status == 0) {
-+              return IRQ_NONE;
-+      }
-+
-+      if (status & RV3028_STATUS_PORF)
-+              dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
-+
-+      if (status & RV3028_STATUS_TF) {
-+              status |= RV3028_STATUS_TF;
-+              ctrl |= RV3028_CTRL2_TIE;
-+              events |= RTC_PF;
-+      }
-+
-+      if (status & RV3028_STATUS_AF) {
-+              status |= RV3028_STATUS_AF;
-+              ctrl |= RV3028_CTRL2_AIE;
-+              events |= RTC_AF;
-+      }
-+
-+      if (status & RV3028_STATUS_UF) {
-+              status |= RV3028_STATUS_UF;
-+              ctrl |= RV3028_CTRL2_UIE;
-+              events |= RTC_UF;
-+      }
-+
-+      if (events) {
-+              rtc_update_irq(rv3028->rtc, 1, events);
-+              regmap_update_bits(rv3028->regmap, RV3028_STATUS, status, 0);
-+              regmap_update_bits(rv3028->regmap, RV3028_CTRL2, ctrl, 0);
-+      }
-+
-+      if (status & RV3028_STATUS_EVF) {
-+              sysfs_notify(&rv3028->rtc->dev.kobj, NULL,
-+                           dev_attr_timestamp0.attr.name);
-+              dev_warn(&rv3028->rtc->dev, "event detected");
-+      }
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int rv3028_get_time(struct device *dev, struct rtc_time *tm)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      u8 date[7];
-+      int ret, status;
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+      if (ret < 0)
-+              return ret;
-+
-+      if (status & RV3028_STATUS_PORF) {
-+              dev_warn(dev, "Voltage low, data is invalid.\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = regmap_bulk_read(rv3028->regmap, RV3028_SEC, date, sizeof(date));
-+      if (ret)
-+              return ret;
-+
-+      tm->tm_sec  = bcd2bin(date[RV3028_SEC] & 0x7f);
-+      tm->tm_min  = bcd2bin(date[RV3028_MIN] & 0x7f);
-+      tm->tm_hour = bcd2bin(date[RV3028_HOUR] & 0x3f);
-+      tm->tm_wday = ilog2(date[RV3028_WDAY] & 0x7f);
-+      tm->tm_mday = bcd2bin(date[RV3028_DAY] & 0x3f);
-+      tm->tm_mon  = bcd2bin(date[RV3028_MONTH] & 0x1f) - 1;
-+      tm->tm_year = bcd2bin(date[RV3028_YEAR]) + 100;
-+
-+      return 0;
-+}
-+
-+static int rv3028_set_time(struct device *dev, struct rtc_time *tm)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      u8 date[7];
-+      int ret;
-+
-+      date[RV3028_SEC]   = bin2bcd(tm->tm_sec);
-+      date[RV3028_MIN]   = bin2bcd(tm->tm_min);
-+      date[RV3028_HOUR]  = bin2bcd(tm->tm_hour);
-+      date[RV3028_WDAY]  = 1 << (tm->tm_wday);
-+      date[RV3028_DAY]   = bin2bcd(tm->tm_mday);
-+      date[RV3028_MONTH] = bin2bcd(tm->tm_mon + 1);
-+      date[RV3028_YEAR]  = bin2bcd(tm->tm_year - 100);
-+
-+      /*
-+       * Writing to the Seconds register has the same effect as setting RESET
-+       * bit to 1
-+       */
-+      ret = regmap_bulk_write(rv3028->regmap, RV3028_SEC, date,
-+                              sizeof(date));
-+      if (ret)
-+              return ret;
-+
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+                               RV3028_STATUS_PORF, 0);
-+
-+      return ret;
-+}
-+
-+static int rv3028_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      u8 alarmvals[3];
-+      int status, ctrl, ret;
-+
-+      ret = regmap_bulk_read(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
-+                             sizeof(alarmvals));
-+      if (ret)
-+              return ret;
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_CTRL2, &ctrl);
-+      if (ret < 0)
-+              return ret;
-+
-+      alrm->time.tm_sec  = 0;
-+      alrm->time.tm_min  = bcd2bin(alarmvals[0] & 0x7f);
-+      alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
-+      alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
-+
-+      alrm->enabled = !!(ctrl & RV3028_CTRL2_AIE);
-+      alrm->pending = (status & RV3028_STATUS_AF) && alrm->enabled;
-+
-+      return 0;
-+}
-+
-+static int rv3028_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      u8 alarmvals[3];
-+      u8 ctrl = 0;
-+      int ret;
-+
-+      /* The alarm has no seconds, round up to nearest minute */
-+      if (alrm->time.tm_sec) {
-+              time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
-+
-+              alarm_time += 60 - alrm->time.tm_sec;
-+              rtc_time64_to_tm(alarm_time, &alrm->time);
-+      }
-+
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+                               RV3028_CTRL2_AIE | RV3028_CTRL2_UIE, 0);
-+      if (ret)
-+              return ret;
-+
-+      alarmvals[0] = bin2bcd(alrm->time.tm_min);
-+      alarmvals[1] = bin2bcd(alrm->time.tm_hour);
-+      alarmvals[2] = bin2bcd(alrm->time.tm_mday);
-+
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+                               RV3028_STATUS_AF, 0);
-+      if (ret)
-+              return ret;
-+
-+      ret = regmap_bulk_write(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
-+                              sizeof(alarmvals));
-+      if (ret)
-+              return ret;
-+
-+      if (alrm->enabled) {
-+              if (rv3028->rtc->uie_rtctimer.enabled)
-+                      ctrl |= RV3028_CTRL2_UIE;
-+              if (rv3028->rtc->aie_timer.enabled)
-+                      ctrl |= RV3028_CTRL2_AIE;
-+      }
-+
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+                               RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
-+
-+      return ret;
-+}
-+
-+static int rv3028_alarm_irq_enable(struct device *dev, unsigned int enabled)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      int ctrl = 0, ret;
-+
-+      if (enabled) {
-+              if (rv3028->rtc->uie_rtctimer.enabled)
-+                      ctrl |= RV3028_CTRL2_UIE;
-+              if (rv3028->rtc->aie_timer.enabled)
-+                      ctrl |= RV3028_CTRL2_AIE;
-+      }
-+
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+                               RV3028_STATUS_AF | RV3028_STATUS_UF, 0);
-+      if (ret)
-+              return ret;
-+
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+                               RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
-+      if (ret)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static int rv3028_read_offset(struct device *dev, long *offset)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      int ret, value, steps;
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_OFFSET, &value);
-+      if (ret < 0)
-+              return ret;
-+
-+      steps = sign_extend32(value << 1, 8);
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
-+      if (ret < 0)
-+              return ret;
-+
-+      steps += value >> 7;
-+
-+      *offset = DIV_ROUND_CLOSEST(steps * OFFSET_STEP_PPT, 1000);
-+
-+      return 0;
-+}
-+
-+static int rv3028_set_offset(struct device *dev, long offset)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      int ret;
-+
-+      offset = clamp(offset, -244141L, 243187L) * 1000;
-+      offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT);
-+
-+      ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1);
-+      if (ret < 0)
-+              return ret;
-+
-+      return regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7),
-+                                offset << 7);
-+}
-+
-+static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-+{
-+      struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+      int status, ret = 0;
-+
-+      switch (cmd) {
-+      case RTC_VL_READ:
-+              ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+              if (ret < 0)
-+                      return ret;
-+
-+              if (status & RV3028_STATUS_PORF)
-+                      dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
-+
-+              status &= RV3028_STATUS_PORF;
-+
-+              if (copy_to_user((void __user *)arg, &status, sizeof(int)))
-+                      return -EFAULT;
-+
-+              return 0;
-+
-+      case RTC_VL_CLR:
-+              ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+                                       RV3028_STATUS_PORF, 0);
-+
-+              return ret;
-+
-+      default:
-+              return -ENOIOCTLCMD;
-+      }
-+}
-+
-+static int rv3028_nvram_write(void *priv, unsigned int offset, void *val,
-+                            size_t bytes)
-+{
-+      return regmap_bulk_write(priv, RV3028_RAM1 + offset, val, bytes);
-+}
-+
-+static int rv3028_nvram_read(void *priv, unsigned int offset, void *val,
-+                           size_t bytes)
-+{
-+      return regmap_bulk_read(priv, RV3028_RAM1 + offset, val, bytes);
-+}
-+
-+static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
-+                             size_t bytes)
-+{
-+      u32 status, ctrl1;
-+      int i, ret, err;
-+      u8 *buf = val;
-+
-+      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;
-+      }
-+
-+      for (i = 0; i < bytes; i++) {
-+              ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
-+              if (ret)
-+                      goto restore_eerd;
-+
-+              ret = regmap_write(priv, RV3028_EEPROM_DATA, buf[i]);
-+              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_WRITE);
-+              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 int rv3028_eeprom_read(void *priv, unsigned int offset, void *val,
-+                            size_t bytes)
-+{
-+      u32 status, ctrl1, data;
-+      int i, ret, err;
-+      u8 *buf = val;
-+
-+      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;
-+      }
-+
-+      for (i = 0; i < bytes; i++) {
-+              ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
-+              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_READ);
-+              if (ret)
-+                      goto restore_eerd;
-+
-+              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_read(priv, RV3028_EEPROM_DATA, &data);
-+              if (ret)
-+                      goto restore_eerd;
-+              buf[i] = data;
-+      }
-+
-+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,
-+      .read_offset = rv3028_read_offset,
-+      .set_offset = rv3028_set_offset,
-+      .ioctl = rv3028_ioctl,
-+};
-+
-+static const struct regmap_config regmap_config = {
-+        .reg_bits = 8,
-+        .val_bits = 8,
-+        .max_register = 0x37,
-+};
-+
-+static int rv3028_probe(struct i2c_client *client)
-+{
-+      struct rv3028_data *rv3028;
-+      int ret, status;
-+      u32 ohms;
-+      struct nvmem_config nvmem_cfg = {
-+              .name = "rv3028_nvram",
-+              .word_size = 1,
-+              .stride = 1,
-+              .size = 2,
-+              .type = NVMEM_TYPE_BATTERY_BACKED,
-+              .reg_read = rv3028_nvram_read,
-+              .reg_write = rv3028_nvram_write,
-+      };
-+      struct nvmem_config eeprom_cfg = {
-+              .name = "rv3028_eeprom",
-+              .word_size = 1,
-+              .stride = 1,
-+              .size = 43,
-+              .type = NVMEM_TYPE_EEPROM,
-+              .reg_read = rv3028_eeprom_read,
-+              .reg_write = rv3028_eeprom_write,
-+      };
-+
-+      rv3028 = devm_kzalloc(&client->dev, sizeof(struct rv3028_data),
-+                            GFP_KERNEL);
-+      if (!rv3028)
-+              return -ENOMEM;
-+
-+      rv3028->regmap = devm_regmap_init_i2c(client, &regmap_config);
-+
-+      i2c_set_clientdata(client, rv3028);
-+
-+      ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+      if (ret < 0)
-+              return ret;
-+
-+      if (status & RV3028_STATUS_PORF)
-+              dev_warn(&client->dev, "Voltage low, data loss detected.\n");
-+
-+      if (status & RV3028_STATUS_AF)
-+              dev_warn(&client->dev, "An alarm may have been missed.\n");
-+
-+      rv3028->rtc = devm_rtc_allocate_device(&client->dev);
-+      if (IS_ERR(rv3028->rtc)) {
-+              return PTR_ERR(rv3028->rtc);
-+      }
-+
-+      if (client->irq > 0) {
-+              ret = devm_request_threaded_irq(&client->dev, client->irq,
-+                                              NULL, rv3028_handle_irq,
-+                                              IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-+                                              "rv3028", rv3028);
-+              if (ret) {
-+                      dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
-+                      client->irq = 0;
-+              } else {
-+                      rv3028_rtc_ops.read_alarm = rv3028_get_alarm;
-+                      rv3028_rtc_ops.set_alarm = rv3028_set_alarm;
-+                      rv3028_rtc_ops.alarm_irq_enable = rv3028_alarm_irq_enable;
-+              }
-+      }
-+
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1,
-+                               RV3028_CTRL1_WADA, RV3028_CTRL1_WADA);
-+      if (ret)
-+              return ret;
-+
-+      /* setup timestamping */
-+      ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+                               RV3028_CTRL2_EIE | RV3028_CTRL2_TSE,
-+                               RV3028_CTRL2_EIE | RV3028_CTRL2_TSE);
-+      if (ret)
-+              return ret;
-+
-+      /* setup trickle charger */
-+      if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
-+                                    &ohms)) {
-+              int i;
-+
-+              for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
-+                      if (ohms == rv3028_trickle_resistors[i])
-+                              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;
-+              } else {
-+                      dev_warn(&client->dev, "invalid trickle resistor value\n");
-+              }
-+      }
-+
-+      ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
-+      if (ret)
-+              return ret;
-+
-+      rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-+      rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099;
-+      rv3028->rtc->ops = &rv3028_rtc_ops;
-+      ret = rtc_register_device(rv3028->rtc);
-+      if (ret)
-+              return ret;
-+
-+      nvmem_cfg.priv = rv3028->regmap;
-+      rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
-+      eeprom_cfg.priv = rv3028->regmap;
-+      rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
-+
-+      rv3028->rtc->max_user_freq = 1;
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id rv3028_of_match[] = {
-+      { .compatible = "microcrystal,rv3028", },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(of, rv3028_of_match);
-+
-+static struct i2c_driver rv3028_driver = {
-+      .driver = {
-+              .name = "rtc-rv3028",
-+              .of_match_table = of_match_ptr(rv3028_of_match),
-+      },
-+      .probe_new      = rv3028_probe,
-+};
-+module_i2c_driver(rv3028_driver);
-+
-+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
-+MODULE_DESCRIPTION("Micro Crystal RV3028 RTC driver");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0342-ASoC-tlv320aic32x4-Break-out-clock-setting-into-sepa.patch b/target/linux/brcm2708/patches-4.19/950-0342-ASoC-tlv320aic32x4-Break-out-clock-setting-into-sepa.patch
new file mode 100644 (file)
index 0000000..3a63be1
--- /dev/null
@@ -0,0 +1,64 @@
+From 95b3311cbcd29e07af1ee96b6b37c9089567bcff Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Mon, 18 Mar 2019 20:37:44 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Break out clock setting into
+ separate function
+
+commit bf31cbfbe25001036e1e096b1c260bf871766ea5 upstream.
+
+Break the clock setting logic out from the main hw_params.  It's
+rather large and unweildy and makes for a large function.  This
+also better enables some of the following changes to the clock
+tree access in the driver.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -698,17 +698,13 @@ static int aic32x4_set_dai_fmt(struct sn
+       return 0;
+ }
+-static int aic32x4_hw_params(struct snd_pcm_substream *substream,
+-                           struct snd_pcm_hw_params *params,
+-                           struct snd_soc_dai *dai)
++static int aic32x4_setup_clocks(struct snd_soc_component *component,
++                              unsigned int sample_rate,
++                              unsigned int parent_rate)
+ {
+-      struct snd_soc_component *component = dai->component;
+-      struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+-      u8 iface1_reg = 0;
+-      u8 dacsetup_reg = 0;
+       int i;
+-      i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params));
++      i = aic32x4_get_divs(parent_rate, sample_rate);
+       if (i < 0) {
+               printk(KERN_ERR "aic32x4: sampling rate not supported\n");
+               return i;
+@@ -765,6 +761,20 @@ static int aic32x4_hw_params(struct snd_
+       snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+                           AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
++      return 0;
++}
++
++static int aic32x4_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 aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
++      u8 iface1_reg = 0;
++      u8 dacsetup_reg = 0;
++
++      aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
++
+       switch (params_width(params)) {
+       case 16:
+               iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
diff --git a/target/linux/brcm2708/patches-4.19/950-0342-overlays-Add-rv3028-to-i2c-rtc.patch b/target/linux/brcm2708/patches-4.19/950-0342-overlays-Add-rv3028-to-i2c-rtc.patch
deleted file mode 100644 (file)
index 2228022..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-From 67dd8e4c8ccf5d331960c7e936e5b03a9f92496d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 28 Mar 2019 13:26:59 +0000
-Subject: [PATCH] overlays: Add rv3028 to i2c-rtc
-
-See: https://github.com/raspberrypi/linux/issues/2912
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README             |  4 +++-
- .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 19 ++++++++++++++++++-
- 2 files changed, 21 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -939,6 +939,8 @@ Params: abx80x                  Select o
-         pcf8563                 Select the PCF8563 device
-+        rv3028                  Select the Micro Crystal RV3028 device
-+
-         addr                    Sets the address for the RTC. Note that the
-                                 device must be configured to use the specified
-                                 address.
-@@ -947,7 +949,7 @@ Params: abx80x                  Select o
-                                 "schottky" (ABx80x only)
-         trickle-resistor-ohms   Resistor value for trickle charge (DS1339,
--                                ABx80x)
-+                                ABx80x, RV3028)
-         wakeup-source           Specify that the RTC can be used as a wakeup
-                                 source
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -158,6 +158,21 @@
-               };
-       };
-+      fragment@10 {
-+              target = <&i2c_arm>;
-+              __dormant__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      rv3028: rv3028@52 {
-+                              compatible = "microcrystal,rv3028";
-+                              reg = <0x52>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-       __overrides__ {
-               abx80x = <0>,"+0";
-               ds1307 = <0>,"+1";
-@@ -169,6 +184,7 @@
-               pcf8523 = <0>,"+7";
-               pcf8563 = <0>,"+8";
-               m41t62 = <0>,"+9";
-+              rv3028 = <0>,"+10";
-               addr = <&abx80x>, "reg:0",
-                      <&ds1307>, "reg:0",
-@@ -182,7 +198,8 @@
-                      <&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",
-+                                      <&rv3028>,"trickle-resistor-ohms:0";
-               wakeup-source = <&ds1339>,"wakeup-source?",
-                               <&ds3231>,"wakeup-source?",
-                               <&mcp7940x>,"wakeup-source?",
diff --git a/target/linux/brcm2708/patches-4.19/950-0343-ASoC-tlv320aic32x4-Properly-Set-Processing-Blocks.patch b/target/linux/brcm2708/patches-4.19/950-0343-ASoC-tlv320aic32x4-Properly-Set-Processing-Blocks.patch
new file mode 100644 (file)
index 0000000..cae096b
--- /dev/null
@@ -0,0 +1,111 @@
+From 6cc882cf38b62fce2a07640413b05b43b420c77a Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 20 Mar 2019 19:38:44 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Properly Set Processing Blocks
+
+commit c95e3a4b96293403a427b5185e60fad28af51fdd upstream.
+
+Different processing blocks are required for different sampling
+rates and power parameters.  Set the processing blocks based
+on this information.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 56 ++++++++++++++++++++------------
+ 1 file changed, 36 insertions(+), 20 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -59,6 +59,8 @@ struct aic32x4_rate_divs {
+       u8 nadc;
+       u8 madc;
+       u8 blck_N;
++      u8 r_block;
++      u8 p_block;
+ };
+ struct aic32x4_priv {
+@@ -307,34 +309,34 @@ static const struct snd_kcontrol_new aic
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+       /* 8k rate */
+-      {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
+-      {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
+-      {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
++      {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
++      {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
++      {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
+       /* 11.025k rate */
+-      {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
+-      {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
++      {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
++      {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
+       /* 16k rate */
+-      {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
+-      {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
+-      {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
++      {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
++      {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
++      {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
+       /* 22.05k rate */
+-      {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
+-      {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
+-      {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
++      {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
++      {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
++      {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
+       /* 32k rate */
+-      {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
+-      {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
++      {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
++      {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
+       /* 44.1k rate */
+-      {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
+-      {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
+-      {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
++      {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
++      {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++      {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+       /* 48k rate */
+-      {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
+-      {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
+-      {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},
++      {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
++      {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++      {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+       /* 96k rate */
+-      {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1},
++      {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
+ };
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -698,6 +700,18 @@ static int aic32x4_set_dai_fmt(struct sn
+       return 0;
+ }
++static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
++                                              u8 r_block, u8 p_block)
++{
++      if (r_block > 18 || p_block > 25)
++              return -EINVAL;
++
++      snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
++      snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
++
++      return 0;
++}
++
+ static int aic32x4_setup_clocks(struct snd_soc_component *component,
+                               unsigned int sample_rate,
+                               unsigned int parent_rate)
+@@ -710,6 +724,8 @@ static int aic32x4_setup_clocks(struct s
+               return i;
+       }
++      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
++
+       /* MCLK as PLL_CLKIN */
+       snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
+                           AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
diff --git a/target/linux/brcm2708/patches-4.19/950-0343-ASoC-tlv320aic32x4-SND_SOC_DAPM_MICBIAS-is-deprecate.patch b/target/linux/brcm2708/patches-4.19/950-0343-ASoC-tlv320aic32x4-SND_SOC_DAPM_MICBIAS-is-deprecate.patch
deleted file mode 100644 (file)
index aa5f12a..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From 053938f67f73773152f70d89aa32e7893ee19694 Mon Sep 17 00:00:00 2001
-From: b-ak <anur.bhargav@gmail.com>
-Date: Wed, 9 Jan 2019 22:41:21 +0530
-Subject: [PATCH] ASoC: tlv320aic32x4: SND_SOC_DAPM_MICBIAS is
- deprecated
-
-commit 04d979d7a7bac2f645cd827ea37e5ffa5b4e1f97 upstream.
-
-SND_SOC_DAPM_MICBIAS is deprecated, replace it with SND_SOC_DAPM_SUPPLY.
-
-MICBIAS voltage wasn't supplied to the microphone with the older
-SND_SOC_DAPM_MICBIAS widget, hence the microphone wouldn't work.
-
-This patch fixes the problem.
-
-Signed-off-by: b-ak <anur.bhargav@gmail.com>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 30 +++++++++++++++++++++++++++++-
- sound/soc/codecs/tlv320aic32x4.h |  1 +
- 2 files changed, 30 insertions(+), 1 deletion(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -79,6 +79,32 @@ struct aic32x4_priv {
-       struct device *dev;
- };
-+static int mic_bias_event(struct snd_soc_dapm_widget *w,
-+      struct snd_kcontrol *kcontrol, int event)
-+{
-+      struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-+
-+      switch (event) {
-+      case SND_SOC_DAPM_POST_PMU:
-+              /* Change Mic Bias Registor */
-+              snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
-+                              AIC32x4_MICBIAS_MASK,
-+                              AIC32X4_MICBIAS_LDOIN |
-+                              AIC32X4_MICBIAS_2075V);
-+              printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
-+              break;
-+      case SND_SOC_DAPM_PRE_PMD:
-+              snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
-+                              AIC32x4_MICBIAS_MASK, 0);
-+              printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
-+                              __func__);
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+
- static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
- {
-@@ -450,7 +476,9 @@ static const struct snd_soc_dapm_widget
-       SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
-                       in3r_to_lmixer_controls),
--      SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
-+      SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
-+                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-+
-       SND_SOC_DAPM_OUTPUT("HPL"),
-       SND_SOC_DAPM_OUTPUT("HPR"),
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -195,6 +195,7 @@ int aic32x4_remove(struct device *dev);
- /* AIC32X4_MICBIAS */
- #define AIC32X4_MICBIAS_LDOIN         BIT(3)
- #define AIC32X4_MICBIAS_2075V         0x60
-+#define AIC32x4_MICBIAS_MASK            GENMASK(6, 3)
- /* AIC32X4_LMICPGANIN */
- #define AIC32X4_LMICPGANIN_IN2R_10K   0x10
diff --git a/target/linux/brcm2708/patches-4.19/950-0344-ASoC-tlv320aic32x4-Break-out-clock-setting-into-sepa.patch b/target/linux/brcm2708/patches-4.19/950-0344-ASoC-tlv320aic32x4-Break-out-clock-setting-into-sepa.patch
deleted file mode 100644 (file)
index 3a63be1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From 95b3311cbcd29e07af1ee96b6b37c9089567bcff Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Mon, 18 Mar 2019 20:37:44 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Break out clock setting into
- separate function
-
-commit bf31cbfbe25001036e1e096b1c260bf871766ea5 upstream.
-
-Break the clock setting logic out from the main hw_params.  It's
-rather large and unweildy and makes for a large function.  This
-also better enables some of the following changes to the clock
-tree access in the driver.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 26 ++++++++++++++++++--------
- 1 file changed, 18 insertions(+), 8 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -698,17 +698,13 @@ static int aic32x4_set_dai_fmt(struct sn
-       return 0;
- }
--static int aic32x4_hw_params(struct snd_pcm_substream *substream,
--                           struct snd_pcm_hw_params *params,
--                           struct snd_soc_dai *dai)
-+static int aic32x4_setup_clocks(struct snd_soc_component *component,
-+                              unsigned int sample_rate,
-+                              unsigned int parent_rate)
- {
--      struct snd_soc_component *component = dai->component;
--      struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
--      u8 iface1_reg = 0;
--      u8 dacsetup_reg = 0;
-       int i;
--      i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params));
-+      i = aic32x4_get_divs(parent_rate, sample_rate);
-       if (i < 0) {
-               printk(KERN_ERR "aic32x4: sampling rate not supported\n");
-               return i;
-@@ -765,6 +761,20 @@ static int aic32x4_hw_params(struct snd_
-       snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-                           AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
-+      return 0;
-+}
-+
-+static int aic32x4_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 aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-+      u8 iface1_reg = 0;
-+      u8 dacsetup_reg = 0;
-+
-+      aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
-+
-       switch (params_width(params)) {
-       case 16:
-               iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
diff --git a/target/linux/brcm2708/patches-4.19/950-0344-ASoC-tlv320aic32x4-Model-PLL-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0344-ASoC-tlv320aic32x4-Model-PLL-in-CCF.patch
new file mode 100644 (file)
index 0000000..4e0ddb9
--- /dev/null
@@ -0,0 +1,877 @@
+From 957ccf05060d65da074d019679ec7f486477e412 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:45 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Model PLL in CCF
+
+commit 514b044cba667e4b7c383ec79b42b997e624b91d upstream.
+
+Model and manage the on-board PLL as a component in the Core
+Clock Framework.  This should allow us to do some more complex
+clock management and power control.  Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/Kconfig             |   1 +
+ sound/soc/codecs/Makefile            |   2 +-
+ sound/soc/codecs/tlv320aic32x4-clk.c | 323 +++++++++++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c     | 195 ++++++++--------
+ sound/soc/codecs/tlv320aic32x4.h     |   5 +
+ 5 files changed, 431 insertions(+), 95 deletions(-)
+ create mode 100644 sound/soc/codecs/tlv320aic32x4-clk.c
+
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -1025,6 +1025,7 @@ config SND_SOC_TLV320AIC31XX
+ config SND_SOC_TLV320AIC32X4
+       tristate
++      depends on COMMON_CLK
+ config SND_SOC_TLV320AIC32X4_I2C
+       tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -182,7 +182,7 @@ snd-soc-tlv320aic23-i2c-objs := tlv320ai
+ snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
+ snd-soc-tlv320aic26-objs := tlv320aic26.o
+ snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
+-snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
++snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o tlv320aic32x4-clk.o
+ snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o
+ snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o
+ snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+--- /dev/null
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -0,0 +1,323 @@
++/* SPDX-License-Identifier: GPL-2.0
++ *
++ * Clock Tree for the Texas Instruments TLV320AIC32x4
++ *
++ * Copyright 2019 Annaliese McDermond
++ *
++ * Author: Annaliese McDermond <nh6z@nh6z.net>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/clkdev.h>
++#include <linux/regmap.h>
++#include <linux/device.h>
++
++#include "tlv320aic32x4.h"
++
++#define to_clk_aic32x4(_hw) container_of(_hw, struct clk_aic32x4, hw)
++struct clk_aic32x4 {
++      struct clk_hw hw;
++      struct device *dev;
++      struct regmap *regmap;
++      unsigned int reg;
++};
++
++/*
++ * struct clk_aic32x4_pll_muldiv - Multiplier/divider settings
++ * @p:                Divider
++ * @r:                first multiplier
++ * @j:                integer part of second multiplier
++ * @d:                decimal part of second multiplier
++ */
++struct clk_aic32x4_pll_muldiv {
++      u8 p;
++      u16 r;
++      u8 j;
++      u16 d;
++};
++
++struct aic32x4_clkdesc {
++      const char *name;
++      const char * const *parent_names;
++      unsigned int num_parents;
++      const struct clk_ops *ops;
++      unsigned int reg;
++};
++
++static int clk_aic32x4_pll_prepare(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++      return regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++                              AIC32X4_PLLEN, AIC32X4_PLLEN);
++}
++
++static void clk_aic32x4_pll_unprepare(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++      regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++                              AIC32X4_PLLEN, 0);
++}
++
++static int clk_aic32x4_pll_is_prepared(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++      unsigned int val;
++      int ret;
++
++      ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
++      if (ret < 0)
++              return ret;
++
++      return !!(val & AIC32X4_PLLEN);
++}
++
++static int clk_aic32x4_pll_get_muldiv(struct clk_aic32x4 *pll,
++                      struct clk_aic32x4_pll_muldiv *settings)
++{
++      /*      Change to use regmap_bulk_read? */
++      unsigned int val;
++      int ret;
++
++      ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
++      if (ret)
++              return ret;
++      settings->r = val & AIC32X4_PLL_R_MASK;
++      settings->p = (val & AIC32X4_PLL_P_MASK) >> AIC32X4_PLL_P_SHIFT;
++
++      ret = regmap_read(pll->regmap, AIC32X4_PLLJ, &val);
++      if (ret < 0)
++              return ret;
++      settings->j = val;
++
++      ret = regmap_read(pll->regmap, AIC32X4_PLLDMSB, &val);
++      if (ret < 0)
++              return ret;
++      settings->d = val << 8;
++
++      ret = regmap_read(pll->regmap, AIC32X4_PLLDLSB,  &val);
++      if (ret < 0)
++              return ret;
++      settings->d |= val;
++
++      return 0;
++}
++
++static int clk_aic32x4_pll_set_muldiv(struct clk_aic32x4 *pll,
++                      struct clk_aic32x4_pll_muldiv *settings)
++{
++      int ret;
++      /*      Change to use regmap_bulk_write for some if not all? */
++
++      ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++                              AIC32X4_PLL_R_MASK, settings->r);
++      if (ret < 0)
++              return ret;
++
++      ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++                              AIC32X4_PLL_P_MASK,
++                              settings->p << AIC32X4_PLL_P_SHIFT);
++      if (ret < 0)
++              return ret;
++
++      ret = regmap_write(pll->regmap, AIC32X4_PLLJ, settings->j);
++      if (ret < 0)
++              return ret;
++
++      ret = regmap_write(pll->regmap, AIC32X4_PLLDMSB, (settings->d >> 8));
++      if (ret < 0)
++              return ret;
++      ret = regmap_write(pll->regmap, AIC32X4_PLLDLSB, (settings->d & 0xff));
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static unsigned long clk_aic32x4_pll_calc_rate(
++                      struct clk_aic32x4_pll_muldiv *settings,
++                      unsigned long parent_rate)
++{
++      u64 rate;
++      /*
++       * We scale j by 10000 to account for the decimal part of P and divide
++       * it back out later.
++       */
++      rate = (u64) parent_rate * settings->r *
++                              ((settings->j * 10000) + settings->d);
++
++      return (unsigned long) DIV_ROUND_UP_ULL(rate, settings->p * 10000);
++}
++
++static int clk_aic32x4_pll_calc_muldiv(struct clk_aic32x4_pll_muldiv *settings,
++                      unsigned long rate, unsigned long parent_rate)
++{
++      u64 multiplier;
++
++      settings->p = parent_rate / AIC32X4_MAX_PLL_CLKIN + 1;
++      if (settings->p > 8)
++              return -1;
++
++      /*
++       * We scale this figure by 10000 so that we can get the decimal part
++       * of the multiplier.   This is because we can't do floating point
++       * math in the kernel.
++       */
++       multiplier = (u64) rate * settings->p * 10000;
++       do_div(multiplier, parent_rate);
++
++      /*
++       * J can't be over 64, so R can scale this.
++       * R can't be greater than 4.
++       */
++      settings->r = ((u32) multiplier / 640000) + 1;
++      if (settings->r > 4)
++              return -1;
++      do_div(multiplier, settings->r);
++
++      /*
++       * J can't be < 1.
++       */
++      if (multiplier < 10000)
++              return -1;
++
++      /* Figure out the integer part, J, and the fractional part, D. */
++      settings->j = (u32) multiplier / 10000;
++      settings->d = (u32) multiplier % 10000;
++
++      return 0;
++}
++
++static unsigned long clk_aic32x4_pll_recalc_rate(struct clk_hw *hw,
++                      unsigned long parent_rate)
++{
++      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++      struct clk_aic32x4_pll_muldiv settings;
++      int ret;
++
++      ret =  clk_aic32x4_pll_get_muldiv(pll, &settings);
++      if (ret < 0)
++              return 0;
++
++      return clk_aic32x4_pll_calc_rate(&settings, parent_rate);
++}
++
++static long clk_aic32x4_pll_round_rate(struct clk_hw *hw,
++                      unsigned long rate,
++                      unsigned long *parent_rate)
++{
++      struct clk_aic32x4_pll_muldiv settings;
++      int ret;
++
++      ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, *parent_rate);
++      if (ret < 0)
++              return 0;
++
++      return clk_aic32x4_pll_calc_rate(&settings, *parent_rate);
++}
++
++static int clk_aic32x4_pll_set_rate(struct clk_hw *hw,
++                      unsigned long rate,
++                      unsigned long parent_rate)
++{
++      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++      struct clk_aic32x4_pll_muldiv settings;
++      int ret;
++
++      ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, parent_rate);
++      if (ret < 0)
++              return -EINVAL;
++
++      return clk_aic32x4_pll_set_muldiv(pll, &settings);
++}
++
++static int clk_aic32x4_pll_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++      return regmap_update_bits(pll->regmap,
++                              AIC32X4_CLKMUX,
++                              AIC32X4_PLL_CLKIN_MASK,
++                              index << AIC32X4_PLL_CLKIN_SHIFT);
++}
++
++static u8 clk_aic32x4_pll_get_parent(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++      unsigned int val;
++
++      regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
++
++      return (val & AIC32X4_PLL_CLKIN_MASK) >> AIC32X4_PLL_CLKIN_SHIFT;
++}
++
++
++static const struct clk_ops aic32x4_pll_ops = {
++      .prepare = clk_aic32x4_pll_prepare,
++      .unprepare = clk_aic32x4_pll_unprepare,
++      .is_prepared = clk_aic32x4_pll_is_prepared,
++      .recalc_rate = clk_aic32x4_pll_recalc_rate,
++      .round_rate = clk_aic32x4_pll_round_rate,
++      .set_rate = clk_aic32x4_pll_set_rate,
++      .set_parent = clk_aic32x4_pll_set_parent,
++      .get_parent = clk_aic32x4_pll_get_parent,
++};
++
++static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
++      {
++              .name = "pll",
++              .parent_names =
++                      (const char* []) { "mclk", "bclk", "gpio", "din" },
++              .num_parents = 4,
++              .ops = &aic32x4_pll_ops,
++              .reg = 0,
++      },
++};
++
++static struct clk *aic32x4_register_clk(struct device *dev,
++                      struct aic32x4_clkdesc *desc)
++{
++      struct clk_init_data init;
++      struct clk_aic32x4 *priv;
++      const char *devname = dev_name(dev);
++
++      init.ops = desc->ops;
++      init.name = desc->name;
++      init.parent_names = desc->parent_names;
++      init.num_parents = desc->num_parents;
++      init.flags = 0;
++
++      priv = devm_kzalloc(dev, sizeof(struct clk_aic32x4), GFP_KERNEL);
++      if (priv == NULL)
++              return (struct clk *) -ENOMEM;
++
++      priv->dev = dev;
++      priv->hw.init = &init;
++      priv->regmap = dev_get_regmap(dev, NULL);
++      priv->reg = desc->reg;
++
++      clk_hw_register_clkdev(&priv->hw, desc->name, devname);
++      return devm_clk_register(dev, &priv->hw);
++}
++
++int aic32x4_register_clocks(struct device *dev, const char *mclk_name)
++{
++      int i;
++
++      /*
++       * These lines are here to preserve the current functionality of
++       * the driver with regard to the DT.  These should eventually be set
++       * by DT nodes so that the connections can be set up in configuration
++       * rather than code.
++       */
++      aic32x4_clkdesc_array[0].parent_names =
++                      (const char* []) { mclk_name, "bclk", "gpio", "din" };
++
++      for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
++              aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(aic32x4_register_clocks);
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -14,7 +14,7 @@
+  *
+  * 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
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+@@ -33,6 +33,7 @@
+ #include <linux/cdev.h>
+ #include <linux/slab.h>
+ #include <linux/clk.h>
++#include <linux/of_clk.h>
+ #include <linux/regulator/consumer.h>
+ #include <sound/tlv320aic32x4.h>
+@@ -49,9 +50,7 @@
+ struct aic32x4_rate_divs {
+       u32 mclk;
+       u32 rate;
+-      u8 p_val;
+-      u8 pll_j;
+-      u16 pll_d;
++      unsigned long pll_rate;
+       u16 dosr;
+       u8 ndac;
+       u8 mdac;
+@@ -71,6 +70,7 @@ struct aic32x4_priv {
+       bool swapdacs;
+       int rstn_gpio;
+       struct clk *mclk;
++      const char *mclk_name;
+       struct regulator *supply_ldo;
+       struct regulator *supply_iov;
+@@ -309,34 +309,34 @@ static const struct snd_kcontrol_new aic
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+       /* 8k rate */
+-      {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
+-      {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
+-      {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
++      { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
++      { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
++      { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
+       /* 11.025k rate */
+-      {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
+-      {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
++      { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
++      { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
+       /* 16k rate */
+-      {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
+-      {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
+-      {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
++      { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
++      { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
++      { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
+       /* 22.05k rate */
+-      {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
+-      {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
+-      {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
++      { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
++      { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
++      { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
+       /* 32k rate */
+-      {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
+-      {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
++      { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
++      { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
+       /* 44.1k rate */
+-      {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
+-      {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+-      {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++      { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
++      { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++      { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+       /* 48k rate */
+-      {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
+-      {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+-      {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++      { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
++      { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++      { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+       /* 96k rate */
+-      {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
++      { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
+ };
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -393,7 +393,7 @@ static const struct snd_kcontrol_new in3
+       SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum),
+ };
+-/*  Right mixer pins */
++/*    Right mixer pins */
+ static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
+ static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
+ static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
+@@ -597,7 +597,7 @@ static const struct snd_soc_dapm_route a
+ static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
+       {
+               .selector_reg = 0,
+-              .selector_mask  = 0xff,
++              .selector_mask  = 0xff,
+               .window_start = 0,
+               .window_len = 128,
+               .range_min = 0,
+@@ -618,7 +618,7 @@ static inline int aic32x4_get_divs(int m
+       for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
+               if ((aic32x4_divs[i].rate == rate)
+-                  && (aic32x4_divs[i].mclk == mclk)) {
++                      && (aic32x4_divs[i].mclk == mclk)) {
+                       return i;
+               }
+       }
+@@ -690,12 +690,12 @@ static int aic32x4_set_dai_fmt(struct sn
+       }
+       snd_soc_component_update_bits(component, AIC32X4_IFACE1,
+-                          AIC32X4_IFACE1_DATATYPE_MASK |
+-                          AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
++                              AIC32X4_IFACE1_DATATYPE_MASK |
++                              AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
+       snd_soc_component_update_bits(component, AIC32X4_IFACE2,
+-                          AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
++                              AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
+       snd_soc_component_update_bits(component, AIC32X4_IFACE3,
+-                          AIC32X4_BCLKINV_MASK, iface_reg_3);
++                              AIC32X4_BCLKINV_MASK, iface_reg_3);
+       return 0;
+ }
+@@ -717,6 +717,11 @@ static int aic32x4_setup_clocks(struct s
+                               unsigned int parent_rate)
+ {
+       int i;
++      int ret;
++
++      struct clk_bulk_data clocks[] = {
++              { .id = "pll" },
++      };
+       i = aic32x4_get_divs(parent_rate, sample_rate);
+       if (i < 0) {
+@@ -724,39 +729,29 @@ static int aic32x4_setup_clocks(struct s
+               return i;
+       }
++      ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
++      if (ret)
++              return ret;
++
++      clk_set_rate(clocks[0].clk, sample_rate);
++
+       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+-      /* MCLK as PLL_CLKIN */
+-      snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
+-                          AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
+       /* PLL as CODEC_CLKIN */
+-      snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_CODEC_CLKIN_MASK,
+-                          AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
++      snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
++                      AIC32X4_CODEC_CLKIN_MASK,
++                      AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
+       /* DAC_MOD_CLK as BDIV_CLKIN */
+       snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
+-                          AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+-
+-      /* We will fix R value to 1 and will make P & J=K.D as variable */
+-      snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_R_MASK, 0x01);
+-
+-      /* PLL P value */
+-      snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_P_MASK,
+-                          aic32x4_divs[i].p_val << AIC32X4_PLL_P_SHIFT);
+-
+-      /* PLL J value */
+-      snd_soc_component_write(component, AIC32X4_PLLJ, aic32x4_divs[i].pll_j);
+-
+-      /* PLL D value */
+-      snd_soc_component_write(component, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8));
+-      snd_soc_component_write(component, AIC32X4_PLLDLSB, (aic32x4_divs[i].pll_d & 0xff));
++                              AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+       /* NDAC divider value */
+       snd_soc_component_update_bits(component, AIC32X4_NDAC,
+-                          AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
++                              AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
+       /* MDAC divider value */
+       snd_soc_component_update_bits(component, AIC32X4_MDAC,
+-                          AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
++                              AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
+       /* DOSR MSB & LSB values */
+       snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+@@ -764,18 +759,18 @@ static int aic32x4_setup_clocks(struct s
+       /* NADC divider value */
+       snd_soc_component_update_bits(component, AIC32X4_NADC,
+-                          AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
++                              AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
+       /* MADC divider value */
+       snd_soc_component_update_bits(component, AIC32X4_MADC,
+-                          AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
++                              AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
+       /* AOSR value */
+       snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
+       /* BCLK N divider */
+       snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+-                          AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
++                              AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
+       return 0;
+ }
+@@ -794,23 +789,23 @@ static int aic32x4_hw_params(struct snd_
+       switch (params_width(params)) {
+       case 16:
+               iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
+-                             AIC32X4_IFACE1_DATALEN_SHIFT);
++                                 AIC32X4_IFACE1_DATALEN_SHIFT);
+               break;
+       case 20:
+               iface1_reg |= (AIC32X4_WORD_LEN_20BITS <<
+-                             AIC32X4_IFACE1_DATALEN_SHIFT);
++                                 AIC32X4_IFACE1_DATALEN_SHIFT);
+               break;
+       case 24:
+               iface1_reg |= (AIC32X4_WORD_LEN_24BITS <<
+-                             AIC32X4_IFACE1_DATALEN_SHIFT);
++                                 AIC32X4_IFACE1_DATALEN_SHIFT);
+               break;
+       case 32:
+               iface1_reg |= (AIC32X4_WORD_LEN_32BITS <<
+-                             AIC32X4_IFACE1_DATALEN_SHIFT);
++                                 AIC32X4_IFACE1_DATALEN_SHIFT);
+               break;
+       }
+       snd_soc_component_update_bits(component, AIC32X4_IFACE1,
+-                          AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
++                              AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
+       if (params_channels(params) == 1) {
+               dacsetup_reg = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN;
+@@ -821,7 +816,7 @@ static int aic32x4_hw_params(struct snd_
+                       dacsetup_reg = AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN;
+       }
+       snd_soc_component_update_bits(component, AIC32X4_DACSETUP,
+-                          AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
++                              AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
+       return 0;
+ }
+@@ -831,7 +826,7 @@ static int aic32x4_mute(struct snd_soc_d
+       struct snd_soc_component *component = dai->component;
+       snd_soc_component_update_bits(component, AIC32X4_DACMUTE,
+-                          AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
++                              AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
+       return 0;
+ }
+@@ -853,27 +848,27 @@ static int aic32x4_set_bias_level(struct
+               /* Switch on PLL */
+               snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+-                                  AIC32X4_PLLEN, AIC32X4_PLLEN);
++                                      AIC32X4_PLLEN, AIC32X4_PLLEN);
+               /* Switch on NDAC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_NDAC,
+-                                  AIC32X4_NDACEN, AIC32X4_NDACEN);
++                                      AIC32X4_NDACEN, AIC32X4_NDACEN);
+               /* Switch on MDAC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_MDAC,
+-                                  AIC32X4_MDACEN, AIC32X4_MDACEN);
++                                      AIC32X4_MDACEN, AIC32X4_MDACEN);
+               /* Switch on NADC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_NADC,
+-                                  AIC32X4_NADCEN, AIC32X4_NADCEN);
++                                      AIC32X4_NADCEN, AIC32X4_NADCEN);
+               /* Switch on MADC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_MADC,
+-                                  AIC32X4_MADCEN, AIC32X4_MADCEN);
++                                      AIC32X4_MADCEN, AIC32X4_MADCEN);
+               /* Switch on BCLK_N Divider */
+               snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+-                                  AIC32X4_BCLKEN, AIC32X4_BCLKEN);
++                                      AIC32X4_BCLKEN, AIC32X4_BCLKEN);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+@@ -884,27 +879,27 @@ static int aic32x4_set_bias_level(struct
+               /* Switch off BCLK_N Divider */
+               snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+-                                  AIC32X4_BCLKEN, 0);
++                                      AIC32X4_BCLKEN, 0);
+               /* Switch off MADC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_MADC,
+-                                  AIC32X4_MADCEN, 0);
++                                      AIC32X4_MADCEN, 0);
+               /* Switch off NADC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_NADC,
+-                                  AIC32X4_NADCEN, 0);
++                                      AIC32X4_NADCEN, 0);
+               /* Switch off MDAC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_MDAC,
+-                                  AIC32X4_MDACEN, 0);
++                                      AIC32X4_MDACEN, 0);
+               /* Switch off NDAC Divider */
+               snd_soc_component_update_bits(component, AIC32X4_NDAC,
+-                                  AIC32X4_NDACEN, 0);
++                                      AIC32X4_NDACEN, 0);
+               /* Switch off PLL */
+               snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+-                                  AIC32X4_PLLEN, 0);
++                                      AIC32X4_PLLEN, 0);
+               /* Switch off master clock */
+               clk_disable_unprepare(aic32x4->mclk);
+@@ -916,7 +911,7 @@ static int aic32x4_set_bias_level(struct
+ }
+ #define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
+-#define AIC32X4_FORMATS       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
++#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+                        | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+ static const struct snd_soc_dai_ops aic32x4_ops = {
+@@ -929,17 +924,17 @@ static const struct snd_soc_dai_ops aic3
+ static struct snd_soc_dai_driver aic32x4_dai = {
+       .name = "tlv320aic32x4-hifi",
+       .playback = {
+-                   .stream_name = "Playback",
+-                   .channels_min = 1,
+-                   .channels_max = 2,
+-                   .rates = AIC32X4_RATES,
+-                   .formats = AIC32X4_FORMATS,},
++                       .stream_name = "Playback",
++                       .channels_min = 1,
++                       .channels_max = 2,
++                       .rates = AIC32X4_RATES,
++                       .formats = AIC32X4_FORMATS,},
+       .capture = {
+-                  .stream_name = "Capture",
+-                  .channels_min = 1,
+-                  .channels_max = 2,
+-                  .rates = AIC32X4_RATES,
+-                  .formats = AIC32X4_FORMATS,},
++                      .stream_name = "Capture",
++                      .channels_min = 1,
++                      .channels_max = 2,
++                      .rates = AIC32X4_RATES,
++                      .formats = AIC32X4_FORMATS,},
+       .ops = &aic32x4_ops,
+       .symmetric_rates = 1,
+ };
+@@ -952,7 +947,7 @@ static void aic32x4_setup_gpios(struct s
+       /* MFP1 */
+       if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) {
+               snd_soc_component_write(component, AIC32X4_DINCTL,
+-                    aic32x4->setup->gpio_func[0]);
++                        aic32x4->setup->gpio_func[0]);
+               snd_soc_add_component_controls(component, aic32x4_mfp1,
+                       ARRAY_SIZE(aic32x4_mfp1));
+       }
+@@ -960,7 +955,7 @@ static void aic32x4_setup_gpios(struct s
+       /* MFP2 */
+       if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) {
+               snd_soc_component_write(component, AIC32X4_DOUTCTL,
+-                    aic32x4->setup->gpio_func[1]);
++                        aic32x4->setup->gpio_func[1]);
+               snd_soc_add_component_controls(component, aic32x4_mfp2,
+                       ARRAY_SIZE(aic32x4_mfp2));
+       }
+@@ -968,7 +963,7 @@ static void aic32x4_setup_gpios(struct s
+       /* MFP3 */
+       if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) {
+               snd_soc_component_write(component, AIC32X4_SCLKCTL,
+-                    aic32x4->setup->gpio_func[2]);
++                        aic32x4->setup->gpio_func[2]);
+               snd_soc_add_component_controls(component, aic32x4_mfp3,
+                       ARRAY_SIZE(aic32x4_mfp3));
+       }
+@@ -976,7 +971,7 @@ static void aic32x4_setup_gpios(struct s
+       /* MFP4 */
+       if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) {
+               snd_soc_component_write(component, AIC32X4_MISOCTL,
+-                    aic32x4->setup->gpio_func[3]);
++                        aic32x4->setup->gpio_func[3]);
+               snd_soc_add_component_controls(component, aic32x4_mfp4,
+                       ARRAY_SIZE(aic32x4_mfp4));
+       }
+@@ -984,7 +979,7 @@ static void aic32x4_setup_gpios(struct s
+       /* MFP5 */
+       if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) {
+               snd_soc_component_write(component, AIC32X4_GPIOCTL,
+-                    aic32x4->setup->gpio_func[4]);
++                        aic32x4->setup->gpio_func[4]);
+               snd_soc_add_component_controls(component, aic32x4_mfp5,
+                       ARRAY_SIZE(aic32x4_mfp5));
+       }
+@@ -1007,8 +1002,8 @@ static int aic32x4_component_probe(struc
+       /* Power platform configuration */
+       if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
+-              snd_soc_component_write(component, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
+-                                                    AIC32X4_MICBIAS_2075V);
++              snd_soc_component_write(component, AIC32X4_MICBIAS,
++                              AIC32X4_MICBIAS_LDOIN | AIC32X4_MICBIAS_2075V);
+       }
+       if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
+               snd_soc_component_write(component, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
+@@ -1071,12 +1066,18 @@ static int aic32x4_parse_dt(struct aic32
+               struct device_node *np)
+ {
+       struct aic32x4_setup_data *aic32x4_setup;
++      int ret;
+       aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup),
+                                                       GFP_KERNEL);
+       if (!aic32x4_setup)
+               return -ENOMEM;
++      ret = of_property_match_string(np, "clock-names", "mclk");
++      if (ret < 0)
++              return -EINVAL;
++      aic32x4->mclk_name = of_clk_get_parent_name(np, ret);
++
+       aic32x4->swapdacs = false;
+       aic32x4->micpga_routing = 0;
+       aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+@@ -1198,7 +1199,7 @@ int aic32x4_probe(struct device *dev, st
+               return PTR_ERR(regmap);
+       aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv),
+-                             GFP_KERNEL);
++                                 GFP_KERNEL);
+       if (aic32x4 == NULL)
+               return -ENOMEM;
+@@ -1210,6 +1211,7 @@ int aic32x4_probe(struct device *dev, st
+               aic32x4->swapdacs = pdata->swapdacs;
+               aic32x4->micpga_routing = pdata->micpga_routing;
+               aic32x4->rstn_gpio = pdata->rstn_gpio;
++              aic32x4->mclk_name = "mclk";
+       } else if (np) {
+               ret = aic32x4_parse_dt(aic32x4, np);
+               if (ret) {
+@@ -1221,6 +1223,7 @@ int aic32x4_probe(struct device *dev, st
+               aic32x4->swapdacs = false;
+               aic32x4->micpga_routing = 0;
+               aic32x4->rstn_gpio = -1;
++              aic32x4->mclk_name = "mclk";
+       }
+       aic32x4->mclk = devm_clk_get(dev, "mclk");
+@@ -1229,6 +1232,10 @@ int aic32x4_probe(struct device *dev, st
+               return PTR_ERR(aic32x4->mclk);
+       }
++      ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
++      if (ret)
++              return ret;
++
+       if (gpio_is_valid(aic32x4->rstn_gpio)) {
+               ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio,
+                               GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -16,6 +16,7 @@ struct regmap_config;
+ extern const struct regmap_config aic32x4_regmap_config;
+ int aic32x4_probe(struct device *dev, struct regmap *regmap);
+ int aic32x4_remove(struct device *dev);
++int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
+ /* tlv320aic32x4 register space (in decimal to match datasheet) */
+@@ -205,4 +206,8 @@ int aic32x4_remove(struct device *dev);
+ #define AIC32X4_RMICPGANIN_IN1L_10K   0x10
+ #define AIC32X4_RMICPGANIN_CM1R_10K   0x40
++/* Clock Limits */
++#define AIC32X4_MAX_PLL_CLKIN         20000000
++
++
+ #endif                                /* _TLV320AIC32X4_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0345-ASoC-tlv320aic32x4-Model-CODEC_CLKIN-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0345-ASoC-tlv320aic32x4-Model-CODEC_CLKIN-in-CCF.patch
new file mode 100644 (file)
index 0000000..928d05a
--- /dev/null
@@ -0,0 +1,120 @@
+From c5f9d78ec34de15732bcbff52bedba7a840e42b2 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:46 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF
+
+commit fd2df3aeafa4b4cc468d58e147e0822967034b71 upstream.
+
+Model and manage codec clock input as a component in the Core
+Clock Framework.  This should allow us to do some more complex
+clock management and power control.  Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-clk.c | 34 ++++++++++++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c     | 18 +++++++++++----
+ 2 files changed, 47 insertions(+), 5 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-clk.c
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -265,6 +265,30 @@ static const struct clk_ops aic32x4_pll_
+       .get_parent = clk_aic32x4_pll_get_parent,
+ };
++static int clk_aic32x4_codec_clkin_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++
++      return regmap_update_bits(mux->regmap,
++              AIC32X4_CLKMUX,
++              AIC32X4_CODEC_CLKIN_MASK, index << AIC32X4_CODEC_CLKIN_SHIFT);
++}
++
++static u8 clk_aic32x4_codec_clkin_get_parent(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++      unsigned int val;
++
++      regmap_read(mux->regmap, AIC32X4_CLKMUX, &val);
++
++      return (val & AIC32X4_CODEC_CLKIN_MASK) >> AIC32X4_CODEC_CLKIN_SHIFT;
++}
++
++static const struct clk_ops aic32x4_codec_clkin_ops = {
++      .set_parent = clk_aic32x4_codec_clkin_set_parent,
++      .get_parent = clk_aic32x4_codec_clkin_get_parent,
++};
++
+ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
+       {
+               .name = "pll",
+@@ -274,6 +298,14 @@ static struct aic32x4_clkdesc aic32x4_cl
+               .ops = &aic32x4_pll_ops,
+               .reg = 0,
+       },
++      {
++              .name = "codec_clkin",
++              .parent_names =
++                      (const char *[]) { "mclk", "bclk", "gpio", "pll" },
++              .num_parents = 4,
++              .ops = &aic32x4_codec_clkin_ops,
++              .reg = 0,
++      },
+ };
+ static struct clk *aic32x4_register_clk(struct device *dev,
+@@ -314,6 +346,8 @@ int aic32x4_register_clocks(struct devic
+        */
+       aic32x4_clkdesc_array[0].parent_names =
+                       (const char* []) { mclk_name, "bclk", "gpio", "din" };
++      aic32x4_clkdesc_array[1].parent_names =
++                      (const char *[]) { mclk_name, "bclk", "gpio", "pll" };
+       for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
+               aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -737,12 +737,9 @@ static int aic32x4_setup_clocks(struct s
+       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+-      /* PLL as CODEC_CLKIN */
+-      snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
+-                      AIC32X4_CODEC_CLKIN_MASK,
+-                      AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
+       /* DAC_MOD_CLK as BDIV_CLKIN */
+-      snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
++      snd_soc_component_update_bits(component, AIC32X4_IFACE3,
++                              AIC32X4_BDIVCLK_MASK,
+                               AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+       /* NDAC divider value */
+@@ -989,6 +986,15 @@ static int aic32x4_component_probe(struc
+ {
+       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+       u32 tmp_reg;
++      int ret;
++
++      struct clk_bulk_data clocks[] = {
++          { .id = "codec_clkin" },
++      };
++
++      ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
++      if (ret)
++              return ret;
+       if (gpio_is_valid(aic32x4->rstn_gpio)) {
+               ndelay(10);
+@@ -1000,6 +1006,8 @@ static int aic32x4_component_probe(struc
+       if (aic32x4->setup)
+               aic32x4_setup_gpios(component);
++      clk_set_parent(clocks[0].clk, clocks[1].clk);
++
+       /* Power platform configuration */
+       if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
+               snd_soc_component_write(component, AIC32X4_MICBIAS,
diff --git a/target/linux/brcm2708/patches-4.19/950-0345-ASoC-tlv320aic32x4-Properly-Set-Processing-Blocks.patch b/target/linux/brcm2708/patches-4.19/950-0345-ASoC-tlv320aic32x4-Properly-Set-Processing-Blocks.patch
deleted file mode 100644 (file)
index cae096b..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-From 6cc882cf38b62fce2a07640413b05b43b420c77a Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 20 Mar 2019 19:38:44 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Properly Set Processing Blocks
-
-commit c95e3a4b96293403a427b5185e60fad28af51fdd upstream.
-
-Different processing blocks are required for different sampling
-rates and power parameters.  Set the processing blocks based
-on this information.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 56 ++++++++++++++++++++------------
- 1 file changed, 36 insertions(+), 20 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -59,6 +59,8 @@ struct aic32x4_rate_divs {
-       u8 nadc;
-       u8 madc;
-       u8 blck_N;
-+      u8 r_block;
-+      u8 p_block;
- };
- struct aic32x4_priv {
-@@ -307,34 +309,34 @@ static const struct snd_kcontrol_new aic
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
-       /* 8k rate */
--      {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
--      {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
--      {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
-+      {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
-+      {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
-+      {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
-       /* 11.025k rate */
--      {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
--      {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
-+      {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
-+      {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
-       /* 16k rate */
--      {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
--      {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
--      {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
-+      {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
-+      {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
-+      {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
-       /* 22.05k rate */
--      {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
--      {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
--      {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
-+      {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
-+      {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
-+      {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
-       /* 32k rate */
--      {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
--      {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
-+      {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
-+      {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
-       /* 44.1k rate */
--      {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
--      {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
--      {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
-+      {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
-+      {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+      {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-       /* 48k rate */
--      {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
--      {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
--      {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},
-+      {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
-+      {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+      {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-       /* 96k rate */
--      {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1},
-+      {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
- };
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -698,6 +700,18 @@ static int aic32x4_set_dai_fmt(struct sn
-       return 0;
- }
-+static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
-+                                              u8 r_block, u8 p_block)
-+{
-+      if (r_block > 18 || p_block > 25)
-+              return -EINVAL;
-+
-+      snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
-+      snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
-+
-+      return 0;
-+}
-+
- static int aic32x4_setup_clocks(struct snd_soc_component *component,
-                               unsigned int sample_rate,
-                               unsigned int parent_rate)
-@@ -710,6 +724,8 @@ static int aic32x4_setup_clocks(struct s
-               return i;
-       }
-+      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-+
-       /* MCLK as PLL_CLKIN */
-       snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
-                           AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
diff --git a/target/linux/brcm2708/patches-4.19/950-0346-ASoC-tlv320aic32x4-Model-DAC-ADC-dividers-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0346-ASoC-tlv320aic32x4-Model-DAC-ADC-dividers-in-CCF.patch
new file mode 100644 (file)
index 0000000..fc671a4
--- /dev/null
@@ -0,0 +1,306 @@
+From 3bf2e5984ab7acb4469ab0f3dfee8b7392001bbf Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:47 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Model DAC/ADC dividers in CCF
+
+commit a51b50062091619915c5155085bbe13a7aca6903 upstream.
+
+Model and manage DAC/ADC dividers as components in the Core
+Clock Framework.  This should allow us to do some more complex
+clock management and power control.  Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-clk.c |  90 ++++++++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c     | 101 +++++++++++++++------------
+ sound/soc/codecs/tlv320aic32x4.h     |   4 ++
+ 3 files changed, 151 insertions(+), 44 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-clk.c
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -289,6 +289,68 @@ static const struct clk_ops aic32x4_code
+       .get_parent = clk_aic32x4_codec_clkin_get_parent,
+ };
++static int clk_aic32x4_div_prepare(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++
++      return regmap_update_bits(div->regmap, div->reg,
++                              AIC32X4_DIVEN, AIC32X4_DIVEN);
++}
++
++static void clk_aic32x4_div_unprepare(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++
++      regmap_update_bits(div->regmap, div->reg,
++                      AIC32X4_DIVEN, 0);
++}
++
++static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate,
++                              unsigned long parent_rate)
++{
++      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++      u8 divisor;
++
++      divisor = DIV_ROUND_UP(parent_rate, rate);
++      if (divisor > 128)
++              return -EINVAL;
++
++      return regmap_update_bits(div->regmap, div->reg,
++                              AIC32X4_DIV_MASK, divisor);
++}
++
++static long clk_aic32x4_div_round_rate(struct clk_hw *hw, unsigned long rate,
++                              unsigned long *parent_rate)
++{
++      unsigned long divisor;
++
++      divisor = DIV_ROUND_UP(*parent_rate, rate);
++      if (divisor > 128)
++              return -EINVAL;
++
++      return DIV_ROUND_UP(*parent_rate, divisor);
++}
++
++static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw,
++                                              unsigned long parent_rate)
++{
++      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++
++      unsigned int val;
++
++      regmap_read(div->regmap, div->reg, &val);
++
++      return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK);
++}
++
++static const struct clk_ops aic32x4_div_ops = {
++      .prepare = clk_aic32x4_div_prepare,
++      .unprepare = clk_aic32x4_div_unprepare,
++      .set_rate = clk_aic32x4_div_set_rate,
++      .round_rate = clk_aic32x4_div_round_rate,
++      .recalc_rate = clk_aic32x4_div_recalc_rate,
++};
++
+ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
+       {
+               .name = "pll",
+@@ -306,6 +368,34 @@ static struct aic32x4_clkdesc aic32x4_cl
+               .ops = &aic32x4_codec_clkin_ops,
+               .reg = 0,
+       },
++      {
++              .name = "ndac",
++              .parent_names = (const char * []) { "codec_clkin" },
++              .num_parents = 1,
++              .ops = &aic32x4_div_ops,
++              .reg = AIC32X4_NDAC,
++      },
++      {
++              .name = "mdac",
++              .parent_names = (const char * []) { "ndac" },
++              .num_parents = 1,
++              .ops = &aic32x4_div_ops,
++              .reg = AIC32X4_MDAC,
++      },
++      {
++              .name = "nadc",
++              .parent_names = (const char * []) { "codec_clkin" },
++              .num_parents = 1,
++              .ops = &aic32x4_div_ops,
++              .reg = AIC32X4_NADC,
++      },
++      {
++              .name = "madc",
++              .parent_names = (const char * []) { "nadc" },
++              .num_parents = 1,
++              .ops = &aic32x4_div_ops,
++              .reg = AIC32X4_MADC,
++      },
+ };
+ static struct clk *aic32x4_register_clk(struct device *dev,
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -52,11 +52,11 @@ struct aic32x4_rate_divs {
+       u32 rate;
+       unsigned long pll_rate;
+       u16 dosr;
+-      u8 ndac;
+-      u8 mdac;
++      unsigned long ndac_rate;
++      unsigned long mdac_rate;
+       u8 aosr;
+-      u8 nadc;
+-      u8 madc;
++      unsigned long nadc_rate;
++      unsigned long madc_rate;
+       u8 blck_N;
+       u8 r_block;
+       u8 p_block;
+@@ -309,34 +309,54 @@ static const struct snd_kcontrol_new aic
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+       /* 8k rate */
+-      { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
+-      { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
+-      { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
++      { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
++              1024000, 24, 1, 1 },
++      { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
++              512000, 24, 1, 1 },
++      { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
++              512000, 24, 1, 1 },
+       /* 11.025k rate */
+-      { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
+-      { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
++      { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
++              1411200, 16, 1, 1 },
++      { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
++              705600, 16, 1, 1 },
+       /* 16k rate */
+-      { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
+-      { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
+-      { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
++      { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
++              2048000, 12, 1, 1 },
++      { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
++              1024000, 12, 1, 1 },
++      { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
++              1024000, 12, 1, 1 },
+       /* 22.05k rate */
+-      { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
+-      { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
+-      { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
++      { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
++              2822400, 8, 1, 1 },
++      { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
++              1411200, 8, 1, 1 },
++      { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
++              1411200, 8, 1, 1 },
+       /* 32k rate */
+-      { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
+-      { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
++      { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
++              2048000, 6, 1, 1 },
++      { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
++              2048000, 6, 1, 1 },
+       /* 44.1k rate */
+-      { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
+-      { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+-      { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++      { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
++              5644800, 4, 1, 1 },
++      { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
++              2822400, 4, 1, 1 },
++      { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
++              2822400, 4, 1, 1 },
+       /* 48k rate */
+-      { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
+-      { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+-      { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++      { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
++              6144000, 4, 1, 1 },
++      { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
++              3072000, 4, 1, 1 },
++      { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
++              3072000, 4, 1, 1 },
+       /* 96k rate */
+-      { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
++      { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
++              6144000, 1, 1, 9 },
+ };
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -721,6 +741,10 @@ static int aic32x4_setup_clocks(struct s
+       struct clk_bulk_data clocks[] = {
+               { .id = "pll" },
++              { .id = "nadc" },
++              { .id = "madc" },
++              { .id = "ndac" },
++              { .id = "mdac" },
+       };
+       i = aic32x4_get_divs(parent_rate, sample_rate);
+@@ -733,7 +757,11 @@ static int aic32x4_setup_clocks(struct s
+       if (ret)
+               return ret;
+-      clk_set_rate(clocks[0].clk, sample_rate);
++      clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
++      clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
++      clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
++      clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
++      clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
+       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+@@ -742,26 +770,10 @@ static int aic32x4_setup_clocks(struct s
+                               AIC32X4_BDIVCLK_MASK,
+                               AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+-      /* NDAC divider value */
+-      snd_soc_component_update_bits(component, AIC32X4_NDAC,
+-                              AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
+-
+-      /* MDAC divider value */
+-      snd_soc_component_update_bits(component, AIC32X4_MDAC,
+-                              AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
+-
+       /* DOSR MSB & LSB values */
+       snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+       snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
+-      /* NADC divider value */
+-      snd_soc_component_update_bits(component, AIC32X4_NADC,
+-                              AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
+-
+-      /* MADC divider value */
+-      snd_soc_component_update_bits(component, AIC32X4_MADC,
+-                              AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
+-
+       /* AOSR value */
+       snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
+@@ -773,8 +785,8 @@ static int aic32x4_setup_clocks(struct s
+ }
+ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
+-                           struct snd_pcm_hw_params *params,
+-                           struct snd_soc_dai *dai)
++                               struct snd_pcm_hw_params *params,
++                               struct snd_soc_dai *dai)
+ {
+       struct snd_soc_component *component = dai->component;
+       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+@@ -989,7 +1001,8 @@ static int aic32x4_component_probe(struc
+       int ret;
+       struct clk_bulk_data clocks[] = {
+-          { .id = "codec_clkin" },
++              { .id = "codec_clkin" },
++              { .id = "pll" },
+       };
+       ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -206,6 +206,10 @@ int aic32x4_register_clocks(struct devic
+ #define AIC32X4_RMICPGANIN_IN1L_10K   0x10
+ #define AIC32X4_RMICPGANIN_CM1R_10K   0x40
++/* Common mask and enable for all of the dividers */
++#define AIC32X4_DIVEN           BIT(7)
++#define AIC32X4_DIV_MASK        GENMASK(6, 0)
++
+ /* Clock Limits */
+ #define AIC32X4_MAX_PLL_CLKIN         20000000
diff --git a/target/linux/brcm2708/patches-4.19/950-0346-ASoC-tlv320aic32x4-Model-PLL-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0346-ASoC-tlv320aic32x4-Model-PLL-in-CCF.patch
deleted file mode 100644 (file)
index 4e0ddb9..0000000
+++ /dev/null
@@ -1,877 +0,0 @@
-From 957ccf05060d65da074d019679ec7f486477e412 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:45 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Model PLL in CCF
-
-commit 514b044cba667e4b7c383ec79b42b997e624b91d upstream.
-
-Model and manage the on-board PLL as a component in the Core
-Clock Framework.  This should allow us to do some more complex
-clock management and power control.  Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/Kconfig             |   1 +
- sound/soc/codecs/Makefile            |   2 +-
- sound/soc/codecs/tlv320aic32x4-clk.c | 323 +++++++++++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c     | 195 ++++++++--------
- sound/soc/codecs/tlv320aic32x4.h     |   5 +
- 5 files changed, 431 insertions(+), 95 deletions(-)
- create mode 100644 sound/soc/codecs/tlv320aic32x4-clk.c
-
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -1025,6 +1025,7 @@ config SND_SOC_TLV320AIC31XX
- config SND_SOC_TLV320AIC32X4
-       tristate
-+      depends on COMMON_CLK
- config SND_SOC_TLV320AIC32X4_I2C
-       tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
---- a/sound/soc/codecs/Makefile
-+++ b/sound/soc/codecs/Makefile
-@@ -182,7 +182,7 @@ snd-soc-tlv320aic23-i2c-objs := tlv320ai
- snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
- snd-soc-tlv320aic26-objs := tlv320aic26.o
- snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
--snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
-+snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o tlv320aic32x4-clk.o
- snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o
- snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o
- snd-soc-tlv320aic3x-objs := tlv320aic3x.o
---- /dev/null
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -0,0 +1,323 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Clock Tree for the Texas Instruments TLV320AIC32x4
-+ *
-+ * Copyright 2019 Annaliese McDermond
-+ *
-+ * Author: Annaliese McDermond <nh6z@nh6z.net>
-+ */
-+
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+#include <linux/regmap.h>
-+#include <linux/device.h>
-+
-+#include "tlv320aic32x4.h"
-+
-+#define to_clk_aic32x4(_hw) container_of(_hw, struct clk_aic32x4, hw)
-+struct clk_aic32x4 {
-+      struct clk_hw hw;
-+      struct device *dev;
-+      struct regmap *regmap;
-+      unsigned int reg;
-+};
-+
-+/*
-+ * struct clk_aic32x4_pll_muldiv - Multiplier/divider settings
-+ * @p:                Divider
-+ * @r:                first multiplier
-+ * @j:                integer part of second multiplier
-+ * @d:                decimal part of second multiplier
-+ */
-+struct clk_aic32x4_pll_muldiv {
-+      u8 p;
-+      u16 r;
-+      u8 j;
-+      u16 d;
-+};
-+
-+struct aic32x4_clkdesc {
-+      const char *name;
-+      const char * const *parent_names;
-+      unsigned int num_parents;
-+      const struct clk_ops *ops;
-+      unsigned int reg;
-+};
-+
-+static int clk_aic32x4_pll_prepare(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+      return regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+                              AIC32X4_PLLEN, AIC32X4_PLLEN);
-+}
-+
-+static void clk_aic32x4_pll_unprepare(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+      regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+                              AIC32X4_PLLEN, 0);
-+}
-+
-+static int clk_aic32x4_pll_is_prepared(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+      unsigned int val;
-+      int ret;
-+
-+      ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      return !!(val & AIC32X4_PLLEN);
-+}
-+
-+static int clk_aic32x4_pll_get_muldiv(struct clk_aic32x4 *pll,
-+                      struct clk_aic32x4_pll_muldiv *settings)
-+{
-+      /*      Change to use regmap_bulk_read? */
-+      unsigned int val;
-+      int ret;
-+
-+      ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
-+      if (ret)
-+              return ret;
-+      settings->r = val & AIC32X4_PLL_R_MASK;
-+      settings->p = (val & AIC32X4_PLL_P_MASK) >> AIC32X4_PLL_P_SHIFT;
-+
-+      ret = regmap_read(pll->regmap, AIC32X4_PLLJ, &val);
-+      if (ret < 0)
-+              return ret;
-+      settings->j = val;
-+
-+      ret = regmap_read(pll->regmap, AIC32X4_PLLDMSB, &val);
-+      if (ret < 0)
-+              return ret;
-+      settings->d = val << 8;
-+
-+      ret = regmap_read(pll->regmap, AIC32X4_PLLDLSB,  &val);
-+      if (ret < 0)
-+              return ret;
-+      settings->d |= val;
-+
-+      return 0;
-+}
-+
-+static int clk_aic32x4_pll_set_muldiv(struct clk_aic32x4 *pll,
-+                      struct clk_aic32x4_pll_muldiv *settings)
-+{
-+      int ret;
-+      /*      Change to use regmap_bulk_write for some if not all? */
-+
-+      ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+                              AIC32X4_PLL_R_MASK, settings->r);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+                              AIC32X4_PLL_P_MASK,
-+                              settings->p << AIC32X4_PLL_P_SHIFT);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = regmap_write(pll->regmap, AIC32X4_PLLJ, settings->j);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = regmap_write(pll->regmap, AIC32X4_PLLDMSB, (settings->d >> 8));
-+      if (ret < 0)
-+              return ret;
-+      ret = regmap_write(pll->regmap, AIC32X4_PLLDLSB, (settings->d & 0xff));
-+      if (ret < 0)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static unsigned long clk_aic32x4_pll_calc_rate(
-+                      struct clk_aic32x4_pll_muldiv *settings,
-+                      unsigned long parent_rate)
-+{
-+      u64 rate;
-+      /*
-+       * We scale j by 10000 to account for the decimal part of P and divide
-+       * it back out later.
-+       */
-+      rate = (u64) parent_rate * settings->r *
-+                              ((settings->j * 10000) + settings->d);
-+
-+      return (unsigned long) DIV_ROUND_UP_ULL(rate, settings->p * 10000);
-+}
-+
-+static int clk_aic32x4_pll_calc_muldiv(struct clk_aic32x4_pll_muldiv *settings,
-+                      unsigned long rate, unsigned long parent_rate)
-+{
-+      u64 multiplier;
-+
-+      settings->p = parent_rate / AIC32X4_MAX_PLL_CLKIN + 1;
-+      if (settings->p > 8)
-+              return -1;
-+
-+      /*
-+       * We scale this figure by 10000 so that we can get the decimal part
-+       * of the multiplier.   This is because we can't do floating point
-+       * math in the kernel.
-+       */
-+       multiplier = (u64) rate * settings->p * 10000;
-+       do_div(multiplier, parent_rate);
-+
-+      /*
-+       * J can't be over 64, so R can scale this.
-+       * R can't be greater than 4.
-+       */
-+      settings->r = ((u32) multiplier / 640000) + 1;
-+      if (settings->r > 4)
-+              return -1;
-+      do_div(multiplier, settings->r);
-+
-+      /*
-+       * J can't be < 1.
-+       */
-+      if (multiplier < 10000)
-+              return -1;
-+
-+      /* Figure out the integer part, J, and the fractional part, D. */
-+      settings->j = (u32) multiplier / 10000;
-+      settings->d = (u32) multiplier % 10000;
-+
-+      return 0;
-+}
-+
-+static unsigned long clk_aic32x4_pll_recalc_rate(struct clk_hw *hw,
-+                      unsigned long parent_rate)
-+{
-+      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+      struct clk_aic32x4_pll_muldiv settings;
-+      int ret;
-+
-+      ret =  clk_aic32x4_pll_get_muldiv(pll, &settings);
-+      if (ret < 0)
-+              return 0;
-+
-+      return clk_aic32x4_pll_calc_rate(&settings, parent_rate);
-+}
-+
-+static long clk_aic32x4_pll_round_rate(struct clk_hw *hw,
-+                      unsigned long rate,
-+                      unsigned long *parent_rate)
-+{
-+      struct clk_aic32x4_pll_muldiv settings;
-+      int ret;
-+
-+      ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, *parent_rate);
-+      if (ret < 0)
-+              return 0;
-+
-+      return clk_aic32x4_pll_calc_rate(&settings, *parent_rate);
-+}
-+
-+static int clk_aic32x4_pll_set_rate(struct clk_hw *hw,
-+                      unsigned long rate,
-+                      unsigned long parent_rate)
-+{
-+      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+      struct clk_aic32x4_pll_muldiv settings;
-+      int ret;
-+
-+      ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, parent_rate);
-+      if (ret < 0)
-+              return -EINVAL;
-+
-+      return clk_aic32x4_pll_set_muldiv(pll, &settings);
-+}
-+
-+static int clk_aic32x4_pll_set_parent(struct clk_hw *hw, u8 index)
-+{
-+      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+      return regmap_update_bits(pll->regmap,
-+                              AIC32X4_CLKMUX,
-+                              AIC32X4_PLL_CLKIN_MASK,
-+                              index << AIC32X4_PLL_CLKIN_SHIFT);
-+}
-+
-+static u8 clk_aic32x4_pll_get_parent(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+      unsigned int val;
-+
-+      regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
-+
-+      return (val & AIC32X4_PLL_CLKIN_MASK) >> AIC32X4_PLL_CLKIN_SHIFT;
-+}
-+
-+
-+static const struct clk_ops aic32x4_pll_ops = {
-+      .prepare = clk_aic32x4_pll_prepare,
-+      .unprepare = clk_aic32x4_pll_unprepare,
-+      .is_prepared = clk_aic32x4_pll_is_prepared,
-+      .recalc_rate = clk_aic32x4_pll_recalc_rate,
-+      .round_rate = clk_aic32x4_pll_round_rate,
-+      .set_rate = clk_aic32x4_pll_set_rate,
-+      .set_parent = clk_aic32x4_pll_set_parent,
-+      .get_parent = clk_aic32x4_pll_get_parent,
-+};
-+
-+static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
-+      {
-+              .name = "pll",
-+              .parent_names =
-+                      (const char* []) { "mclk", "bclk", "gpio", "din" },
-+              .num_parents = 4,
-+              .ops = &aic32x4_pll_ops,
-+              .reg = 0,
-+      },
-+};
-+
-+static struct clk *aic32x4_register_clk(struct device *dev,
-+                      struct aic32x4_clkdesc *desc)
-+{
-+      struct clk_init_data init;
-+      struct clk_aic32x4 *priv;
-+      const char *devname = dev_name(dev);
-+
-+      init.ops = desc->ops;
-+      init.name = desc->name;
-+      init.parent_names = desc->parent_names;
-+      init.num_parents = desc->num_parents;
-+      init.flags = 0;
-+
-+      priv = devm_kzalloc(dev, sizeof(struct clk_aic32x4), GFP_KERNEL);
-+      if (priv == NULL)
-+              return (struct clk *) -ENOMEM;
-+
-+      priv->dev = dev;
-+      priv->hw.init = &init;
-+      priv->regmap = dev_get_regmap(dev, NULL);
-+      priv->reg = desc->reg;
-+
-+      clk_hw_register_clkdev(&priv->hw, desc->name, devname);
-+      return devm_clk_register(dev, &priv->hw);
-+}
-+
-+int aic32x4_register_clocks(struct device *dev, const char *mclk_name)
-+{
-+      int i;
-+
-+      /*
-+       * These lines are here to preserve the current functionality of
-+       * the driver with regard to the DT.  These should eventually be set
-+       * by DT nodes so that the connections can be set up in configuration
-+       * rather than code.
-+       */
-+      aic32x4_clkdesc_array[0].parent_names =
-+                      (const char* []) { mclk_name, "bclk", "gpio", "din" };
-+
-+      for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
-+              aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(aic32x4_register_clocks);
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -14,7 +14,7 @@
-  *
-  * 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
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-@@ -33,6 +33,7 @@
- #include <linux/cdev.h>
- #include <linux/slab.h>
- #include <linux/clk.h>
-+#include <linux/of_clk.h>
- #include <linux/regulator/consumer.h>
- #include <sound/tlv320aic32x4.h>
-@@ -49,9 +50,7 @@
- struct aic32x4_rate_divs {
-       u32 mclk;
-       u32 rate;
--      u8 p_val;
--      u8 pll_j;
--      u16 pll_d;
-+      unsigned long pll_rate;
-       u16 dosr;
-       u8 ndac;
-       u8 mdac;
-@@ -71,6 +70,7 @@ struct aic32x4_priv {
-       bool swapdacs;
-       int rstn_gpio;
-       struct clk *mclk;
-+      const char *mclk_name;
-       struct regulator *supply_ldo;
-       struct regulator *supply_iov;
-@@ -309,34 +309,34 @@ static const struct snd_kcontrol_new aic
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
-       /* 8k rate */
--      {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
--      {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
--      {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
-+      { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
-+      { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
-+      { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
-       /* 11.025k rate */
--      {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
--      {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
-+      { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
-+      { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
-       /* 16k rate */
--      {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
--      {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
--      {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
-+      { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
-+      { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
-+      { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
-       /* 22.05k rate */
--      {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
--      {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
--      {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
-+      { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
-+      { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
-+      { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
-       /* 32k rate */
--      {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
--      {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
-+      { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
-+      { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
-       /* 44.1k rate */
--      {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
--      {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
--      {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+      { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
-+      { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+      { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-       /* 48k rate */
--      {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
--      {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
--      {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+      { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
-+      { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+      { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-       /* 96k rate */
--      {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
-+      { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
- };
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -393,7 +393,7 @@ static const struct snd_kcontrol_new in3
-       SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum),
- };
--/*  Right mixer pins */
-+/*    Right mixer pins */
- static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
- static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
- static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
-@@ -597,7 +597,7 @@ static const struct snd_soc_dapm_route a
- static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
-       {
-               .selector_reg = 0,
--              .selector_mask  = 0xff,
-+              .selector_mask  = 0xff,
-               .window_start = 0,
-               .window_len = 128,
-               .range_min = 0,
-@@ -618,7 +618,7 @@ static inline int aic32x4_get_divs(int m
-       for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
-               if ((aic32x4_divs[i].rate == rate)
--                  && (aic32x4_divs[i].mclk == mclk)) {
-+                      && (aic32x4_divs[i].mclk == mclk)) {
-                       return i;
-               }
-       }
-@@ -690,12 +690,12 @@ static int aic32x4_set_dai_fmt(struct sn
-       }
-       snd_soc_component_update_bits(component, AIC32X4_IFACE1,
--                          AIC32X4_IFACE1_DATATYPE_MASK |
--                          AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
-+                              AIC32X4_IFACE1_DATATYPE_MASK |
-+                              AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
-       snd_soc_component_update_bits(component, AIC32X4_IFACE2,
--                          AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
-+                              AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
-       snd_soc_component_update_bits(component, AIC32X4_IFACE3,
--                          AIC32X4_BCLKINV_MASK, iface_reg_3);
-+                              AIC32X4_BCLKINV_MASK, iface_reg_3);
-       return 0;
- }
-@@ -717,6 +717,11 @@ static int aic32x4_setup_clocks(struct s
-                               unsigned int parent_rate)
- {
-       int i;
-+      int ret;
-+
-+      struct clk_bulk_data clocks[] = {
-+              { .id = "pll" },
-+      };
-       i = aic32x4_get_divs(parent_rate, sample_rate);
-       if (i < 0) {
-@@ -724,39 +729,29 @@ static int aic32x4_setup_clocks(struct s
-               return i;
-       }
-+      ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-+      if (ret)
-+              return ret;
-+
-+      clk_set_rate(clocks[0].clk, sample_rate);
-+
-       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
--      /* MCLK as PLL_CLKIN */
--      snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
--                          AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
-       /* PLL as CODEC_CLKIN */
--      snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_CODEC_CLKIN_MASK,
--                          AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
-+      snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
-+                      AIC32X4_CODEC_CLKIN_MASK,
-+                      AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
-       /* DAC_MOD_CLK as BDIV_CLKIN */
-       snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
--                          AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
--
--      /* We will fix R value to 1 and will make P & J=K.D as variable */
--      snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_R_MASK, 0x01);
--
--      /* PLL P value */
--      snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_P_MASK,
--                          aic32x4_divs[i].p_val << AIC32X4_PLL_P_SHIFT);
--
--      /* PLL J value */
--      snd_soc_component_write(component, AIC32X4_PLLJ, aic32x4_divs[i].pll_j);
--
--      /* PLL D value */
--      snd_soc_component_write(component, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8));
--      snd_soc_component_write(component, AIC32X4_PLLDLSB, (aic32x4_divs[i].pll_d & 0xff));
-+                              AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
-       /* NDAC divider value */
-       snd_soc_component_update_bits(component, AIC32X4_NDAC,
--                          AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
-+                              AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
-       /* MDAC divider value */
-       snd_soc_component_update_bits(component, AIC32X4_MDAC,
--                          AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
-+                              AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
-       /* DOSR MSB & LSB values */
-       snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
-@@ -764,18 +759,18 @@ static int aic32x4_setup_clocks(struct s
-       /* NADC divider value */
-       snd_soc_component_update_bits(component, AIC32X4_NADC,
--                          AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
-+                              AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
-       /* MADC divider value */
-       snd_soc_component_update_bits(component, AIC32X4_MADC,
--                          AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
-+                              AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
-       /* AOSR value */
-       snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-       /* BCLK N divider */
-       snd_soc_component_update_bits(component, AIC32X4_BCLKN,
--                          AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
-+                              AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
-       return 0;
- }
-@@ -794,23 +789,23 @@ static int aic32x4_hw_params(struct snd_
-       switch (params_width(params)) {
-       case 16:
-               iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
--                             AIC32X4_IFACE1_DATALEN_SHIFT);
-+                                 AIC32X4_IFACE1_DATALEN_SHIFT);
-               break;
-       case 20:
-               iface1_reg |= (AIC32X4_WORD_LEN_20BITS <<
--                             AIC32X4_IFACE1_DATALEN_SHIFT);
-+                                 AIC32X4_IFACE1_DATALEN_SHIFT);
-               break;
-       case 24:
-               iface1_reg |= (AIC32X4_WORD_LEN_24BITS <<
--                             AIC32X4_IFACE1_DATALEN_SHIFT);
-+                                 AIC32X4_IFACE1_DATALEN_SHIFT);
-               break;
-       case 32:
-               iface1_reg |= (AIC32X4_WORD_LEN_32BITS <<
--                             AIC32X4_IFACE1_DATALEN_SHIFT);
-+                                 AIC32X4_IFACE1_DATALEN_SHIFT);
-               break;
-       }
-       snd_soc_component_update_bits(component, AIC32X4_IFACE1,
--                          AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
-+                              AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
-       if (params_channels(params) == 1) {
-               dacsetup_reg = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN;
-@@ -821,7 +816,7 @@ static int aic32x4_hw_params(struct snd_
-                       dacsetup_reg = AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN;
-       }
-       snd_soc_component_update_bits(component, AIC32X4_DACSETUP,
--                          AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
-+                              AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
-       return 0;
- }
-@@ -831,7 +826,7 @@ static int aic32x4_mute(struct snd_soc_d
-       struct snd_soc_component *component = dai->component;
-       snd_soc_component_update_bits(component, AIC32X4_DACMUTE,
--                          AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
-+                              AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
-       return 0;
- }
-@@ -853,27 +848,27 @@ static int aic32x4_set_bias_level(struct
-               /* Switch on PLL */
-               snd_soc_component_update_bits(component, AIC32X4_PLLPR,
--                                  AIC32X4_PLLEN, AIC32X4_PLLEN);
-+                                      AIC32X4_PLLEN, AIC32X4_PLLEN);
-               /* Switch on NDAC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_NDAC,
--                                  AIC32X4_NDACEN, AIC32X4_NDACEN);
-+                                      AIC32X4_NDACEN, AIC32X4_NDACEN);
-               /* Switch on MDAC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_MDAC,
--                                  AIC32X4_MDACEN, AIC32X4_MDACEN);
-+                                      AIC32X4_MDACEN, AIC32X4_MDACEN);
-               /* Switch on NADC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_NADC,
--                                  AIC32X4_NADCEN, AIC32X4_NADCEN);
-+                                      AIC32X4_NADCEN, AIC32X4_NADCEN);
-               /* Switch on MADC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_MADC,
--                                  AIC32X4_MADCEN, AIC32X4_MADCEN);
-+                                      AIC32X4_MADCEN, AIC32X4_MADCEN);
-               /* Switch on BCLK_N Divider */
-               snd_soc_component_update_bits(component, AIC32X4_BCLKN,
--                                  AIC32X4_BCLKEN, AIC32X4_BCLKEN);
-+                                      AIC32X4_BCLKEN, AIC32X4_BCLKEN);
-               break;
-       case SND_SOC_BIAS_PREPARE:
-               break;
-@@ -884,27 +879,27 @@ static int aic32x4_set_bias_level(struct
-               /* Switch off BCLK_N Divider */
-               snd_soc_component_update_bits(component, AIC32X4_BCLKN,
--                                  AIC32X4_BCLKEN, 0);
-+                                      AIC32X4_BCLKEN, 0);
-               /* Switch off MADC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_MADC,
--                                  AIC32X4_MADCEN, 0);
-+                                      AIC32X4_MADCEN, 0);
-               /* Switch off NADC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_NADC,
--                                  AIC32X4_NADCEN, 0);
-+                                      AIC32X4_NADCEN, 0);
-               /* Switch off MDAC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_MDAC,
--                                  AIC32X4_MDACEN, 0);
-+                                      AIC32X4_MDACEN, 0);
-               /* Switch off NDAC Divider */
-               snd_soc_component_update_bits(component, AIC32X4_NDAC,
--                                  AIC32X4_NDACEN, 0);
-+                                      AIC32X4_NDACEN, 0);
-               /* Switch off PLL */
-               snd_soc_component_update_bits(component, AIC32X4_PLLPR,
--                                  AIC32X4_PLLEN, 0);
-+                                      AIC32X4_PLLEN, 0);
-               /* Switch off master clock */
-               clk_disable_unprepare(aic32x4->mclk);
-@@ -916,7 +911,7 @@ static int aic32x4_set_bias_level(struct
- }
- #define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
--#define AIC32X4_FORMATS       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
-+#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
-                        | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
- static const struct snd_soc_dai_ops aic32x4_ops = {
-@@ -929,17 +924,17 @@ static const struct snd_soc_dai_ops aic3
- static struct snd_soc_dai_driver aic32x4_dai = {
-       .name = "tlv320aic32x4-hifi",
-       .playback = {
--                   .stream_name = "Playback",
--                   .channels_min = 1,
--                   .channels_max = 2,
--                   .rates = AIC32X4_RATES,
--                   .formats = AIC32X4_FORMATS,},
-+                       .stream_name = "Playback",
-+                       .channels_min = 1,
-+                       .channels_max = 2,
-+                       .rates = AIC32X4_RATES,
-+                       .formats = AIC32X4_FORMATS,},
-       .capture = {
--                  .stream_name = "Capture",
--                  .channels_min = 1,
--                  .channels_max = 2,
--                  .rates = AIC32X4_RATES,
--                  .formats = AIC32X4_FORMATS,},
-+                      .stream_name = "Capture",
-+                      .channels_min = 1,
-+                      .channels_max = 2,
-+                      .rates = AIC32X4_RATES,
-+                      .formats = AIC32X4_FORMATS,},
-       .ops = &aic32x4_ops,
-       .symmetric_rates = 1,
- };
-@@ -952,7 +947,7 @@ static void aic32x4_setup_gpios(struct s
-       /* MFP1 */
-       if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) {
-               snd_soc_component_write(component, AIC32X4_DINCTL,
--                    aic32x4->setup->gpio_func[0]);
-+                        aic32x4->setup->gpio_func[0]);
-               snd_soc_add_component_controls(component, aic32x4_mfp1,
-                       ARRAY_SIZE(aic32x4_mfp1));
-       }
-@@ -960,7 +955,7 @@ static void aic32x4_setup_gpios(struct s
-       /* MFP2 */
-       if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) {
-               snd_soc_component_write(component, AIC32X4_DOUTCTL,
--                    aic32x4->setup->gpio_func[1]);
-+                        aic32x4->setup->gpio_func[1]);
-               snd_soc_add_component_controls(component, aic32x4_mfp2,
-                       ARRAY_SIZE(aic32x4_mfp2));
-       }
-@@ -968,7 +963,7 @@ static void aic32x4_setup_gpios(struct s
-       /* MFP3 */
-       if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) {
-               snd_soc_component_write(component, AIC32X4_SCLKCTL,
--                    aic32x4->setup->gpio_func[2]);
-+                        aic32x4->setup->gpio_func[2]);
-               snd_soc_add_component_controls(component, aic32x4_mfp3,
-                       ARRAY_SIZE(aic32x4_mfp3));
-       }
-@@ -976,7 +971,7 @@ static void aic32x4_setup_gpios(struct s
-       /* MFP4 */
-       if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) {
-               snd_soc_component_write(component, AIC32X4_MISOCTL,
--                    aic32x4->setup->gpio_func[3]);
-+                        aic32x4->setup->gpio_func[3]);
-               snd_soc_add_component_controls(component, aic32x4_mfp4,
-                       ARRAY_SIZE(aic32x4_mfp4));
-       }
-@@ -984,7 +979,7 @@ static void aic32x4_setup_gpios(struct s
-       /* MFP5 */
-       if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) {
-               snd_soc_component_write(component, AIC32X4_GPIOCTL,
--                    aic32x4->setup->gpio_func[4]);
-+                        aic32x4->setup->gpio_func[4]);
-               snd_soc_add_component_controls(component, aic32x4_mfp5,
-                       ARRAY_SIZE(aic32x4_mfp5));
-       }
-@@ -1007,8 +1002,8 @@ static int aic32x4_component_probe(struc
-       /* Power platform configuration */
-       if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
--              snd_soc_component_write(component, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
--                                                    AIC32X4_MICBIAS_2075V);
-+              snd_soc_component_write(component, AIC32X4_MICBIAS,
-+                              AIC32X4_MICBIAS_LDOIN | AIC32X4_MICBIAS_2075V);
-       }
-       if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
-               snd_soc_component_write(component, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
-@@ -1071,12 +1066,18 @@ static int aic32x4_parse_dt(struct aic32
-               struct device_node *np)
- {
-       struct aic32x4_setup_data *aic32x4_setup;
-+      int ret;
-       aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup),
-                                                       GFP_KERNEL);
-       if (!aic32x4_setup)
-               return -ENOMEM;
-+      ret = of_property_match_string(np, "clock-names", "mclk");
-+      if (ret < 0)
-+              return -EINVAL;
-+      aic32x4->mclk_name = of_clk_get_parent_name(np, ret);
-+
-       aic32x4->swapdacs = false;
-       aic32x4->micpga_routing = 0;
-       aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
-@@ -1198,7 +1199,7 @@ int aic32x4_probe(struct device *dev, st
-               return PTR_ERR(regmap);
-       aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv),
--                             GFP_KERNEL);
-+                                 GFP_KERNEL);
-       if (aic32x4 == NULL)
-               return -ENOMEM;
-@@ -1210,6 +1211,7 @@ int aic32x4_probe(struct device *dev, st
-               aic32x4->swapdacs = pdata->swapdacs;
-               aic32x4->micpga_routing = pdata->micpga_routing;
-               aic32x4->rstn_gpio = pdata->rstn_gpio;
-+              aic32x4->mclk_name = "mclk";
-       } else if (np) {
-               ret = aic32x4_parse_dt(aic32x4, np);
-               if (ret) {
-@@ -1221,6 +1223,7 @@ int aic32x4_probe(struct device *dev, st
-               aic32x4->swapdacs = false;
-               aic32x4->micpga_routing = 0;
-               aic32x4->rstn_gpio = -1;
-+              aic32x4->mclk_name = "mclk";
-       }
-       aic32x4->mclk = devm_clk_get(dev, "mclk");
-@@ -1229,6 +1232,10 @@ int aic32x4_probe(struct device *dev, st
-               return PTR_ERR(aic32x4->mclk);
-       }
-+      ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
-+      if (ret)
-+              return ret;
-+
-       if (gpio_is_valid(aic32x4->rstn_gpio)) {
-               ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio,
-                               GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -16,6 +16,7 @@ struct regmap_config;
- extern const struct regmap_config aic32x4_regmap_config;
- int aic32x4_probe(struct device *dev, struct regmap *regmap);
- int aic32x4_remove(struct device *dev);
-+int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
- /* tlv320aic32x4 register space (in decimal to match datasheet) */
-@@ -205,4 +206,8 @@ int aic32x4_remove(struct device *dev);
- #define AIC32X4_RMICPGANIN_IN1L_10K   0x10
- #define AIC32X4_RMICPGANIN_CM1R_10K   0x40
-+/* Clock Limits */
-+#define AIC32X4_MAX_PLL_CLKIN         20000000
-+
-+
- #endif                                /* _TLV320AIC32X4_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0347-ASoC-tlv320aic32x4-Model-BDIV-divider-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0347-ASoC-tlv320aic32x4-Model-BDIV-divider-in-CCF.patch
new file mode 100644 (file)
index 0000000..708e449
--- /dev/null
@@ -0,0 +1,210 @@
+From 69f3f8c51077d0f3dc7f46c2c9a94da899d8eb7c Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:48 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Model BDIV divider in CCF
+
+commit 9b484124ebd906c4d6bc826cc0d417e80cc1105c upstream.
+
+Model and manage BDIV divider as components in the Core
+Clock Framework.  This should allow us to do some more complex
+clock management and power control.  Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-clk.c | 36 ++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c     | 56 +++++++++++++---------------
+ 2 files changed, 62 insertions(+), 30 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-clk.c
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -351,6 +351,34 @@ static const struct clk_ops aic32x4_div_
+       .recalc_rate = clk_aic32x4_div_recalc_rate,
+ };
++static int clk_aic32x4_bdiv_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++
++      return regmap_update_bits(mux->regmap, AIC32X4_IFACE3,
++                              AIC32X4_BDIVCLK_MASK, index);
++}
++
++static u8 clk_aic32x4_bdiv_get_parent(struct clk_hw *hw)
++{
++      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++      unsigned int val;
++
++      regmap_read(mux->regmap, AIC32X4_IFACE3, &val);
++
++      return val & AIC32X4_BDIVCLK_MASK;
++}
++
++static const struct clk_ops aic32x4_bdiv_ops = {
++      .prepare = clk_aic32x4_div_prepare,
++      .unprepare = clk_aic32x4_div_unprepare,
++      .set_parent = clk_aic32x4_bdiv_set_parent,
++      .get_parent = clk_aic32x4_bdiv_get_parent,
++      .set_rate = clk_aic32x4_div_set_rate,
++      .round_rate = clk_aic32x4_div_round_rate,
++      .recalc_rate = clk_aic32x4_div_recalc_rate,
++};
++
+ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
+       {
+               .name = "pll",
+@@ -396,6 +424,14 @@ static struct aic32x4_clkdesc aic32x4_cl
+               .ops = &aic32x4_div_ops,
+               .reg = AIC32X4_MADC,
+       },
++      {
++              .name = "bdiv",
++              .parent_names =
++                      (const char *[]) { "ndac", "mdac", "nadc", "madc" },
++              .num_parents = 4,
++              .ops = &aic32x4_bdiv_ops,
++              .reg = AIC32X4_BCLKN,
++      },
+ };
+ static struct clk *aic32x4_register_clk(struct device *dev,
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -57,7 +57,7 @@ struct aic32x4_rate_divs {
+       u8 aosr;
+       unsigned long nadc_rate;
+       unsigned long madc_rate;
+-      u8 blck_N;
++      unsigned long bdiv_rate;
+       u8 r_block;
+       u8 p_block;
+ };
+@@ -310,53 +310,53 @@ static const struct snd_kcontrol_new aic
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+       /* 8k rate */
+       { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
+-              1024000, 24, 1, 1 },
++              1024000, 256000, 1, 1 },
+       { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
+-              512000, 24, 1, 1 },
++              512000, 256000, 1, 1 },
+       { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
+-              512000, 24, 1, 1 },
++              512000, 256000, 1, 1 },
+       /* 11.025k rate */
+       { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
+-              1411200, 16, 1, 1 },
++              1411200, 352800, 1, 1 },
+       { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
+-              705600, 16, 1, 1 },
++              705600, 352800, 1, 1 },
+       /* 16k rate */
+       { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
+-              2048000, 12, 1, 1 },
++              2048000, 512000, 1, 1 },
+       { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
+-              1024000, 12, 1, 1 },
++              1024000, 512000, 1, 1 },
+       { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
+-              1024000, 12, 1, 1 },
++              1024000, 512000, 1, 1 },
+       /* 22.05k rate */
+       { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
+-              2822400, 8, 1, 1 },
++              2822400, 705600, 1, 1 },
+       { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
+-              1411200, 8, 1, 1 },
++              1411200, 705600, 1, 1 },
+       { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
+-              1411200, 8, 1, 1 },
++              1411200, 705600, 1, 1 },
+       /* 32k rate */
+       { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
+-              2048000, 6, 1, 1 },
++              2048000, 1024000, 1, 1 },
+       { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
+-              2048000, 6, 1, 1 },
++              2048000, 1024000, 1, 1 },
+       /* 44.1k rate */
+       { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
+-              5644800, 4, 1, 1 },
++              5644800, 1411200, 1, 1 },
+       { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
+-              2822400, 4, 1, 1 },
++              2822400, 1411200, 1, 1 },
+       { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
+-              2822400, 4, 1, 1 },
++              2822400, 1411200, 1, 1 },
+       /* 48k rate */
+       { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
+-              6144000, 4, 1, 1 },
++              6144000, 1536000, 1, 1 },
+       { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
+-              3072000, 4, 1, 1 },
++              3072000, 1536000, 1, 1 },
+       { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
+-              3072000, 4, 1, 1 },
++              3072000, 1536000, 1, 1 },
+       /* 96k rate */
+       { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
+-              6144000, 1, 1, 9 },
++              6144000, 3072000, 1, 9 },
+ };
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -745,6 +745,7 @@ static int aic32x4_setup_clocks(struct s
+               { .id = "madc" },
+               { .id = "ndac" },
+               { .id = "mdac" },
++              { .id = "bdiv" },
+       };
+       i = aic32x4_get_divs(parent_rate, sample_rate);
+@@ -762,14 +763,10 @@ static int aic32x4_setup_clocks(struct s
+       clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
+       clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
+       clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
++      clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
+       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+-      /* DAC_MOD_CLK as BDIV_CLKIN */
+-      snd_soc_component_update_bits(component, AIC32X4_IFACE3,
+-                              AIC32X4_BDIVCLK_MASK,
+-                              AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+-
+       /* DOSR MSB & LSB values */
+       snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+       snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
+@@ -777,10 +774,6 @@ static int aic32x4_setup_clocks(struct s
+       /* AOSR value */
+       snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
+-      /* BCLK N divider */
+-      snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+-                              AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
+-
+       return 0;
+ }
+@@ -1003,6 +996,8 @@ static int aic32x4_component_probe(struc
+       struct clk_bulk_data clocks[] = {
+               { .id = "codec_clkin" },
+               { .id = "pll" },
++              { .id = "bdiv" },
++              { .id = "mdac" },
+       };
+       ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+@@ -1020,6 +1015,7 @@ static int aic32x4_component_probe(struc
+               aic32x4_setup_gpios(component);
+       clk_set_parent(clocks[0].clk, clocks[1].clk);
++      clk_set_parent(clocks[2].clk, clocks[3].clk);
+       /* Power platform configuration */
+       if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0347-ASoC-tlv320aic32x4-Model-CODEC_CLKIN-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0347-ASoC-tlv320aic32x4-Model-CODEC_CLKIN-in-CCF.patch
deleted file mode 100644 (file)
index 928d05a..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-From c5f9d78ec34de15732bcbff52bedba7a840e42b2 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:46 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF
-
-commit fd2df3aeafa4b4cc468d58e147e0822967034b71 upstream.
-
-Model and manage codec clock input as a component in the Core
-Clock Framework.  This should allow us to do some more complex
-clock management and power control.  Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-clk.c | 34 ++++++++++++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c     | 18 +++++++++++----
- 2 files changed, 47 insertions(+), 5 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-clk.c
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -265,6 +265,30 @@ static const struct clk_ops aic32x4_pll_
-       .get_parent = clk_aic32x4_pll_get_parent,
- };
-+static int clk_aic32x4_codec_clkin_set_parent(struct clk_hw *hw, u8 index)
-+{
-+      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+
-+      return regmap_update_bits(mux->regmap,
-+              AIC32X4_CLKMUX,
-+              AIC32X4_CODEC_CLKIN_MASK, index << AIC32X4_CODEC_CLKIN_SHIFT);
-+}
-+
-+static u8 clk_aic32x4_codec_clkin_get_parent(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+      unsigned int val;
-+
-+      regmap_read(mux->regmap, AIC32X4_CLKMUX, &val);
-+
-+      return (val & AIC32X4_CODEC_CLKIN_MASK) >> AIC32X4_CODEC_CLKIN_SHIFT;
-+}
-+
-+static const struct clk_ops aic32x4_codec_clkin_ops = {
-+      .set_parent = clk_aic32x4_codec_clkin_set_parent,
-+      .get_parent = clk_aic32x4_codec_clkin_get_parent,
-+};
-+
- static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
-       {
-               .name = "pll",
-@@ -274,6 +298,14 @@ static struct aic32x4_clkdesc aic32x4_cl
-               .ops = &aic32x4_pll_ops,
-               .reg = 0,
-       },
-+      {
-+              .name = "codec_clkin",
-+              .parent_names =
-+                      (const char *[]) { "mclk", "bclk", "gpio", "pll" },
-+              .num_parents = 4,
-+              .ops = &aic32x4_codec_clkin_ops,
-+              .reg = 0,
-+      },
- };
- static struct clk *aic32x4_register_clk(struct device *dev,
-@@ -314,6 +346,8 @@ int aic32x4_register_clocks(struct devic
-        */
-       aic32x4_clkdesc_array[0].parent_names =
-                       (const char* []) { mclk_name, "bclk", "gpio", "din" };
-+      aic32x4_clkdesc_array[1].parent_names =
-+                      (const char *[]) { mclk_name, "bclk", "gpio", "pll" };
-       for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
-               aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -737,12 +737,9 @@ static int aic32x4_setup_clocks(struct s
-       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
--      /* PLL as CODEC_CLKIN */
--      snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
--                      AIC32X4_CODEC_CLKIN_MASK,
--                      AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
-       /* DAC_MOD_CLK as BDIV_CLKIN */
--      snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
-+      snd_soc_component_update_bits(component, AIC32X4_IFACE3,
-+                              AIC32X4_BDIVCLK_MASK,
-                               AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
-       /* NDAC divider value */
-@@ -989,6 +986,15 @@ static int aic32x4_component_probe(struc
- {
-       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-       u32 tmp_reg;
-+      int ret;
-+
-+      struct clk_bulk_data clocks[] = {
-+          { .id = "codec_clkin" },
-+      };
-+
-+      ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-+      if (ret)
-+              return ret;
-       if (gpio_is_valid(aic32x4->rstn_gpio)) {
-               ndelay(10);
-@@ -1000,6 +1006,8 @@ static int aic32x4_component_probe(struc
-       if (aic32x4->setup)
-               aic32x4_setup_gpios(component);
-+      clk_set_parent(clocks[0].clk, clocks[1].clk);
-+
-       /* Power platform configuration */
-       if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
-               snd_soc_component_write(component, AIC32X4_MICBIAS,
diff --git a/target/linux/brcm2708/patches-4.19/950-0348-ASoC-tlv320aic32x4-Control-clock-gating-with-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0348-ASoC-tlv320aic32x4-Control-clock-gating-with-CCF.patch
new file mode 100644 (file)
index 0000000..c056c34
--- /dev/null
@@ -0,0 +1,109 @@
+From f844ea32cba0c4030594a0f590725477a5751f32 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:49 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Control clock gating with CCF
+
+commit d25970b5fd51e9fcf0afbe190908ea4049454da4 upstream.
+
+Control the clock gating to the various clock components to use
+the CCF.  This allows us to prepare_enalbe only 3 clocks and the
+relationships assigned to them will cause upstream clockss to
+enable automatically.  Additionally we can do this in a single
+call to the CCF.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 67 +++++++-------------------------
+ 1 file changed, 13 insertions(+), 54 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -836,41 +836,25 @@ static int aic32x4_mute(struct snd_soc_d
+ static int aic32x4_set_bias_level(struct snd_soc_component *component,
+                                 enum snd_soc_bias_level level)
+ {
+-      struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+       int ret;
++      struct clk_bulk_data clocks[] = {
++              { .id = "madc" },
++              { .id = "mdac" },
++              { .id = "bdiv" },
++      };
++
++      ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
++      if (ret)
++              return ret;
++
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+-              /* Switch on master clock */
+-              ret = clk_prepare_enable(aic32x4->mclk);
++              ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks);
+               if (ret) {
+-                      dev_err(component->dev, "Failed to enable master clock\n");
++                      dev_err(component->dev, "Failed to enable clocks\n");
+                       return ret;
+               }
+-
+-              /* Switch on PLL */
+-              snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+-                                      AIC32X4_PLLEN, AIC32X4_PLLEN);
+-
+-              /* Switch on NDAC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_NDAC,
+-                                      AIC32X4_NDACEN, AIC32X4_NDACEN);
+-
+-              /* Switch on MDAC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_MDAC,
+-                                      AIC32X4_MDACEN, AIC32X4_MDACEN);
+-
+-              /* Switch on NADC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_NADC,
+-                                      AIC32X4_NADCEN, AIC32X4_NADCEN);
+-
+-              /* Switch on MADC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_MADC,
+-                                      AIC32X4_MADCEN, AIC32X4_MADCEN);
+-
+-              /* Switch on BCLK_N Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+-                                      AIC32X4_BCLKEN, AIC32X4_BCLKEN);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+@@ -879,32 +863,7 @@ static int aic32x4_set_bias_level(struct
+               if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+                       break;
+-              /* Switch off BCLK_N Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+-                                      AIC32X4_BCLKEN, 0);
+-
+-              /* Switch off MADC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_MADC,
+-                                      AIC32X4_MADCEN, 0);
+-
+-              /* Switch off NADC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_NADC,
+-                                      AIC32X4_NADCEN, 0);
+-
+-              /* Switch off MDAC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_MDAC,
+-                                      AIC32X4_MDACEN, 0);
+-
+-              /* Switch off NDAC Divider */
+-              snd_soc_component_update_bits(component, AIC32X4_NDAC,
+-                                      AIC32X4_NDACEN, 0);
+-
+-              /* Switch off PLL */
+-              snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+-                                      AIC32X4_PLLEN, 0);
+-
+-              /* Switch off master clock */
+-              clk_disable_unprepare(aic32x4->mclk);
++              clk_bulk_disable_unprepare(ARRAY_SIZE(clocks), clocks);
+               break;
+       case SND_SOC_BIAS_OFF:
+               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0348-ASoC-tlv320aic32x4-Model-DAC-ADC-dividers-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0348-ASoC-tlv320aic32x4-Model-DAC-ADC-dividers-in-CCF.patch
deleted file mode 100644 (file)
index fc671a4..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-From 3bf2e5984ab7acb4469ab0f3dfee8b7392001bbf Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:47 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Model DAC/ADC dividers in CCF
-
-commit a51b50062091619915c5155085bbe13a7aca6903 upstream.
-
-Model and manage DAC/ADC dividers as components in the Core
-Clock Framework.  This should allow us to do some more complex
-clock management and power control.  Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-clk.c |  90 ++++++++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c     | 101 +++++++++++++++------------
- sound/soc/codecs/tlv320aic32x4.h     |   4 ++
- 3 files changed, 151 insertions(+), 44 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-clk.c
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -289,6 +289,68 @@ static const struct clk_ops aic32x4_code
-       .get_parent = clk_aic32x4_codec_clkin_get_parent,
- };
-+static int clk_aic32x4_div_prepare(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+
-+      return regmap_update_bits(div->regmap, div->reg,
-+                              AIC32X4_DIVEN, AIC32X4_DIVEN);
-+}
-+
-+static void clk_aic32x4_div_unprepare(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+
-+      regmap_update_bits(div->regmap, div->reg,
-+                      AIC32X4_DIVEN, 0);
-+}
-+
-+static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate,
-+                              unsigned long parent_rate)
-+{
-+      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+      u8 divisor;
-+
-+      divisor = DIV_ROUND_UP(parent_rate, rate);
-+      if (divisor > 128)
-+              return -EINVAL;
-+
-+      return regmap_update_bits(div->regmap, div->reg,
-+                              AIC32X4_DIV_MASK, divisor);
-+}
-+
-+static long clk_aic32x4_div_round_rate(struct clk_hw *hw, unsigned long rate,
-+                              unsigned long *parent_rate)
-+{
-+      unsigned long divisor;
-+
-+      divisor = DIV_ROUND_UP(*parent_rate, rate);
-+      if (divisor > 128)
-+              return -EINVAL;
-+
-+      return DIV_ROUND_UP(*parent_rate, divisor);
-+}
-+
-+static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw,
-+                                              unsigned long parent_rate)
-+{
-+      struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+
-+      unsigned int val;
-+
-+      regmap_read(div->regmap, div->reg, &val);
-+
-+      return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK);
-+}
-+
-+static const struct clk_ops aic32x4_div_ops = {
-+      .prepare = clk_aic32x4_div_prepare,
-+      .unprepare = clk_aic32x4_div_unprepare,
-+      .set_rate = clk_aic32x4_div_set_rate,
-+      .round_rate = clk_aic32x4_div_round_rate,
-+      .recalc_rate = clk_aic32x4_div_recalc_rate,
-+};
-+
- static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
-       {
-               .name = "pll",
-@@ -306,6 +368,34 @@ static struct aic32x4_clkdesc aic32x4_cl
-               .ops = &aic32x4_codec_clkin_ops,
-               .reg = 0,
-       },
-+      {
-+              .name = "ndac",
-+              .parent_names = (const char * []) { "codec_clkin" },
-+              .num_parents = 1,
-+              .ops = &aic32x4_div_ops,
-+              .reg = AIC32X4_NDAC,
-+      },
-+      {
-+              .name = "mdac",
-+              .parent_names = (const char * []) { "ndac" },
-+              .num_parents = 1,
-+              .ops = &aic32x4_div_ops,
-+              .reg = AIC32X4_MDAC,
-+      },
-+      {
-+              .name = "nadc",
-+              .parent_names = (const char * []) { "codec_clkin" },
-+              .num_parents = 1,
-+              .ops = &aic32x4_div_ops,
-+              .reg = AIC32X4_NADC,
-+      },
-+      {
-+              .name = "madc",
-+              .parent_names = (const char * []) { "nadc" },
-+              .num_parents = 1,
-+              .ops = &aic32x4_div_ops,
-+              .reg = AIC32X4_MADC,
-+      },
- };
- static struct clk *aic32x4_register_clk(struct device *dev,
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -52,11 +52,11 @@ struct aic32x4_rate_divs {
-       u32 rate;
-       unsigned long pll_rate;
-       u16 dosr;
--      u8 ndac;
--      u8 mdac;
-+      unsigned long ndac_rate;
-+      unsigned long mdac_rate;
-       u8 aosr;
--      u8 nadc;
--      u8 madc;
-+      unsigned long nadc_rate;
-+      unsigned long madc_rate;
-       u8 blck_N;
-       u8 r_block;
-       u8 p_block;
-@@ -309,34 +309,54 @@ static const struct snd_kcontrol_new aic
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
-       /* 8k rate */
--      { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
--      { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
--      { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
-+      { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
-+              1024000, 24, 1, 1 },
-+      { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
-+              512000, 24, 1, 1 },
-+      { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
-+              512000, 24, 1, 1 },
-       /* 11.025k rate */
--      { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
--      { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
-+      { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
-+              1411200, 16, 1, 1 },
-+      { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
-+              705600, 16, 1, 1 },
-       /* 16k rate */
--      { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
--      { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
--      { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
-+      { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
-+              2048000, 12, 1, 1 },
-+      { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
-+              1024000, 12, 1, 1 },
-+      { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
-+              1024000, 12, 1, 1 },
-       /* 22.05k rate */
--      { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
--      { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
--      { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
-+      { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
-+              2822400, 8, 1, 1 },
-+      { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
-+              1411200, 8, 1, 1 },
-+      { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
-+              1411200, 8, 1, 1 },
-       /* 32k rate */
--      { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
--      { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
-+      { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
-+              2048000, 6, 1, 1 },
-+      { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
-+              2048000, 6, 1, 1 },
-       /* 44.1k rate */
--      { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
--      { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
--      { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+      { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
-+              5644800, 4, 1, 1 },
-+      { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
-+              2822400, 4, 1, 1 },
-+      { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
-+              2822400, 4, 1, 1 },
-       /* 48k rate */
--      { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
--      { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
--      { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+      { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
-+              6144000, 4, 1, 1 },
-+      { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
-+              3072000, 4, 1, 1 },
-+      { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
-+              3072000, 4, 1, 1 },
-       /* 96k rate */
--      { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
-+      { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
-+              6144000, 1, 1, 9 },
- };
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -721,6 +741,10 @@ static int aic32x4_setup_clocks(struct s
-       struct clk_bulk_data clocks[] = {
-               { .id = "pll" },
-+              { .id = "nadc" },
-+              { .id = "madc" },
-+              { .id = "ndac" },
-+              { .id = "mdac" },
-       };
-       i = aic32x4_get_divs(parent_rate, sample_rate);
-@@ -733,7 +757,11 @@ static int aic32x4_setup_clocks(struct s
-       if (ret)
-               return ret;
--      clk_set_rate(clocks[0].clk, sample_rate);
-+      clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
-+      clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
-+      clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
-+      clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
-+      clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
-       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-@@ -742,26 +770,10 @@ static int aic32x4_setup_clocks(struct s
-                               AIC32X4_BDIVCLK_MASK,
-                               AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
--      /* NDAC divider value */
--      snd_soc_component_update_bits(component, AIC32X4_NDAC,
--                              AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
--
--      /* MDAC divider value */
--      snd_soc_component_update_bits(component, AIC32X4_MDAC,
--                              AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
--
-       /* DOSR MSB & LSB values */
-       snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
-       snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
--      /* NADC divider value */
--      snd_soc_component_update_bits(component, AIC32X4_NADC,
--                              AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
--
--      /* MADC divider value */
--      snd_soc_component_update_bits(component, AIC32X4_MADC,
--                              AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
--
-       /* AOSR value */
-       snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-@@ -773,8 +785,8 @@ static int aic32x4_setup_clocks(struct s
- }
- static int aic32x4_hw_params(struct snd_pcm_substream *substream,
--                           struct snd_pcm_hw_params *params,
--                           struct snd_soc_dai *dai)
-+                               struct snd_pcm_hw_params *params,
-+                               struct snd_soc_dai *dai)
- {
-       struct snd_soc_component *component = dai->component;
-       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-@@ -989,7 +1001,8 @@ static int aic32x4_component_probe(struc
-       int ret;
-       struct clk_bulk_data clocks[] = {
--          { .id = "codec_clkin" },
-+              { .id = "codec_clkin" },
-+              { .id = "pll" },
-       };
-       ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -206,6 +206,10 @@ int aic32x4_register_clocks(struct devic
- #define AIC32X4_RMICPGANIN_IN1L_10K   0x10
- #define AIC32X4_RMICPGANIN_CM1R_10K   0x40
-+/* Common mask and enable for all of the dividers */
-+#define AIC32X4_DIVEN           BIT(7)
-+#define AIC32X4_DIV_MASK        GENMASK(6, 0)
-+
- /* Clock Limits */
- #define AIC32X4_MAX_PLL_CLKIN         20000000
diff --git a/target/linux/brcm2708/patches-4.19/950-0349-ASoC-tlv320aic32x4-Model-BDIV-divider-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0349-ASoC-tlv320aic32x4-Model-BDIV-divider-in-CCF.patch
deleted file mode 100644 (file)
index 708e449..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-From 69f3f8c51077d0f3dc7f46c2c9a94da899d8eb7c Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:48 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Model BDIV divider in CCF
-
-commit 9b484124ebd906c4d6bc826cc0d417e80cc1105c upstream.
-
-Model and manage BDIV divider as components in the Core
-Clock Framework.  This should allow us to do some more complex
-clock management and power control.  Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-clk.c | 36 ++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c     | 56 +++++++++++++---------------
- 2 files changed, 62 insertions(+), 30 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-clk.c
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -351,6 +351,34 @@ static const struct clk_ops aic32x4_div_
-       .recalc_rate = clk_aic32x4_div_recalc_rate,
- };
-+static int clk_aic32x4_bdiv_set_parent(struct clk_hw *hw, u8 index)
-+{
-+      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+
-+      return regmap_update_bits(mux->regmap, AIC32X4_IFACE3,
-+                              AIC32X4_BDIVCLK_MASK, index);
-+}
-+
-+static u8 clk_aic32x4_bdiv_get_parent(struct clk_hw *hw)
-+{
-+      struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+      unsigned int val;
-+
-+      regmap_read(mux->regmap, AIC32X4_IFACE3, &val);
-+
-+      return val & AIC32X4_BDIVCLK_MASK;
-+}
-+
-+static const struct clk_ops aic32x4_bdiv_ops = {
-+      .prepare = clk_aic32x4_div_prepare,
-+      .unprepare = clk_aic32x4_div_unprepare,
-+      .set_parent = clk_aic32x4_bdiv_set_parent,
-+      .get_parent = clk_aic32x4_bdiv_get_parent,
-+      .set_rate = clk_aic32x4_div_set_rate,
-+      .round_rate = clk_aic32x4_div_round_rate,
-+      .recalc_rate = clk_aic32x4_div_recalc_rate,
-+};
-+
- static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
-       {
-               .name = "pll",
-@@ -396,6 +424,14 @@ static struct aic32x4_clkdesc aic32x4_cl
-               .ops = &aic32x4_div_ops,
-               .reg = AIC32X4_MADC,
-       },
-+      {
-+              .name = "bdiv",
-+              .parent_names =
-+                      (const char *[]) { "ndac", "mdac", "nadc", "madc" },
-+              .num_parents = 4,
-+              .ops = &aic32x4_bdiv_ops,
-+              .reg = AIC32X4_BCLKN,
-+      },
- };
- static struct clk *aic32x4_register_clk(struct device *dev,
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -57,7 +57,7 @@ struct aic32x4_rate_divs {
-       u8 aosr;
-       unsigned long nadc_rate;
-       unsigned long madc_rate;
--      u8 blck_N;
-+      unsigned long bdiv_rate;
-       u8 r_block;
-       u8 p_block;
- };
-@@ -310,53 +310,53 @@ static const struct snd_kcontrol_new aic
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
-       /* 8k rate */
-       { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
--              1024000, 24, 1, 1 },
-+              1024000, 256000, 1, 1 },
-       { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
--              512000, 24, 1, 1 },
-+              512000, 256000, 1, 1 },
-       { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
--              512000, 24, 1, 1 },
-+              512000, 256000, 1, 1 },
-       /* 11.025k rate */
-       { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
--              1411200, 16, 1, 1 },
-+              1411200, 352800, 1, 1 },
-       { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
--              705600, 16, 1, 1 },
-+              705600, 352800, 1, 1 },
-       /* 16k rate */
-       { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
--              2048000, 12, 1, 1 },
-+              2048000, 512000, 1, 1 },
-       { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
--              1024000, 12, 1, 1 },
-+              1024000, 512000, 1, 1 },
-       { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
--              1024000, 12, 1, 1 },
-+              1024000, 512000, 1, 1 },
-       /* 22.05k rate */
-       { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
--              2822400, 8, 1, 1 },
-+              2822400, 705600, 1, 1 },
-       { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
--              1411200, 8, 1, 1 },
-+              1411200, 705600, 1, 1 },
-       { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
--              1411200, 8, 1, 1 },
-+              1411200, 705600, 1, 1 },
-       /* 32k rate */
-       { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
--              2048000, 6, 1, 1 },
-+              2048000, 1024000, 1, 1 },
-       { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
--              2048000, 6, 1, 1 },
-+              2048000, 1024000, 1, 1 },
-       /* 44.1k rate */
-       { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
--              5644800, 4, 1, 1 },
-+              5644800, 1411200, 1, 1 },
-       { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
--              2822400, 4, 1, 1 },
-+              2822400, 1411200, 1, 1 },
-       { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
--              2822400, 4, 1, 1 },
-+              2822400, 1411200, 1, 1 },
-       /* 48k rate */
-       { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
--              6144000, 4, 1, 1 },
-+              6144000, 1536000, 1, 1 },
-       { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
--              3072000, 4, 1, 1 },
-+              3072000, 1536000, 1, 1 },
-       { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
--              3072000, 4, 1, 1 },
-+              3072000, 1536000, 1, 1 },
-       /* 96k rate */
-       { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
--              6144000, 1, 1, 9 },
-+              6144000, 3072000, 1, 9 },
- };
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -745,6 +745,7 @@ static int aic32x4_setup_clocks(struct s
-               { .id = "madc" },
-               { .id = "ndac" },
-               { .id = "mdac" },
-+              { .id = "bdiv" },
-       };
-       i = aic32x4_get_divs(parent_rate, sample_rate);
-@@ -762,14 +763,10 @@ static int aic32x4_setup_clocks(struct s
-       clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
-       clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
-       clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
-+      clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
-       aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
--      /* DAC_MOD_CLK as BDIV_CLKIN */
--      snd_soc_component_update_bits(component, AIC32X4_IFACE3,
--                              AIC32X4_BDIVCLK_MASK,
--                              AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
--
-       /* DOSR MSB & LSB values */
-       snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
-       snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
-@@ -777,10 +774,6 @@ static int aic32x4_setup_clocks(struct s
-       /* AOSR value */
-       snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
--      /* BCLK N divider */
--      snd_soc_component_update_bits(component, AIC32X4_BCLKN,
--                              AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
--
-       return 0;
- }
-@@ -1003,6 +996,8 @@ static int aic32x4_component_probe(struc
-       struct clk_bulk_data clocks[] = {
-               { .id = "codec_clkin" },
-               { .id = "pll" },
-+              { .id = "bdiv" },
-+              { .id = "mdac" },
-       };
-       ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-@@ -1020,6 +1015,7 @@ static int aic32x4_component_probe(struc
-               aic32x4_setup_gpios(component);
-       clk_set_parent(clocks[0].clk, clocks[1].clk);
-+      clk_set_parent(clocks[2].clk, clocks[3].clk);
-       /* Power platform configuration */
-       if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0349-ASoC-tlv320aic32x4-Move-aosr-and-dosr-setting-to-sep.patch b/target/linux/brcm2708/patches-4.19/950-0349-ASoC-tlv320aic32x4-Move-aosr-and-dosr-setting-to-sep.patch
new file mode 100644 (file)
index 0000000..85b008e
--- /dev/null
@@ -0,0 +1,58 @@
+From a2d8d212b986e4a4ae52c748d246e4c28ebaf1bc Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:50 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Move aosr and dosr setting to
+ separate functions
+
+commit fbafbf6517274a797e6e6508c18dd8dba5920c89 upstream.
+
+Move these to separate helper functions.  This looks cleaner and fits
+better with the new clock setting in CCF.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -720,6 +720,20 @@ static int aic32x4_set_dai_fmt(struct sn
+       return 0;
+ }
++static int aic32x4_set_aosr(struct snd_soc_component *component, u8 aosr)
++{
++      return snd_soc_component_write(component, AIC32X4_AOSR, aosr);
++}
++
++static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
++{
++      snd_soc_component_write(component, AIC32X4_DOSRMSB, dosr >> 8);
++      snd_soc_component_write(component, AIC32X4_DOSRLSB,
++                    (dosr & 0xff));
++
++      return 0;
++}
++
+ static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
+                                               u8 r_block, u8 p_block)
+ {
+@@ -765,14 +779,10 @@ static int aic32x4_setup_clocks(struct s
+       clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
+       clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
+-      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
++      aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
++      aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
+-      /* DOSR MSB & LSB values */
+-      snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+-      snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
+-
+-      /* AOSR value */
+-      snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
++      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0350-ASoC-tlv320aic32x4-Control-clock-gating-with-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0350-ASoC-tlv320aic32x4-Control-clock-gating-with-CCF.patch
deleted file mode 100644 (file)
index c056c34..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-From f844ea32cba0c4030594a0f590725477a5751f32 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:49 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Control clock gating with CCF
-
-commit d25970b5fd51e9fcf0afbe190908ea4049454da4 upstream.
-
-Control the clock gating to the various clock components to use
-the CCF.  This allows us to prepare_enalbe only 3 clocks and the
-relationships assigned to them will cause upstream clockss to
-enable automatically.  Additionally we can do this in a single
-call to the CCF.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 67 +++++++-------------------------
- 1 file changed, 13 insertions(+), 54 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -836,41 +836,25 @@ static int aic32x4_mute(struct snd_soc_d
- static int aic32x4_set_bias_level(struct snd_soc_component *component,
-                                 enum snd_soc_bias_level level)
- {
--      struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-       int ret;
-+      struct clk_bulk_data clocks[] = {
-+              { .id = "madc" },
-+              { .id = "mdac" },
-+              { .id = "bdiv" },
-+      };
-+
-+      ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-+      if (ret)
-+              return ret;
-+
-       switch (level) {
-       case SND_SOC_BIAS_ON:
--              /* Switch on master clock */
--              ret = clk_prepare_enable(aic32x4->mclk);
-+              ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks);
-               if (ret) {
--                      dev_err(component->dev, "Failed to enable master clock\n");
-+                      dev_err(component->dev, "Failed to enable clocks\n");
-                       return ret;
-               }
--
--              /* Switch on PLL */
--              snd_soc_component_update_bits(component, AIC32X4_PLLPR,
--                                      AIC32X4_PLLEN, AIC32X4_PLLEN);
--
--              /* Switch on NDAC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_NDAC,
--                                      AIC32X4_NDACEN, AIC32X4_NDACEN);
--
--              /* Switch on MDAC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_MDAC,
--                                      AIC32X4_MDACEN, AIC32X4_MDACEN);
--
--              /* Switch on NADC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_NADC,
--                                      AIC32X4_NADCEN, AIC32X4_NADCEN);
--
--              /* Switch on MADC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_MADC,
--                                      AIC32X4_MADCEN, AIC32X4_MADCEN);
--
--              /* Switch on BCLK_N Divider */
--              snd_soc_component_update_bits(component, AIC32X4_BCLKN,
--                                      AIC32X4_BCLKEN, AIC32X4_BCLKEN);
-               break;
-       case SND_SOC_BIAS_PREPARE:
-               break;
-@@ -879,32 +863,7 @@ static int aic32x4_set_bias_level(struct
-               if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
-                       break;
--              /* Switch off BCLK_N Divider */
--              snd_soc_component_update_bits(component, AIC32X4_BCLKN,
--                                      AIC32X4_BCLKEN, 0);
--
--              /* Switch off MADC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_MADC,
--                                      AIC32X4_MADCEN, 0);
--
--              /* Switch off NADC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_NADC,
--                                      AIC32X4_NADCEN, 0);
--
--              /* Switch off MDAC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_MDAC,
--                                      AIC32X4_MDACEN, 0);
--
--              /* Switch off NDAC Divider */
--              snd_soc_component_update_bits(component, AIC32X4_NDAC,
--                                      AIC32X4_NDACEN, 0);
--
--              /* Switch off PLL */
--              snd_soc_component_update_bits(component, AIC32X4_PLLPR,
--                                      AIC32X4_PLLEN, 0);
--
--              /* Switch off master clock */
--              clk_disable_unprepare(aic32x4->mclk);
-+              clk_bulk_disable_unprepare(ARRAY_SIZE(clocks), clocks);
-               break;
-       case SND_SOC_BIAS_OFF:
-               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0350-ASoC-tlv320aic32x4-Dynamically-Determine-Clocking.patch b/target/linux/brcm2708/patches-4.19/950-0350-ASoC-tlv320aic32x4-Dynamically-Determine-Clocking.patch
new file mode 100644 (file)
index 0000000..9455206
--- /dev/null
@@ -0,0 +1,285 @@
+From 3e62c56daa1c799bb2a1d954ecfb88e8d37421bb Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:51 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Dynamically Determine Clocking
+
+commit 96c3bb00239de4fb5f4ddca42c1f90d6d9b3c697 upstream.
+
+The existing code uses a static lookup table to determine the
+settings of the various clock devices on board the chip.  This is
+limiting in a couple of ways.  First, this doesn't allow for any
+master clock rates other than the three that have been
+precalculated.  Additionally, new sample rates are difficult to
+add to the table.  Witness that the chip is capable of 192000 Hz
+sampling, but it is not provided by this driver.  Last, if the
+driver is clocked by something that isn't a crystal, the
+upstream clock may not be able to achieve exactly the rate
+requested in the driver.  This will mean that clocking will be
+slightly off for the sampling clock or that it won't work at all.
+
+This patch determines the settings for all of the clocks at
+runtime considering the real conditions of the clocks in the
+system.  The rules for the clocks are in TI's SLAA557 application
+guide on pages 37, 51 and 77.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 190 ++++++++++++++-----------------
+ sound/soc/codecs/tlv320aic32x4.h |   4 +-
+ 2 files changed, 90 insertions(+), 104 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -47,21 +47,6 @@
+ #include "tlv320aic32x4.h"
+-struct aic32x4_rate_divs {
+-      u32 mclk;
+-      u32 rate;
+-      unsigned long pll_rate;
+-      u16 dosr;
+-      unsigned long ndac_rate;
+-      unsigned long mdac_rate;
+-      u8 aosr;
+-      unsigned long nadc_rate;
+-      unsigned long madc_rate;
+-      unsigned long bdiv_rate;
+-      u8 r_block;
+-      u8 p_block;
+-};
+-
+ struct aic32x4_priv {
+       struct regmap *regmap;
+       u32 sysclk;
+@@ -307,58 +292,6 @@ static const struct snd_kcontrol_new aic
+                       0, 0x0F, 0),
+ };
+-static const struct aic32x4_rate_divs aic32x4_divs[] = {
+-      /* 8k rate */
+-      { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
+-              1024000, 256000, 1, 1 },
+-      { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
+-              512000, 256000, 1, 1 },
+-      { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
+-              512000, 256000, 1, 1 },
+-      /* 11.025k rate */
+-      { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
+-              1411200, 352800, 1, 1 },
+-      { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
+-              705600, 352800, 1, 1 },
+-      /* 16k rate */
+-      { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
+-              2048000, 512000, 1, 1 },
+-      { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
+-              1024000, 512000, 1, 1 },
+-      { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
+-              1024000, 512000, 1, 1 },
+-      /* 22.05k rate */
+-      { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
+-              2822400, 705600, 1, 1 },
+-      { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
+-              1411200, 705600, 1, 1 },
+-      { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
+-              1411200, 705600, 1, 1 },
+-      /* 32k rate */
+-      { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
+-              2048000, 1024000, 1, 1 },
+-      { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
+-              2048000, 1024000, 1, 1 },
+-      /* 44.1k rate */
+-      { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
+-              5644800, 1411200, 1, 1 },
+-      { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
+-              2822400, 1411200, 1, 1 },
+-      { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
+-              2822400, 1411200, 1, 1 },
+-      /* 48k rate */
+-      { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
+-              6144000, 1536000, 1, 1 },
+-      { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
+-              3072000, 1536000, 1, 1 },
+-      { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
+-              3072000, 1536000, 1, 1 },
+-
+-      /* 96k rate */
+-      { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
+-              6144000, 3072000, 1, 9 },
+-};
+-
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+       SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0),
+       SOC_DAPM_SINGLE("IN1_L Switch", AIC32X4_HPLROUTE, 2, 1, 0),
+@@ -632,20 +565,6 @@ const struct regmap_config aic32x4_regma
+ };
+ EXPORT_SYMBOL(aic32x4_regmap_config);
+-static inline int aic32x4_get_divs(int mclk, int rate)
+-{
+-      int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
+-              if ((aic32x4_divs[i].rate == rate)
+-                      && (aic32x4_divs[i].mclk == mclk)) {
+-                      return i;
+-              }
+-      }
+-      printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n");
+-      return -EINVAL;
+-}
+-
+ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                                 int clk_id, unsigned int freq, int dir)
+ {
+@@ -747,11 +666,17 @@ static int aic32x4_set_processing_blocks
+ }
+ static int aic32x4_setup_clocks(struct snd_soc_component *component,
+-                              unsigned int sample_rate,
+-                              unsigned int parent_rate)
++                              unsigned int sample_rate)
+ {
+-      int i;
++      u8 aosr;
++      u16 dosr;
++      u8 adc_resource_class, dac_resource_class;
++      u8 madc, nadc, mdac, ndac, max_nadc, min_mdac, max_ndac;
++      u8 dosr_increment;
++      u16 max_dosr, min_dosr;
++      unsigned long mclk_rate, adc_clock_rate, dac_clock_rate;
+       int ret;
++      struct clk *mclk;
+       struct clk_bulk_data clocks[] = {
+               { .id = "pll" },
+@@ -761,30 +686,89 @@ static int aic32x4_setup_clocks(struct s
+               { .id = "mdac" },
+               { .id = "bdiv" },
+       };
+-
+-      i = aic32x4_get_divs(parent_rate, sample_rate);
+-      if (i < 0) {
+-              printk(KERN_ERR "aic32x4: sampling rate not supported\n");
+-              return i;
+-      }
+-
+       ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+       if (ret)
+               return ret;
+-      clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
+-      clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
+-      clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
+-      clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
+-      clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
+-      clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
++      mclk = clk_get_parent(clocks[1].clk);
++      mclk_rate = clk_get_rate(mclk);
+-      aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
+-      aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
++      if (sample_rate <= 48000) {
++              aosr = 128;
++              adc_resource_class = 6;
++              dac_resource_class = 8;
++              dosr_increment = 8;
++              aic32x4_set_processing_blocks(component, 1, 1);
++      } else if (sample_rate <= 96000) {
++              aosr = 64;
++              adc_resource_class = 6;
++              dac_resource_class = 8;
++              dosr_increment = 4;
++              aic32x4_set_processing_blocks(component, 1, 9);
++      } else if (sample_rate == 192000) {
++              aosr = 32;
++              adc_resource_class = 3;
++              dac_resource_class = 4;
++              dosr_increment = 2;
++              aic32x4_set_processing_blocks(component, 13, 19);
++      } else {
++              dev_err(component->dev, "Sampling rate not supported\n");
++              return -EINVAL;
++      }
+-      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
++      madc = DIV_ROUND_UP((32 * adc_resource_class), aosr);
++      max_dosr = (AIC32X4_MAX_DOSR_FREQ / sample_rate / dosr_increment) *
++                      dosr_increment;
++      min_dosr = (AIC32X4_MIN_DOSR_FREQ / sample_rate / dosr_increment) *
++                      dosr_increment;
++      max_nadc = AIC32X4_MAX_CODEC_CLKIN_FREQ / (madc * aosr * sample_rate);
++
++      for (nadc = max_nadc; nadc > 0; --nadc) {
++              adc_clock_rate = nadc * madc * aosr * sample_rate;
++              for (dosr = max_dosr; dosr >= min_dosr;
++                              dosr -= dosr_increment) {
++                      min_mdac = DIV_ROUND_UP((32 * dac_resource_class), dosr);
++                      max_ndac = AIC32X4_MAX_CODEC_CLKIN_FREQ /
++                                      (min_mdac * dosr * sample_rate);
++                      for (mdac = min_mdac; mdac <= 128; ++mdac) {
++                              for (ndac = max_ndac; ndac > 0; --ndac) {
++                                      dac_clock_rate = ndac * mdac * dosr *
++                                                      sample_rate;
++                                      if (dac_clock_rate == adc_clock_rate) {
++                                              if (clk_round_rate(clocks[0].clk, dac_clock_rate) == 0)
++                                                      continue;
++
++                                              clk_set_rate(clocks[0].clk,
++                                                      dac_clock_rate);
++
++                                              clk_set_rate(clocks[1].clk,
++                                                      sample_rate * aosr *
++                                                      madc);
++                                              clk_set_rate(clocks[2].clk,
++                                                      sample_rate * aosr);
++                                              aic32x4_set_aosr(component,
++                                                      aosr);
++
++                                              clk_set_rate(clocks[3].clk,
++                                                      sample_rate * dosr *
++                                                      mdac);
++                                              clk_set_rate(clocks[4].clk,
++                                                      sample_rate * dosr);
++                                              aic32x4_set_dosr(component,
++                                                      dosr);
++
++                                              clk_set_rate(clocks[5].clk,
++                                                      sample_rate * 32);
++                                              return 0;
++                                      }
++                              }
++                      }
++              }
++      }
+-      return 0;
++      dev_err(component->dev,
++              "Could not set clocks to support sample rate.\n");
++      return -EINVAL;
+ }
+ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
+@@ -796,7 +780,7 @@ static int aic32x4_hw_params(struct snd_
+       u8 iface1_reg = 0;
+       u8 dacsetup_reg = 0;
+-      aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
++      aic32x4_setup_clocks(component, params_rate(params));
+       switch (params_width(params)) {
+       case 16:
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -211,7 +211,9 @@ int aic32x4_register_clocks(struct devic
+ #define AIC32X4_DIV_MASK        GENMASK(6, 0)
+ /* Clock Limits */
++#define AIC32X4_MAX_DOSR_FREQ         6200000
++#define AIC32X4_MIN_DOSR_FREQ         2800000
++#define AIC32X4_MAX_CODEC_CLKIN_FREQ    110000000
+ #define AIC32X4_MAX_PLL_CLKIN         20000000
+-
+ #endif                                /* _TLV320AIC32X4_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0351-ASoC-tlv320aic32x4-Move-aosr-and-dosr-setting-to-sep.patch b/target/linux/brcm2708/patches-4.19/950-0351-ASoC-tlv320aic32x4-Move-aosr-and-dosr-setting-to-sep.patch
deleted file mode 100644 (file)
index 85b008e..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From a2d8d212b986e4a4ae52c748d246e4c28ebaf1bc Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:50 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Move aosr and dosr setting to
- separate functions
-
-commit fbafbf6517274a797e6e6508c18dd8dba5920c89 upstream.
-
-Move these to separate helper functions.  This looks cleaner and fits
-better with the new clock setting in CCF.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 24 +++++++++++++++++-------
- 1 file changed, 17 insertions(+), 7 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -720,6 +720,20 @@ static int aic32x4_set_dai_fmt(struct sn
-       return 0;
- }
-+static int aic32x4_set_aosr(struct snd_soc_component *component, u8 aosr)
-+{
-+      return snd_soc_component_write(component, AIC32X4_AOSR, aosr);
-+}
-+
-+static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
-+{
-+      snd_soc_component_write(component, AIC32X4_DOSRMSB, dosr >> 8);
-+      snd_soc_component_write(component, AIC32X4_DOSRLSB,
-+                    (dosr & 0xff));
-+
-+      return 0;
-+}
-+
- static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
-                                               u8 r_block, u8 p_block)
- {
-@@ -765,14 +779,10 @@ static int aic32x4_setup_clocks(struct s
-       clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
-       clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
--      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-+      aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
-+      aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
--      /* DOSR MSB & LSB values */
--      snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
--      snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
--
--      /* AOSR value */
--      snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-+      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0351-ASoC-tlv320aic32x4-Restructure-set_dai_sysclk.patch b/target/linux/brcm2708/patches-4.19/950-0351-ASoC-tlv320aic32x4-Restructure-set_dai_sysclk.patch
new file mode 100644 (file)
index 0000000..5caebcb
--- /dev/null
@@ -0,0 +1,51 @@
+From 5ec6ed3e423878cf975a955c8796c2cdb10b5ca7 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:52 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Restructure set_dai_sysclk
+
+commit aa6a60f7be925210d5156f0e8025f3afe1f4f54d upstream.
+
+The sysclk is now managed by the CCF.  Change this function
+to merely find the system clock and set it using
+clk_set_rate.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -49,7 +49,6 @@
+ struct aic32x4_priv {
+       struct regmap *regmap;
+-      u32 sysclk;
+       u32 power_cfg;
+       u32 micpga_routing;
+       bool swapdacs;
+@@ -569,17 +568,13 @@ static int aic32x4_set_dai_sysclk(struct
+                                 int clk_id, unsigned int freq, int dir)
+ {
+       struct snd_soc_component *component = codec_dai->component;
+-      struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
++      struct clk *mclk;
++      struct clk *pll;
+-      switch (freq) {
+-      case 12000000:
+-      case 24000000:
+-      case 25000000:
+-              aic32x4->sysclk = freq;
+-              return 0;
+-      }
+-      printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n");
+-      return -EINVAL;
++      pll = devm_clk_get(component->dev, "pll");
++      mclk = clk_get_parent(pll);
++
++      return clk_set_rate(mclk, freq);
+ }
+ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
diff --git a/target/linux/brcm2708/patches-4.19/950-0352-ASoC-tlv320aic32x4-Dynamically-Determine-Clocking.patch b/target/linux/brcm2708/patches-4.19/950-0352-ASoC-tlv320aic32x4-Dynamically-Determine-Clocking.patch
deleted file mode 100644 (file)
index 9455206..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-From 3e62c56daa1c799bb2a1d954ecfb88e8d37421bb Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:51 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Dynamically Determine Clocking
-
-commit 96c3bb00239de4fb5f4ddca42c1f90d6d9b3c697 upstream.
-
-The existing code uses a static lookup table to determine the
-settings of the various clock devices on board the chip.  This is
-limiting in a couple of ways.  First, this doesn't allow for any
-master clock rates other than the three that have been
-precalculated.  Additionally, new sample rates are difficult to
-add to the table.  Witness that the chip is capable of 192000 Hz
-sampling, but it is not provided by this driver.  Last, if the
-driver is clocked by something that isn't a crystal, the
-upstream clock may not be able to achieve exactly the rate
-requested in the driver.  This will mean that clocking will be
-slightly off for the sampling clock or that it won't work at all.
-
-This patch determines the settings for all of the clocks at
-runtime considering the real conditions of the clocks in the
-system.  The rules for the clocks are in TI's SLAA557 application
-guide on pages 37, 51 and 77.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 190 ++++++++++++++-----------------
- sound/soc/codecs/tlv320aic32x4.h |   4 +-
- 2 files changed, 90 insertions(+), 104 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -47,21 +47,6 @@
- #include "tlv320aic32x4.h"
--struct aic32x4_rate_divs {
--      u32 mclk;
--      u32 rate;
--      unsigned long pll_rate;
--      u16 dosr;
--      unsigned long ndac_rate;
--      unsigned long mdac_rate;
--      u8 aosr;
--      unsigned long nadc_rate;
--      unsigned long madc_rate;
--      unsigned long bdiv_rate;
--      u8 r_block;
--      u8 p_block;
--};
--
- struct aic32x4_priv {
-       struct regmap *regmap;
-       u32 sysclk;
-@@ -307,58 +292,6 @@ static const struct snd_kcontrol_new aic
-                       0, 0x0F, 0),
- };
--static const struct aic32x4_rate_divs aic32x4_divs[] = {
--      /* 8k rate */
--      { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
--              1024000, 256000, 1, 1 },
--      { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
--              512000, 256000, 1, 1 },
--      { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
--              512000, 256000, 1, 1 },
--      /* 11.025k rate */
--      { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
--              1411200, 352800, 1, 1 },
--      { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
--              705600, 352800, 1, 1 },
--      /* 16k rate */
--      { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
--              2048000, 512000, 1, 1 },
--      { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
--              1024000, 512000, 1, 1 },
--      { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
--              1024000, 512000, 1, 1 },
--      /* 22.05k rate */
--      { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
--              2822400, 705600, 1, 1 },
--      { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
--              1411200, 705600, 1, 1 },
--      { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
--              1411200, 705600, 1, 1 },
--      /* 32k rate */
--      { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
--              2048000, 1024000, 1, 1 },
--      { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
--              2048000, 1024000, 1, 1 },
--      /* 44.1k rate */
--      { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
--              5644800, 1411200, 1, 1 },
--      { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
--              2822400, 1411200, 1, 1 },
--      { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
--              2822400, 1411200, 1, 1 },
--      /* 48k rate */
--      { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
--              6144000, 1536000, 1, 1 },
--      { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
--              3072000, 1536000, 1, 1 },
--      { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
--              3072000, 1536000, 1, 1 },
--
--      /* 96k rate */
--      { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
--              6144000, 3072000, 1, 9 },
--};
--
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-       SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0),
-       SOC_DAPM_SINGLE("IN1_L Switch", AIC32X4_HPLROUTE, 2, 1, 0),
-@@ -632,20 +565,6 @@ const struct regmap_config aic32x4_regma
- };
- EXPORT_SYMBOL(aic32x4_regmap_config);
--static inline int aic32x4_get_divs(int mclk, int rate)
--{
--      int i;
--
--      for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
--              if ((aic32x4_divs[i].rate == rate)
--                      && (aic32x4_divs[i].mclk == mclk)) {
--                      return i;
--              }
--      }
--      printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n");
--      return -EINVAL;
--}
--
- static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-                                 int clk_id, unsigned int freq, int dir)
- {
-@@ -747,11 +666,17 @@ static int aic32x4_set_processing_blocks
- }
- static int aic32x4_setup_clocks(struct snd_soc_component *component,
--                              unsigned int sample_rate,
--                              unsigned int parent_rate)
-+                              unsigned int sample_rate)
- {
--      int i;
-+      u8 aosr;
-+      u16 dosr;
-+      u8 adc_resource_class, dac_resource_class;
-+      u8 madc, nadc, mdac, ndac, max_nadc, min_mdac, max_ndac;
-+      u8 dosr_increment;
-+      u16 max_dosr, min_dosr;
-+      unsigned long mclk_rate, adc_clock_rate, dac_clock_rate;
-       int ret;
-+      struct clk *mclk;
-       struct clk_bulk_data clocks[] = {
-               { .id = "pll" },
-@@ -761,30 +686,89 @@ static int aic32x4_setup_clocks(struct s
-               { .id = "mdac" },
-               { .id = "bdiv" },
-       };
--
--      i = aic32x4_get_divs(parent_rate, sample_rate);
--      if (i < 0) {
--              printk(KERN_ERR "aic32x4: sampling rate not supported\n");
--              return i;
--      }
--
-       ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-       if (ret)
-               return ret;
--      clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
--      clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
--      clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
--      clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
--      clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
--      clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
-+      mclk = clk_get_parent(clocks[1].clk);
-+      mclk_rate = clk_get_rate(mclk);
--      aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
--      aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
-+      if (sample_rate <= 48000) {
-+              aosr = 128;
-+              adc_resource_class = 6;
-+              dac_resource_class = 8;
-+              dosr_increment = 8;
-+              aic32x4_set_processing_blocks(component, 1, 1);
-+      } else if (sample_rate <= 96000) {
-+              aosr = 64;
-+              adc_resource_class = 6;
-+              dac_resource_class = 8;
-+              dosr_increment = 4;
-+              aic32x4_set_processing_blocks(component, 1, 9);
-+      } else if (sample_rate == 192000) {
-+              aosr = 32;
-+              adc_resource_class = 3;
-+              dac_resource_class = 4;
-+              dosr_increment = 2;
-+              aic32x4_set_processing_blocks(component, 13, 19);
-+      } else {
-+              dev_err(component->dev, "Sampling rate not supported\n");
-+              return -EINVAL;
-+      }
--      aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-+      madc = DIV_ROUND_UP((32 * adc_resource_class), aosr);
-+      max_dosr = (AIC32X4_MAX_DOSR_FREQ / sample_rate / dosr_increment) *
-+                      dosr_increment;
-+      min_dosr = (AIC32X4_MIN_DOSR_FREQ / sample_rate / dosr_increment) *
-+                      dosr_increment;
-+      max_nadc = AIC32X4_MAX_CODEC_CLKIN_FREQ / (madc * aosr * sample_rate);
-+
-+      for (nadc = max_nadc; nadc > 0; --nadc) {
-+              adc_clock_rate = nadc * madc * aosr * sample_rate;
-+              for (dosr = max_dosr; dosr >= min_dosr;
-+                              dosr -= dosr_increment) {
-+                      min_mdac = DIV_ROUND_UP((32 * dac_resource_class), dosr);
-+                      max_ndac = AIC32X4_MAX_CODEC_CLKIN_FREQ /
-+                                      (min_mdac * dosr * sample_rate);
-+                      for (mdac = min_mdac; mdac <= 128; ++mdac) {
-+                              for (ndac = max_ndac; ndac > 0; --ndac) {
-+                                      dac_clock_rate = ndac * mdac * dosr *
-+                                                      sample_rate;
-+                                      if (dac_clock_rate == adc_clock_rate) {
-+                                              if (clk_round_rate(clocks[0].clk, dac_clock_rate) == 0)
-+                                                      continue;
-+
-+                                              clk_set_rate(clocks[0].clk,
-+                                                      dac_clock_rate);
-+
-+                                              clk_set_rate(clocks[1].clk,
-+                                                      sample_rate * aosr *
-+                                                      madc);
-+                                              clk_set_rate(clocks[2].clk,
-+                                                      sample_rate * aosr);
-+                                              aic32x4_set_aosr(component,
-+                                                      aosr);
-+
-+                                              clk_set_rate(clocks[3].clk,
-+                                                      sample_rate * dosr *
-+                                                      mdac);
-+                                              clk_set_rate(clocks[4].clk,
-+                                                      sample_rate * dosr);
-+                                              aic32x4_set_dosr(component,
-+                                                      dosr);
-+
-+                                              clk_set_rate(clocks[5].clk,
-+                                                      sample_rate * 32);
-+                                              return 0;
-+                                      }
-+                              }
-+                      }
-+              }
-+      }
--      return 0;
-+      dev_err(component->dev,
-+              "Could not set clocks to support sample rate.\n");
-+      return -EINVAL;
- }
- static int aic32x4_hw_params(struct snd_pcm_substream *substream,
-@@ -796,7 +780,7 @@ static int aic32x4_hw_params(struct snd_
-       u8 iface1_reg = 0;
-       u8 dacsetup_reg = 0;
--      aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
-+      aic32x4_setup_clocks(component, params_rate(params));
-       switch (params_width(params)) {
-       case 16:
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -211,7 +211,9 @@ int aic32x4_register_clocks(struct devic
- #define AIC32X4_DIV_MASK        GENMASK(6, 0)
- /* Clock Limits */
-+#define AIC32X4_MAX_DOSR_FREQ         6200000
-+#define AIC32X4_MIN_DOSR_FREQ         2800000
-+#define AIC32X4_MAX_CODEC_CLKIN_FREQ    110000000
- #define AIC32X4_MAX_PLL_CLKIN         20000000
--
- #endif                                /* _TLV320AIC32X4_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0352-ASoC-tlv320aic32x4-Remove-mclk-references.patch b/target/linux/brcm2708/patches-4.19/950-0352-ASoC-tlv320aic32x4-Remove-mclk-references.patch
new file mode 100644 (file)
index 0000000..bee5852
--- /dev/null
@@ -0,0 +1,39 @@
+From 3c7bf08e6b6bdc2e6005aaa5e6aa6d12ce40d406 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:53 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Remove mclk references
+
+commit 78f2d58a289302e56a7def96a783a7686ebf27e2 upstream.
+
+mclk is not used by anything anymore.  Remove support for it.
+All that information now comes from the clock tree.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -53,7 +53,6 @@ struct aic32x4_priv {
+       u32 micpga_routing;
+       bool swapdacs;
+       int rstn_gpio;
+-      struct clk *mclk;
+       const char *mclk_name;
+       struct regulator *supply_ldo;
+@@ -1191,12 +1190,6 @@ int aic32x4_probe(struct device *dev, st
+               aic32x4->mclk_name = "mclk";
+       }
+-      aic32x4->mclk = devm_clk_get(dev, "mclk");
+-      if (IS_ERR(aic32x4->mclk)) {
+-              dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
+-              return PTR_ERR(aic32x4->mclk);
+-      }
+-
+       ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
+       if (ret)
+               return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0353-ASoC-tlv320aic32x4-Allow-192000-Sample-Rate.patch b/target/linux/brcm2708/patches-4.19/950-0353-ASoC-tlv320aic32x4-Allow-192000-Sample-Rate.patch
new file mode 100644 (file)
index 0000000..15ded09
--- /dev/null
@@ -0,0 +1,27 @@
+From e54269cdeb78beb5131594de702daeecc2b05ec2 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:54 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Allow 192000 Sample Rate
+
+commit 6d56ee1550b8a81bc63c80051ff78d8d704b09ba upstream.
+
+The clocking and processing blocks are now properly set up to
+support 192000 sample rates.  Allow drivers to ask for that.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -859,7 +859,7 @@ static int aic32x4_set_bias_level(struct
+       return 0;
+ }
+-#define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
++#define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000
+ #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+                        | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/target/linux/brcm2708/patches-4.19/950-0353-ASoC-tlv320aic32x4-Restructure-set_dai_sysclk.patch b/target/linux/brcm2708/patches-4.19/950-0353-ASoC-tlv320aic32x4-Restructure-set_dai_sysclk.patch
deleted file mode 100644 (file)
index 5caebcb..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From 5ec6ed3e423878cf975a955c8796c2cdb10b5ca7 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:52 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Restructure set_dai_sysclk
-
-commit aa6a60f7be925210d5156f0e8025f3afe1f4f54d upstream.
-
-The sysclk is now managed by the CCF.  Change this function
-to merely find the system clock and set it using
-clk_set_rate.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 17 ++++++-----------
- 1 file changed, 6 insertions(+), 11 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -49,7 +49,6 @@
- struct aic32x4_priv {
-       struct regmap *regmap;
--      u32 sysclk;
-       u32 power_cfg;
-       u32 micpga_routing;
-       bool swapdacs;
-@@ -569,17 +568,13 @@ static int aic32x4_set_dai_sysclk(struct
-                                 int clk_id, unsigned int freq, int dir)
- {
-       struct snd_soc_component *component = codec_dai->component;
--      struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-+      struct clk *mclk;
-+      struct clk *pll;
--      switch (freq) {
--      case 12000000:
--      case 24000000:
--      case 25000000:
--              aic32x4->sysclk = freq;
--              return 0;
--      }
--      printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n");
--      return -EINVAL;
-+      pll = devm_clk_get(component->dev, "pll");
-+      mclk = clk_get_parent(pll);
-+
-+      return clk_set_rate(mclk, freq);
- }
- static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
diff --git a/target/linux/brcm2708/patches-4.19/950-0354-ASoC-tlv320aic32x4-Only-enable-with-common-clock.patch b/target/linux/brcm2708/patches-4.19/950-0354-ASoC-tlv320aic32x4-Only-enable-with-common-clock.patch
new file mode 100644 (file)
index 0000000..d995353
--- /dev/null
@@ -0,0 +1,43 @@
+From 0ef20f96802fac1ce888a1e0b56e14b6b3fd4f72 Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@kernel.org>
+Date: Tue, 26 Mar 2019 13:10:13 +0000
+Subject: [PATCH] ASoC: tlv320aic32x4: Only enable with common clock
+
+commit 64f01d2b5ccc621c3aa66b82daf9154f5581f36a upstream.
+
+Some architectures do not yet support the common clock API at all but
+the tlv320aic32x4 driver now requires it.
+
+Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/Kconfig | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -170,8 +170,8 @@ config SND_SOC_ALL_CODECS
+       select SND_SOC_TAS5713 if I2C
+       select SND_SOC_TLV320AIC26 if SPI_MASTER
+       select SND_SOC_TLV320AIC31XX if I2C
+-      select SND_SOC_TLV320AIC32X4_I2C if I2C
+-      select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER
++      select SND_SOC_TLV320AIC32X4_I2C if I2C && COMMON_CLK
++      select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER && COMMON_CLK
+       select SND_SOC_TLV320AIC3X if I2C
+       select SND_SOC_TPA6130A2 if I2C
+       select SND_SOC_TLV320DAC33 if I2C
+@@ -1030,11 +1030,13 @@ config SND_SOC_TLV320AIC32X4
+ config SND_SOC_TLV320AIC32X4_I2C
+       tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
+       depends on I2C
++      depends on COMMON_CLK
+       select SND_SOC_TLV320AIC32X4
+ config SND_SOC_TLV320AIC32X4_SPI
+       tristate "Texas Instruments TLV320AIC32x4 audio CODECs - SPI"
+       depends on SPI_MASTER
++      depends on COMMON_CLK
+       select SND_SOC_TLV320AIC32X4
+ config SND_SOC_TLV320AIC3X
diff --git a/target/linux/brcm2708/patches-4.19/950-0354-ASoC-tlv320aic32x4-Remove-mclk-references.patch b/target/linux/brcm2708/patches-4.19/950-0354-ASoC-tlv320aic32x4-Remove-mclk-references.patch
deleted file mode 100644 (file)
index bee5852..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From 3c7bf08e6b6bdc2e6005aaa5e6aa6d12ce40d406 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:53 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Remove mclk references
-
-commit 78f2d58a289302e56a7def96a783a7686ebf27e2 upstream.
-
-mclk is not used by anything anymore.  Remove support for it.
-All that information now comes from the clock tree.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 7 -------
- 1 file changed, 7 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -53,7 +53,6 @@ struct aic32x4_priv {
-       u32 micpga_routing;
-       bool swapdacs;
-       int rstn_gpio;
--      struct clk *mclk;
-       const char *mclk_name;
-       struct regulator *supply_ldo;
-@@ -1191,12 +1190,6 @@ int aic32x4_probe(struct device *dev, st
-               aic32x4->mclk_name = "mclk";
-       }
--      aic32x4->mclk = devm_clk_get(dev, "mclk");
--      if (IS_ERR(aic32x4->mclk)) {
--              dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
--              return PTR_ERR(aic32x4->mclk);
--      }
--
-       ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
-       if (ret)
-               return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0355-ASoC-tlv320aic32x4-Allow-192000-Sample-Rate.patch b/target/linux/brcm2708/patches-4.19/950-0355-ASoC-tlv320aic32x4-Allow-192000-Sample-Rate.patch
deleted file mode 100644 (file)
index 15ded09..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From e54269cdeb78beb5131594de702daeecc2b05ec2 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:54 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Allow 192000 Sample Rate
-
-commit 6d56ee1550b8a81bc63c80051ff78d8d704b09ba upstream.
-
-The clocking and processing blocks are now properly set up to
-support 192000 sample rates.  Allow drivers to ask for that.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -859,7 +859,7 @@ static int aic32x4_set_bias_level(struct
-       return 0;
- }
--#define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
-+#define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000
- #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
-                        | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/target/linux/brcm2708/patches-4.19/950-0355-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch b/target/linux/brcm2708/patches-4.19/950-0355-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch
new file mode 100644 (file)
index 0000000..ba10100
--- /dev/null
@@ -0,0 +1,761 @@
+From c667b06f616d5dec68469ac73764abd5bcb1d694 Mon Sep 17 00:00:00 2001
+From: FERHAT Nicolas <contact@audiophonics.fr>
+Date: Fri, 5 Apr 2019 13:06:42 +0100
+Subject: [PATCH] Audiophonics I-Sabre 9038Q2M DAC driver
+
+Signed-off-by: Audiophonics <contact@audiophonics.fr>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   6 +
+ .../boot/dts/overlays/i-sabre-q2m-overlay.dts |  39 ++
+ sound/soc/bcm/Kconfig                         |   7 +
+ sound/soc/bcm/Makefile                        |   2 +
+ sound/soc/bcm/i-sabre-q2m.c                   | 157 +++++++
+ sound/soc/codecs/Kconfig                      |   5 +
+ sound/soc/codecs/Makefile                     |   2 +
+ sound/soc/codecs/i-sabre-codec.c              | 392 ++++++++++++++++++
+ sound/soc/codecs/i-sabre-codec.h              |  42 ++
+ 13 files changed, 656 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
+ create mode 100644 sound/soc/bcm/i-sabre-q2m.c
+ create mode 100644 sound/soc/codecs/i-sabre-codec.c
+ create mode 100644 sound/soc/codecs/i-sabre-codec.h
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -55,6 +55,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       hy28a.dtbo \
+       hy28b.dtbo \
+       hy28b-2017.dtbo \
++      i-sabre-q2m.dtbo \
+       i2c-bcm2708.dtbo \
+       i2c-gpio.dtbo \
+       i2c-mux.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -869,6 +869,12 @@ Params: speed                   Display
+         ledgpio                 GPIO used to control backlight
++Name:   i-sabre-q2m
++Info:   Configures the Audiophonics I-SABRE Q2M DAC
++Load:   dtoverlay=i-sabre-q2m
++Params: <None>
++
++
+ Name:   i2c-bcm2708
+ Info:   Fall back to the i2c_bcm2708 driver for the i2c_arm bus.
+ Load:   dtoverlay=i2c-bcm2708
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
+@@ -0,0 +1,39 @@
++// Definitions for I-Sabre Q2M
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2708";
++
++      fragment@0 {
++              target = <&sound>;
++              frag0: __overlay__ {
++                      compatible = "audiophonics,i-sabre-q2m";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      i-sabre-codec@48 {
++                              #sound-dai-cells = <0>;
++                              compatible = "audiophonics,i-sabre-codec";
++                              reg = <0x48>;
++                              status = "okay";
++                      };
++              };
++      };
++};
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -123,6 +123,13 @@ config SND_BCM2708_SOC_IQAUDIO_DIGI
+       help
+         Say Y or M if you want to add support for IQAudIO Digital IO board.
++config SND_BCM2708_SOC_I_SABRE_Q2M
++        tristate "Support for Audiophonics I-Sabre Q2M DAC"
++        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++        select SND_SOC_I_SABRE_CODEC
++        help
++        Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC
++
+ config SND_BCM2708_SOC_ADAU1977_ADC
+       tristate "Support for ADAU1977 ADC"
+       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -19,6 +19,7 @@ snd-soc-justboom-dac-objs := justboom-da
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
++ snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+ snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
+ snd-soc-audiosense-pi-objs := audiosense-pi.o
+@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DA
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
++ obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
+ obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
+--- /dev/null
++++ b/sound/soc/bcm/i-sabre-q2m.c
+@@ -0,0 +1,157 @@
++/*
++ * ASoC Driver for I-Sabre Q2M
++ *
++ * Author: Satoru Kawase
++ * Modified by: Xiao Qingyong
++ * Update kernel v4.18+ by : Audiophonics
++ *            Copyright 2018 Audiophonics
++ *
++ * 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/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <sound/core.h>
++#include <sound/soc.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++
++#include "../codecs/i-sabre-codec.h"
++
++
++static int snd_rpi_i_sabre_q2m_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_component *component = rtd->codec_dai->component;
++      unsigned int value;
++
++      /* Device ID */
++      value = snd_soc_component_read32(component, ISABRECODEC_REG_01);
++      dev_info(component->card->dev, "Audiophonics Device ID : %02X\n", value);
++
++      /* API revision */
++      value = snd_soc_component_read32(component, ISABRECODEC_REG_02);
++      dev_info(component->card->dev, "Audiophonics API revision : %02X\n", value);
++
++      return 0;
++}
++
++static int snd_rpi_i_sabre_q2m_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;
++      int bclk_ratio;
++
++      bclk_ratio = snd_pcm_format_physical_width(
++                      params_format(params)) * params_channels(params);
++      return snd_soc_dai_set_bclk_ratio(cpu_dai, bclk_ratio);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_i_sabre_q2m_ops = {
++      .hw_params = snd_rpi_i_sabre_q2m_hw_params,
++};
++
++
++static struct snd_soc_dai_link snd_rpi_i_sabre_q2m_dai[] = {
++      {
++              .name           = "I-Sabre Q2M",
++              .stream_name    = "I-Sabre Q2M DAC",
++              .cpu_dai_name   = "bcm2708-i2s.0",
++              .codec_dai_name = "i-sabre-codec-dai",
++              .platform_name  = "bcm2708-i2s.0",
++              .codec_name     = "i-sabre-codec-i2c.1-0048",
++              .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++                                              | SND_SOC_DAIFMT_CBS_CFS,
++              .init           = snd_rpi_i_sabre_q2m_init,
++              .ops            = &snd_rpi_i_sabre_q2m_ops,
++      }
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_i_sabre_q2m = {
++      .name      = "I-Sabre Q2M DAC",
++      .owner     = THIS_MODULE,
++      .dai_link  = snd_rpi_i_sabre_q2m_dai,
++      .num_links = ARRAY_SIZE(snd_rpi_i_sabre_q2m_dai)
++};
++
++
++static int snd_rpi_i_sabre_q2m_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++
++      snd_rpi_i_sabre_q2m.dev = &pdev->dev;
++      if (pdev->dev.of_node) {
++              struct device_node *i2s_node;
++              struct snd_soc_dai_link *dai;
++
++              dai = &snd_rpi_i_sabre_q2m_dai[0];
++              i2s_node = of_parse_phandle(pdev->dev.of_node,
++                                                      "i2s-controller", 0);
++              if (i2s_node) {
++                      dai->cpu_dai_name     = NULL;
++                      dai->cpu_of_node      = i2s_node;
++                      dai->platform_name    = NULL;
++                      dai->platform_of_node = i2s_node;
++              } else {
++                      dev_err(&pdev->dev,
++                          "Property 'i2s-controller' missing or invalid\n");
++                      return (-EINVAL);
++              }
++
++              dai->name        = "I-Sabre Q2M";
++              dai->stream_name = "I-Sabre Q2M DAC";
++              dai->dai_fmt     = SND_SOC_DAIFMT_I2S
++                                      | SND_SOC_DAIFMT_NB_NF
++                                      | SND_SOC_DAIFMT_CBS_CFS;
++      }
++
++      /* Wait for registering codec driver */
++      mdelay(50);
++
++      ret = snd_soc_register_card(&snd_rpi_i_sabre_q2m);
++      if (ret) {
++              dev_err(&pdev->dev,
++                      "snd_soc_register_card() failed: %d\n", ret);
++      }
++
++      return ret;
++}
++
++static int snd_rpi_i_sabre_q2m_remove(struct platform_device *pdev)
++{
++      return snd_soc_unregister_card(&snd_rpi_i_sabre_q2m);
++}
++
++static const struct of_device_id snd_rpi_i_sabre_q2m_of_match[] = {
++      { .compatible = "audiophonics,i-sabre-q2m", },
++      {}
++};
++MODULE_DEVICE_TABLE(of, snd_rpi_i_sabre_q2m_of_match);
++
++static struct platform_driver snd_rpi_i_sabre_q2m_driver = {
++      .driver = {
++              .name           = "snd-rpi-i-sabre-q2m",
++              .owner          = THIS_MODULE,
++              .of_match_table = snd_rpi_i_sabre_q2m_of_match,
++      },
++      .probe  = snd_rpi_i_sabre_q2m_probe,
++      .remove = snd_rpi_i_sabre_q2m_remove,
++};
++module_platform_driver(snd_rpi_i_sabre_q2m_driver);
++
++MODULE_DESCRIPTION("ASoC Driver for I-Sabre Q2M");
++MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
++MODULE_LICENSE("GPL");
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -85,6 +85,7 @@ config SND_SOC_ALL_CODECS
+       select SND_SOC_ICS43432
+       select SND_SOC_INNO_RK3036
+       select SND_SOC_ISABELLE if I2C
++      select SND_SOC_I_SABRE_CODEC if I2C
+       select SND_SOC_JZ4740_CODEC
+       select SND_SOC_LM4857 if I2C
+       select SND_SOC_LM49453 if I2C
+@@ -1322,4 +1323,8 @@ config SND_SOC_TPA6130A2
+       tristate "Texas Instruments TPA6130A2 headphone amplifier"
+       depends on I2C
++config SND_SOC_I_SABRE_CODEC
++      tristate "Audiophonics I-SABRE Codec"
++      depends on I2C
++
+ endmenu
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -81,6 +81,7 @@ snd-soc-hdac-hdmi-objs := hdac_hdmi.o
+ snd-soc-ics43432-objs := ics43432.o
+ snd-soc-inno-rk3036-objs := inno_rk3036.o
+ snd-soc-isabelle-objs := isabelle.o
++snd-soc-i-sabre-codec-objs := i-sabre-codec.o
+ snd-soc-jz4740-codec-objs := jz4740.o
+ snd-soc-l3-objs := l3.o
+ snd-soc-lm4857-objs := lm4857.o
+@@ -343,6 +344,7 @@ obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-s
+ obj-$(CONFIG_SND_SOC_ICS43432)        += snd-soc-ics43432.o
+ obj-$(CONFIG_SND_SOC_INNO_RK3036)     += snd-soc-inno-rk3036.o
+ obj-$(CONFIG_SND_SOC_ISABELLE)        += snd-soc-isabelle.o
++obj-$(CONFIG_SND_SOC_I_SABRE_CODEC)   += snd-soc-i-sabre-codec.o
+ obj-$(CONFIG_SND_SOC_JZ4740_CODEC)    += snd-soc-jz4740-codec.o
+ obj-$(CONFIG_SND_SOC_L3)      += snd-soc-l3.o
+ obj-$(CONFIG_SND_SOC_LM4857)  += snd-soc-lm4857.o
+--- /dev/null
++++ b/sound/soc/codecs/i-sabre-codec.c
+@@ -0,0 +1,392 @@
++/*
++ * Driver for I-Sabre Q2M
++ *
++ * Author: Satoru Kawase
++ * Modified by: Xiao Qingyong
++ * Modified by: JC BARBAUD (Mute)
++ * Update kernel v4.18+ by : Audiophonics
++ *            Copyright 2018 Audiophonics
++ *
++ * 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/init.h>
++#include <linux/module.h>
++#include <linux/regmap.h>
++#include <linux/i2c.h>
++#include <sound/soc.h>
++#include <sound/pcm_params.h>
++#include <sound/tlv.h>
++
++#include "i-sabre-codec.h"
++
++
++/* I-Sabre Q2M Codec Private Data */
++struct i_sabre_codec_priv {
++      struct regmap *regmap;
++      unsigned int fmt;
++};
++
++
++/* I-Sabre Q2M Codec Default Register Value */
++static const struct reg_default i_sabre_codec_reg_defaults[] = {
++      { ISABRECODEC_REG_10, 0x00 },
++      { ISABRECODEC_REG_20, 0x00 },
++      { ISABRECODEC_REG_21, 0x00 },
++      { ISABRECODEC_REG_22, 0x00 },
++      { ISABRECODEC_REG_24, 0x00 },
++};
++
++
++static bool i_sabre_codec_writeable(struct device *dev, unsigned int reg)
++{
++      switch (reg) {
++      case ISABRECODEC_REG_10:
++      case ISABRECODEC_REG_20:
++      case ISABRECODEC_REG_21:
++      case ISABRECODEC_REG_22:
++      case ISABRECODEC_REG_24:
++              return true;
++
++      default:
++              return false;
++      }
++}
++
++static bool i_sabre_codec_readable(struct device *dev, unsigned int reg)
++{
++      switch (reg) {
++      case ISABRECODEC_REG_01:
++      case ISABRECODEC_REG_02:
++      case ISABRECODEC_REG_10:
++      case ISABRECODEC_REG_20:
++      case ISABRECODEC_REG_21:
++      case ISABRECODEC_REG_22:
++      case ISABRECODEC_REG_24:
++              return true;
++
++      default:
++              return false;
++      }
++}
++
++static bool i_sabre_codec_volatile(struct device *dev, unsigned int reg)
++{
++      switch (reg) {
++      case ISABRECODEC_REG_01:
++      case ISABRECODEC_REG_02:
++              return true;
++
++      default:
++              return false;
++      }
++}
++
++
++/* Volume Scale */
++static const DECLARE_TLV_DB_SCALE(volume_tlv, -10000, 100, 0);
++
++
++/* Filter Type */
++static const char * const fir_filter_type_texts[] = {
++      "brick wall",
++      "corrected minimum phase fast",
++      "minimum phase slow",
++      "minimum phase fast",
++      "linear phase slow",
++      "linear phase fast",
++      "apodizing fast",
++};
++
++static SOC_ENUM_SINGLE_DECL(i_sabre_fir_filter_type_enum,
++                              ISABRECODEC_REG_22, 0, fir_filter_type_texts);
++
++
++/* I2S / SPDIF Select */
++static const char * const iis_spdif_sel_texts[] = {
++      "I2S",
++      "SPDIF",
++};
++
++static SOC_ENUM_SINGLE_DECL(i_sabre_iis_spdif_sel_enum,
++                              ISABRECODEC_REG_24, 0, iis_spdif_sel_texts);
++
++
++/* Control */
++static const struct snd_kcontrol_new i_sabre_codec_controls[] = {
++SOC_SINGLE_RANGE_TLV("Digital Playback Volume", ISABRECODEC_REG_20, 0, 0, 100, 1, volume_tlv),
++SOC_SINGLE("Digital Playback Switch", ISABRECODEC_REG_21, 0, 1, 1),
++SOC_ENUM("FIR Filter Type", i_sabre_fir_filter_type_enum),
++SOC_ENUM("I2S/SPDIF Select", i_sabre_iis_spdif_sel_enum),
++};
++
++
++static const u32 i_sabre_codec_dai_rates_slave[] = {
++      8000, 11025, 16000, 22050, 32000,
++      44100, 48000, 64000, 88200, 96000,
++      176400, 192000, 352800, 384000,
++      705600, 768000, 1411200, 1536000
++};
++
++static const struct snd_pcm_hw_constraint_list constraints_slave = {
++      .list  = i_sabre_codec_dai_rates_slave,
++      .count = ARRAY_SIZE(i_sabre_codec_dai_rates_slave),
++};
++
++static int i_sabre_codec_dai_startup_slave(
++              struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
++{
++      struct snd_soc_component *component = dai->component;
++      int ret;
++
++      ret = snd_pcm_hw_constraint_list(substream->runtime,
++                      0, SNDRV_PCM_HW_PARAM_RATE, &constraints_slave);
++      if (ret != 0) {
++              dev_err(component->card->dev, "Failed to setup rates constraints: %d\n", ret);
++      }
++
++      return ret;
++}
++
++static int i_sabre_codec_dai_startup(
++              struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
++{
++      struct snd_soc_component      *component = dai->component;
++      struct i_sabre_codec_priv *i_sabre_codec
++                                      = snd_soc_component_get_drvdata(component);
++
++      switch (i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++      case SND_SOC_DAIFMT_CBS_CFS:
++              return i_sabre_codec_dai_startup_slave(substream, dai);
++
++      default:
++              return (-EINVAL);
++      }
++}
++
++static int i_sabre_codec_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 i_sabre_codec_priv *i_sabre_codec
++                                      = snd_soc_component_get_drvdata(component);
++      unsigned int daifmt;
++      int format_width;
++
++      dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
++                      params_rate(params), params_channels(params));
++
++      /* Check I2S Format (Bit Size) */
++      format_width = snd_pcm_format_width(params_format(params));
++      if ((format_width != 32) && (format_width != 16)) {
++              dev_err(component->card->dev, "Bad frame size: %d\n",
++                              snd_pcm_format_width(params_format(params)));
++              return (-EINVAL);
++      }
++
++      /* Check Slave Mode */
++      daifmt = i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK;
++      if (daifmt != SND_SOC_DAIFMT_CBS_CFS) {
++              return (-EINVAL);
++      }
++
++      /* Notify Sampling Frequency  */
++      switch (params_rate(params))
++      {
++      case 44100:
++      case 48000:
++      case 88200:
++      case 96000:
++      case 176400:
++      case 192000:
++              snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x00);
++              break;
++
++      case 352800:
++      case 384000:
++      case 705600:
++      case 768000:
++      case 1411200:
++      case 1536000:
++              snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x01);
++              break;
++      }
++
++      return 0;
++}
++
++static int i_sabre_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
++{
++      struct snd_soc_component      *component = dai->component;
++      struct i_sabre_codec_priv *i_sabre_codec
++                                      = snd_soc_component_get_drvdata(component);
++
++      /* interface format */
++      switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++      case SND_SOC_DAIFMT_I2S:
++              break;
++
++      case SND_SOC_DAIFMT_RIGHT_J:
++      case SND_SOC_DAIFMT_LEFT_J:
++      default:
++              return (-EINVAL);
++      }
++
++      /* clock inversion */
++      if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
++              return (-EINVAL);
++      }
++
++      /* Set Audio Data Format */
++      i_sabre_codec->fmt = fmt;
++
++      return 0;
++}
++
++static int i_sabre_codec_dac_mute(struct snd_soc_dai *dai, int mute)
++{
++      struct snd_soc_component *component = dai->component;
++
++      if (mute) {
++              snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x01);
++      } else {
++              snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x00);
++      }
++
++      return 0;
++}
++
++
++static const struct snd_soc_dai_ops i_sabre_codec_dai_ops = {
++      .startup      = i_sabre_codec_dai_startup,
++      .hw_params    = i_sabre_codec_hw_params,
++      .set_fmt      = i_sabre_codec_set_fmt,
++      .digital_mute = i_sabre_codec_dac_mute,
++};
++
++static struct snd_soc_dai_driver i_sabre_codec_dai = {
++      .name = "i-sabre-codec-dai",
++      .playback = {
++              .stream_name  = "Playback",
++              .channels_min = 2,
++              .channels_max = 2,
++              .rates = SNDRV_PCM_RATE_CONTINUOUS,
++              .rate_min = 8000,
++              .rate_max = 1536000,
++              .formats      = SNDRV_PCM_FMTBIT_S16_LE
++                              | SNDRV_PCM_FMTBIT_S32_LE,
++      },
++      .ops = &i_sabre_codec_dai_ops,
++};
++
++static struct snd_soc_component_driver i_sabre_codec_codec_driver = {
++              .controls         = i_sabre_codec_controls,
++              .num_controls     = ARRAY_SIZE(i_sabre_codec_controls),
++};
++
++
++static const struct regmap_config i_sabre_codec_regmap = {
++      .reg_bits         = 8,
++      .val_bits         = 8,
++      .max_register     = ISABRECODEC_MAX_REG,
++
++      .reg_defaults     = i_sabre_codec_reg_defaults,
++      .num_reg_defaults = ARRAY_SIZE(i_sabre_codec_reg_defaults),
++
++      .writeable_reg    = i_sabre_codec_writeable,
++      .readable_reg     = i_sabre_codec_readable,
++      .volatile_reg     = i_sabre_codec_volatile,
++
++      .cache_type       = REGCACHE_RBTREE,
++};
++
++
++static int i_sabre_codec_probe(struct device *dev, struct regmap *regmap)
++{
++      struct i_sabre_codec_priv *i_sabre_codec;
++      int ret;
++
++      i_sabre_codec = devm_kzalloc(dev, sizeof(*i_sabre_codec), GFP_KERNEL);
++      if (!i_sabre_codec) {
++              dev_err(dev, "devm_kzalloc");
++              return (-ENOMEM);
++      }
++
++      i_sabre_codec->regmap = regmap;
++
++      dev_set_drvdata(dev, i_sabre_codec);
++
++      ret = snd_soc_register_component(dev,
++                      &i_sabre_codec_codec_driver, &i_sabre_codec_dai, 1);
++      if (ret != 0) {
++              dev_err(dev, "Failed to register CODEC: %d\n", ret);
++              return ret;
++      }
++
++      return 0;
++}
++
++static void i_sabre_codec_remove(struct device *dev)
++{
++      snd_soc_unregister_component(dev);
++}
++
++
++static int i_sabre_codec_i2c_probe(
++              struct i2c_client *i2c, const struct i2c_device_id *id)
++{
++      struct regmap *regmap;
++
++      regmap = devm_regmap_init_i2c(i2c, &i_sabre_codec_regmap);
++      if (IS_ERR(regmap)) {
++              return PTR_ERR(regmap);
++      }
++
++      return i_sabre_codec_probe(&i2c->dev, regmap);
++}
++
++static int i_sabre_codec_i2c_remove(struct i2c_client *i2c)
++{
++      i_sabre_codec_remove(&i2c->dev);
++
++      return 0;
++}
++
++
++static const struct i2c_device_id i_sabre_codec_i2c_id[] = {
++      { "i-sabre-codec", },
++      { }
++};
++MODULE_DEVICE_TABLE(i2c, i_sabre_codec_i2c_id);
++
++static const struct of_device_id i_sabre_codec_of_match[] = {
++      { .compatible = "audiophonics,i-sabre-codec", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, i_sabre_codec_of_match);
++
++static struct i2c_driver i_sabre_codec_i2c_driver = {
++      .driver = {
++              .name           = "i-sabre-codec-i2c",
++              .owner          = THIS_MODULE,
++              .of_match_table = of_match_ptr(i_sabre_codec_of_match),
++      },
++      .probe    = i_sabre_codec_i2c_probe,
++      .remove   = i_sabre_codec_i2c_remove,
++      .id_table = i_sabre_codec_i2c_id,
++};
++module_i2c_driver(i_sabre_codec_i2c_driver);
++
++
++MODULE_DESCRIPTION("ASoC I-Sabre Q2M codec driver");
++MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/sound/soc/codecs/i-sabre-codec.h
+@@ -0,0 +1,42 @@
++/*
++ * Driver for I-Sabre Q2M
++ *
++ * Author: Satoru Kawase
++ * Modified by: Xiao Qingyong
++ *      Copyright 2018 Audiophonics
++ *
++ * 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.
++ */
++
++#ifndef _SND_SOC_ISABRECODEC
++#define _SND_SOC_ISABRECODEC
++
++
++/* ISABRECODEC Register Address */
++#define ISABRECODEC_REG_01    0x01    /* Virtual Device ID  :  0x01 = es9038q2m */
++#define ISABRECODEC_REG_02    0x02    /* API revision       :  0x01 = Revision 01 */
++#define ISABRECODEC_REG_10    0x10    /* 0x01 = above 192kHz, 0x00 = otherwise */
++#define ISABRECODEC_REG_20    0x20    /* 0 - 100 (decimal value, 0 = min., 100 = max.) */
++#define ISABRECODEC_REG_21    0x21    /* 0x00 = Mute OFF, 0x01 = Mute ON */
++#define ISABRECODEC_REG_22    0x22    
++/*
++   0x00 = brick wall,
++   0x01 = corrected minimum phase fast,
++   0x02 = minimum phase slow,
++   0x03 = minimum phase fast,
++   0x04 = linear phase slow,
++   0x05 = linear phase fast,
++   0x06 = apodizing fast,
++*/
++//#define ISABRECODEC_REG_23  0x23    /* reserved */
++#define ISABRECODEC_REG_24    0x24    /* 0x00 = I2S, 0x01 = SPDIF */
++#define ISABRECODEC_MAX_REG   0x24    /* Maximum Register Number */
++
++#endif /* _SND_SOC_ISABRECODEC */
diff --git a/target/linux/brcm2708/patches-4.19/950-0356-ASoC-tlv320aic32x4-Change-author-s-name.patch b/target/linux/brcm2708/patches-4.19/950-0356-ASoC-tlv320aic32x4-Change-author-s-name.patch
new file mode 100644 (file)
index 0000000..8c4cdd5
--- /dev/null
@@ -0,0 +1,54 @@
+From 5942d9e650ce419236d5a7dc53c2513889ed3453 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:17:15 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Change author's name
+
+commit 7297ba6c74c5b9e78d8e936af82eecfcf7d32dfb upstream.
+
+The author of these files has changed her name.  Update
+instances in the code of her dead name to current legal
+name.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-i2c.c | 4 ++--
+ sound/soc/codecs/tlv320aic32x4-spi.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-i2c.c
++++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
+@@ -3,7 +3,7 @@
+  *
+  * Copyright 2011 NW Digital Radio
+  *
+- * Author: Jeremy McDermond <nh6z@nh6z.net>
++ * Author: Annaliese McDermond <nh6z@nh6z.net>
+  *
+  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+  *
+@@ -72,5 +72,5 @@ static struct i2c_driver aic32x4_i2c_dri
+ module_i2c_driver(aic32x4_i2c_driver);
+ MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C");
+-MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
++MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
+ MODULE_LICENSE("GPL");
+--- a/sound/soc/codecs/tlv320aic32x4-spi.c
++++ b/sound/soc/codecs/tlv320aic32x4-spi.c
+@@ -3,7 +3,7 @@
+  *
+  * Copyright 2011 NW Digital Radio
+  *
+- * Author: Jeremy McDermond <nh6z@nh6z.net>
++ * Author: Annaliese McDermond <nh6z@nh6z.net>
+  *
+  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+  *
+@@ -74,5 +74,5 @@ static struct spi_driver aic32x4_spi_dri
+ module_spi_driver(aic32x4_spi_driver);
+ MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI");
+-MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
++MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
+ MODULE_LICENSE("GPL");
diff --git a/target/linux/brcm2708/patches-4.19/950-0356-ASoC-tlv320aic32x4-Only-enable-with-common-clock.patch b/target/linux/brcm2708/patches-4.19/950-0356-ASoC-tlv320aic32x4-Only-enable-with-common-clock.patch
deleted file mode 100644 (file)
index d995353..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-From 0ef20f96802fac1ce888a1e0b56e14b6b3fd4f72 Mon Sep 17 00:00:00 2001
-From: Mark Brown <broonie@kernel.org>
-Date: Tue, 26 Mar 2019 13:10:13 +0000
-Subject: [PATCH] ASoC: tlv320aic32x4: Only enable with common clock
-
-commit 64f01d2b5ccc621c3aa66b82daf9154f5581f36a upstream.
-
-Some architectures do not yet support the common clock API at all but
-the tlv320aic32x4 driver now requires it.
-
-Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/Kconfig | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -170,8 +170,8 @@ config SND_SOC_ALL_CODECS
-       select SND_SOC_TAS5713 if I2C
-       select SND_SOC_TLV320AIC26 if SPI_MASTER
-       select SND_SOC_TLV320AIC31XX if I2C
--      select SND_SOC_TLV320AIC32X4_I2C if I2C
--      select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER
-+      select SND_SOC_TLV320AIC32X4_I2C if I2C && COMMON_CLK
-+      select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER && COMMON_CLK
-       select SND_SOC_TLV320AIC3X if I2C
-       select SND_SOC_TPA6130A2 if I2C
-       select SND_SOC_TLV320DAC33 if I2C
-@@ -1030,11 +1030,13 @@ config SND_SOC_TLV320AIC32X4
- config SND_SOC_TLV320AIC32X4_I2C
-       tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
-       depends on I2C
-+      depends on COMMON_CLK
-       select SND_SOC_TLV320AIC32X4
- config SND_SOC_TLV320AIC32X4_SPI
-       tristate "Texas Instruments TLV320AIC32x4 audio CODECs - SPI"
-       depends on SPI_MASTER
-+      depends on COMMON_CLK
-       select SND_SOC_TLV320AIC32X4
- config SND_SOC_TLV320AIC3X
diff --git a/target/linux/brcm2708/patches-4.19/950-0357-ASoC-tlv320aic32x4-Update-copyright-and-use-SPDX-ide.patch b/target/linux/brcm2708/patches-4.19/950-0357-ASoC-tlv320aic32x4-Update-copyright-and-use-SPDX-ide.patch
new file mode 100644 (file)
index 0000000..b967eda
--- /dev/null
@@ -0,0 +1,70 @@
+From 1ed86adfa457ecd9668f2541dabfebd3ee82d035 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:17:16 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Update copyright and use SPDX
+ identifier
+
+commit 8a1d95c393d971e624fc28f11516b0bc3a7fa706 upstream.
+
+Update the copyright dates and use the SPDX identifier instead
+of reciting the license.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-i2c.c | 14 ++------------
+ sound/soc/codecs/tlv320aic32x4-spi.c | 14 ++------------
+ 2 files changed, 4 insertions(+), 24 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-i2c.c
++++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
+@@ -1,21 +1,11 @@
+-/*
+- * linux/sound/soc/codecs/tlv320aic32x4-i2c.c
++/* SPDX-License-Identifier: GPL-2.0
+  *
+- * Copyright 2011 NW Digital Radio
++ * Copyright 2011-2019 NW Digital Radio
+  *
+  * Author: Annaliese McDermond <nh6z@nh6z.net>
+  *
+  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+  *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * 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/i2c.h>
+--- a/sound/soc/codecs/tlv320aic32x4-spi.c
++++ b/sound/soc/codecs/tlv320aic32x4-spi.c
+@@ -1,21 +1,11 @@
+-/*
+- * linux/sound/soc/codecs/tlv320aic32x4-spi.c
++/* SPDX-License-Identifier: GPL-2.0
+  *
+- * Copyright 2011 NW Digital Radio
++ * Copyright 2011-2019 NW Digital Radio
+  *
+  * Author: Annaliese McDermond <nh6z@nh6z.net>
+  *
+  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+  *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * 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/spi/spi.h>
diff --git a/target/linux/brcm2708/patches-4.19/950-0357-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch b/target/linux/brcm2708/patches-4.19/950-0357-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch
deleted file mode 100644 (file)
index ba10100..0000000
+++ /dev/null
@@ -1,761 +0,0 @@
-From c667b06f616d5dec68469ac73764abd5bcb1d694 Mon Sep 17 00:00:00 2001
-From: FERHAT Nicolas <contact@audiophonics.fr>
-Date: Fri, 5 Apr 2019 13:06:42 +0100
-Subject: [PATCH] Audiophonics I-Sabre 9038Q2M DAC driver
-
-Signed-off-by: Audiophonics <contact@audiophonics.fr>
----
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |   6 +
- .../boot/dts/overlays/i-sabre-q2m-overlay.dts |  39 ++
- sound/soc/bcm/Kconfig                         |   7 +
- sound/soc/bcm/Makefile                        |   2 +
- sound/soc/bcm/i-sabre-q2m.c                   | 157 +++++++
- sound/soc/codecs/Kconfig                      |   5 +
- sound/soc/codecs/Makefile                     |   2 +
- sound/soc/codecs/i-sabre-codec.c              | 392 ++++++++++++++++++
- sound/soc/codecs/i-sabre-codec.h              |  42 ++
- 13 files changed, 656 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
- create mode 100644 sound/soc/bcm/i-sabre-q2m.c
- create mode 100644 sound/soc/codecs/i-sabre-codec.c
- create mode 100644 sound/soc/codecs/i-sabre-codec.h
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -55,6 +55,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       hy28a.dtbo \
-       hy28b.dtbo \
-       hy28b-2017.dtbo \
-+      i-sabre-q2m.dtbo \
-       i2c-bcm2708.dtbo \
-       i2c-gpio.dtbo \
-       i2c-mux.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -869,6 +869,12 @@ Params: speed                   Display
-         ledgpio                 GPIO used to control backlight
-+Name:   i-sabre-q2m
-+Info:   Configures the Audiophonics I-SABRE Q2M DAC
-+Load:   dtoverlay=i-sabre-q2m
-+Params: <None>
-+
-+
- Name:   i2c-bcm2708
- Info:   Fall back to the i2c_bcm2708 driver for the i2c_arm bus.
- Load:   dtoverlay=i2c-bcm2708
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
-@@ -0,0 +1,39 @@
-+// Definitions for I-Sabre Q2M
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2708";
-+
-+      fragment@0 {
-+              target = <&sound>;
-+              frag0: __overlay__ {
-+                      compatible = "audiophonics,i-sabre-q2m";
-+                      i2s-controller = <&i2s>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      i-sabre-codec@48 {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "audiophonics,i-sabre-codec";
-+                              reg = <0x48>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+};
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -123,6 +123,13 @@ config SND_BCM2708_SOC_IQAUDIO_DIGI
-       help
-         Say Y or M if you want to add support for IQAudIO Digital IO board.
-+config SND_BCM2708_SOC_I_SABRE_Q2M
-+        tristate "Support for Audiophonics I-Sabre Q2M DAC"
-+        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+        select SND_SOC_I_SABRE_CODEC
-+        help
-+        Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC
-+
- config SND_BCM2708_SOC_ADAU1977_ADC
-       tristate "Support for ADAU1977 ADC"
-       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -19,6 +19,7 @@ snd-soc-justboom-dac-objs := justboom-da
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
-+ snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
- snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
- snd-soc-audiosense-pi-objs := audiosense-pi.o
-@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DA
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
-+ obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
- obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
---- /dev/null
-+++ b/sound/soc/bcm/i-sabre-q2m.c
-@@ -0,0 +1,157 @@
-+/*
-+ * ASoC Driver for I-Sabre Q2M
-+ *
-+ * Author: Satoru Kawase
-+ * Modified by: Xiao Qingyong
-+ * Update kernel v4.18+ by : Audiophonics
-+ *            Copyright 2018 Audiophonics
-+ *
-+ * 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/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/fs.h>
-+#include <asm/uaccess.h>
-+#include <sound/core.h>
-+#include <sound/soc.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+
-+#include "../codecs/i-sabre-codec.h"
-+
-+
-+static int snd_rpi_i_sabre_q2m_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      struct snd_soc_component *component = rtd->codec_dai->component;
-+      unsigned int value;
-+
-+      /* Device ID */
-+      value = snd_soc_component_read32(component, ISABRECODEC_REG_01);
-+      dev_info(component->card->dev, "Audiophonics Device ID : %02X\n", value);
-+
-+      /* API revision */
-+      value = snd_soc_component_read32(component, ISABRECODEC_REG_02);
-+      dev_info(component->card->dev, "Audiophonics API revision : %02X\n", value);
-+
-+      return 0;
-+}
-+
-+static int snd_rpi_i_sabre_q2m_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;
-+      int bclk_ratio;
-+
-+      bclk_ratio = snd_pcm_format_physical_width(
-+                      params_format(params)) * params_channels(params);
-+      return snd_soc_dai_set_bclk_ratio(cpu_dai, bclk_ratio);
-+}
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_i_sabre_q2m_ops = {
-+      .hw_params = snd_rpi_i_sabre_q2m_hw_params,
-+};
-+
-+
-+static struct snd_soc_dai_link snd_rpi_i_sabre_q2m_dai[] = {
-+      {
-+              .name           = "I-Sabre Q2M",
-+              .stream_name    = "I-Sabre Q2M DAC",
-+              .cpu_dai_name   = "bcm2708-i2s.0",
-+              .codec_dai_name = "i-sabre-codec-dai",
-+              .platform_name  = "bcm2708-i2s.0",
-+              .codec_name     = "i-sabre-codec-i2c.1-0048",
-+              .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+                                              | SND_SOC_DAIFMT_CBS_CFS,
-+              .init           = snd_rpi_i_sabre_q2m_init,
-+              .ops            = &snd_rpi_i_sabre_q2m_ops,
-+      }
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_i_sabre_q2m = {
-+      .name      = "I-Sabre Q2M DAC",
-+      .owner     = THIS_MODULE,
-+      .dai_link  = snd_rpi_i_sabre_q2m_dai,
-+      .num_links = ARRAY_SIZE(snd_rpi_i_sabre_q2m_dai)
-+};
-+
-+
-+static int snd_rpi_i_sabre_q2m_probe(struct platform_device *pdev)
-+{
-+      int ret = 0;
-+
-+      snd_rpi_i_sabre_q2m.dev = &pdev->dev;
-+      if (pdev->dev.of_node) {
-+              struct device_node *i2s_node;
-+              struct snd_soc_dai_link *dai;
-+
-+              dai = &snd_rpi_i_sabre_q2m_dai[0];
-+              i2s_node = of_parse_phandle(pdev->dev.of_node,
-+                                                      "i2s-controller", 0);
-+              if (i2s_node) {
-+                      dai->cpu_dai_name     = NULL;
-+                      dai->cpu_of_node      = i2s_node;
-+                      dai->platform_name    = NULL;
-+                      dai->platform_of_node = i2s_node;
-+              } else {
-+                      dev_err(&pdev->dev,
-+                          "Property 'i2s-controller' missing or invalid\n");
-+                      return (-EINVAL);
-+              }
-+
-+              dai->name        = "I-Sabre Q2M";
-+              dai->stream_name = "I-Sabre Q2M DAC";
-+              dai->dai_fmt     = SND_SOC_DAIFMT_I2S
-+                                      | SND_SOC_DAIFMT_NB_NF
-+                                      | SND_SOC_DAIFMT_CBS_CFS;
-+      }
-+
-+      /* Wait for registering codec driver */
-+      mdelay(50);
-+
-+      ret = snd_soc_register_card(&snd_rpi_i_sabre_q2m);
-+      if (ret) {
-+              dev_err(&pdev->dev,
-+                      "snd_soc_register_card() failed: %d\n", ret);
-+      }
-+
-+      return ret;
-+}
-+
-+static int snd_rpi_i_sabre_q2m_remove(struct platform_device *pdev)
-+{
-+      return snd_soc_unregister_card(&snd_rpi_i_sabre_q2m);
-+}
-+
-+static const struct of_device_id snd_rpi_i_sabre_q2m_of_match[] = {
-+      { .compatible = "audiophonics,i-sabre-q2m", },
-+      {}
-+};
-+MODULE_DEVICE_TABLE(of, snd_rpi_i_sabre_q2m_of_match);
-+
-+static struct platform_driver snd_rpi_i_sabre_q2m_driver = {
-+      .driver = {
-+              .name           = "snd-rpi-i-sabre-q2m",
-+              .owner          = THIS_MODULE,
-+              .of_match_table = snd_rpi_i_sabre_q2m_of_match,
-+      },
-+      .probe  = snd_rpi_i_sabre_q2m_probe,
-+      .remove = snd_rpi_i_sabre_q2m_remove,
-+};
-+module_platform_driver(snd_rpi_i_sabre_q2m_driver);
-+
-+MODULE_DESCRIPTION("ASoC Driver for I-Sabre Q2M");
-+MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
-+MODULE_LICENSE("GPL");
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -85,6 +85,7 @@ config SND_SOC_ALL_CODECS
-       select SND_SOC_ICS43432
-       select SND_SOC_INNO_RK3036
-       select SND_SOC_ISABELLE if I2C
-+      select SND_SOC_I_SABRE_CODEC if I2C
-       select SND_SOC_JZ4740_CODEC
-       select SND_SOC_LM4857 if I2C
-       select SND_SOC_LM49453 if I2C
-@@ -1322,4 +1323,8 @@ config SND_SOC_TPA6130A2
-       tristate "Texas Instruments TPA6130A2 headphone amplifier"
-       depends on I2C
-+config SND_SOC_I_SABRE_CODEC
-+      tristate "Audiophonics I-SABRE Codec"
-+      depends on I2C
-+
- endmenu
---- a/sound/soc/codecs/Makefile
-+++ b/sound/soc/codecs/Makefile
-@@ -81,6 +81,7 @@ snd-soc-hdac-hdmi-objs := hdac_hdmi.o
- snd-soc-ics43432-objs := ics43432.o
- snd-soc-inno-rk3036-objs := inno_rk3036.o
- snd-soc-isabelle-objs := isabelle.o
-+snd-soc-i-sabre-codec-objs := i-sabre-codec.o
- snd-soc-jz4740-codec-objs := jz4740.o
- snd-soc-l3-objs := l3.o
- snd-soc-lm4857-objs := lm4857.o
-@@ -343,6 +344,7 @@ obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-s
- obj-$(CONFIG_SND_SOC_ICS43432)        += snd-soc-ics43432.o
- obj-$(CONFIG_SND_SOC_INNO_RK3036)     += snd-soc-inno-rk3036.o
- obj-$(CONFIG_SND_SOC_ISABELLE)        += snd-soc-isabelle.o
-+obj-$(CONFIG_SND_SOC_I_SABRE_CODEC)   += snd-soc-i-sabre-codec.o
- obj-$(CONFIG_SND_SOC_JZ4740_CODEC)    += snd-soc-jz4740-codec.o
- obj-$(CONFIG_SND_SOC_L3)      += snd-soc-l3.o
- obj-$(CONFIG_SND_SOC_LM4857)  += snd-soc-lm4857.o
---- /dev/null
-+++ b/sound/soc/codecs/i-sabre-codec.c
-@@ -0,0 +1,392 @@
-+/*
-+ * Driver for I-Sabre Q2M
-+ *
-+ * Author: Satoru Kawase
-+ * Modified by: Xiao Qingyong
-+ * Modified by: JC BARBAUD (Mute)
-+ * Update kernel v4.18+ by : Audiophonics
-+ *            Copyright 2018 Audiophonics
-+ *
-+ * 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/init.h>
-+#include <linux/module.h>
-+#include <linux/regmap.h>
-+#include <linux/i2c.h>
-+#include <sound/soc.h>
-+#include <sound/pcm_params.h>
-+#include <sound/tlv.h>
-+
-+#include "i-sabre-codec.h"
-+
-+
-+/* I-Sabre Q2M Codec Private Data */
-+struct i_sabre_codec_priv {
-+      struct regmap *regmap;
-+      unsigned int fmt;
-+};
-+
-+
-+/* I-Sabre Q2M Codec Default Register Value */
-+static const struct reg_default i_sabre_codec_reg_defaults[] = {
-+      { ISABRECODEC_REG_10, 0x00 },
-+      { ISABRECODEC_REG_20, 0x00 },
-+      { ISABRECODEC_REG_21, 0x00 },
-+      { ISABRECODEC_REG_22, 0x00 },
-+      { ISABRECODEC_REG_24, 0x00 },
-+};
-+
-+
-+static bool i_sabre_codec_writeable(struct device *dev, unsigned int reg)
-+{
-+      switch (reg) {
-+      case ISABRECODEC_REG_10:
-+      case ISABRECODEC_REG_20:
-+      case ISABRECODEC_REG_21:
-+      case ISABRECODEC_REG_22:
-+      case ISABRECODEC_REG_24:
-+              return true;
-+
-+      default:
-+              return false;
-+      }
-+}
-+
-+static bool i_sabre_codec_readable(struct device *dev, unsigned int reg)
-+{
-+      switch (reg) {
-+      case ISABRECODEC_REG_01:
-+      case ISABRECODEC_REG_02:
-+      case ISABRECODEC_REG_10:
-+      case ISABRECODEC_REG_20:
-+      case ISABRECODEC_REG_21:
-+      case ISABRECODEC_REG_22:
-+      case ISABRECODEC_REG_24:
-+              return true;
-+
-+      default:
-+              return false;
-+      }
-+}
-+
-+static bool i_sabre_codec_volatile(struct device *dev, unsigned int reg)
-+{
-+      switch (reg) {
-+      case ISABRECODEC_REG_01:
-+      case ISABRECODEC_REG_02:
-+              return true;
-+
-+      default:
-+              return false;
-+      }
-+}
-+
-+
-+/* Volume Scale */
-+static const DECLARE_TLV_DB_SCALE(volume_tlv, -10000, 100, 0);
-+
-+
-+/* Filter Type */
-+static const char * const fir_filter_type_texts[] = {
-+      "brick wall",
-+      "corrected minimum phase fast",
-+      "minimum phase slow",
-+      "minimum phase fast",
-+      "linear phase slow",
-+      "linear phase fast",
-+      "apodizing fast",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(i_sabre_fir_filter_type_enum,
-+                              ISABRECODEC_REG_22, 0, fir_filter_type_texts);
-+
-+
-+/* I2S / SPDIF Select */
-+static const char * const iis_spdif_sel_texts[] = {
-+      "I2S",
-+      "SPDIF",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(i_sabre_iis_spdif_sel_enum,
-+                              ISABRECODEC_REG_24, 0, iis_spdif_sel_texts);
-+
-+
-+/* Control */
-+static const struct snd_kcontrol_new i_sabre_codec_controls[] = {
-+SOC_SINGLE_RANGE_TLV("Digital Playback Volume", ISABRECODEC_REG_20, 0, 0, 100, 1, volume_tlv),
-+SOC_SINGLE("Digital Playback Switch", ISABRECODEC_REG_21, 0, 1, 1),
-+SOC_ENUM("FIR Filter Type", i_sabre_fir_filter_type_enum),
-+SOC_ENUM("I2S/SPDIF Select", i_sabre_iis_spdif_sel_enum),
-+};
-+
-+
-+static const u32 i_sabre_codec_dai_rates_slave[] = {
-+      8000, 11025, 16000, 22050, 32000,
-+      44100, 48000, 64000, 88200, 96000,
-+      176400, 192000, 352800, 384000,
-+      705600, 768000, 1411200, 1536000
-+};
-+
-+static const struct snd_pcm_hw_constraint_list constraints_slave = {
-+      .list  = i_sabre_codec_dai_rates_slave,
-+      .count = ARRAY_SIZE(i_sabre_codec_dai_rates_slave),
-+};
-+
-+static int i_sabre_codec_dai_startup_slave(
-+              struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
-+{
-+      struct snd_soc_component *component = dai->component;
-+      int ret;
-+
-+      ret = snd_pcm_hw_constraint_list(substream->runtime,
-+                      0, SNDRV_PCM_HW_PARAM_RATE, &constraints_slave);
-+      if (ret != 0) {
-+              dev_err(component->card->dev, "Failed to setup rates constraints: %d\n", ret);
-+      }
-+
-+      return ret;
-+}
-+
-+static int i_sabre_codec_dai_startup(
-+              struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
-+{
-+      struct snd_soc_component      *component = dai->component;
-+      struct i_sabre_codec_priv *i_sabre_codec
-+                                      = snd_soc_component_get_drvdata(component);
-+
-+      switch (i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+      case SND_SOC_DAIFMT_CBS_CFS:
-+              return i_sabre_codec_dai_startup_slave(substream, dai);
-+
-+      default:
-+              return (-EINVAL);
-+      }
-+}
-+
-+static int i_sabre_codec_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 i_sabre_codec_priv *i_sabre_codec
-+                                      = snd_soc_component_get_drvdata(component);
-+      unsigned int daifmt;
-+      int format_width;
-+
-+      dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
-+                      params_rate(params), params_channels(params));
-+
-+      /* Check I2S Format (Bit Size) */
-+      format_width = snd_pcm_format_width(params_format(params));
-+      if ((format_width != 32) && (format_width != 16)) {
-+              dev_err(component->card->dev, "Bad frame size: %d\n",
-+                              snd_pcm_format_width(params_format(params)));
-+              return (-EINVAL);
-+      }
-+
-+      /* Check Slave Mode */
-+      daifmt = i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK;
-+      if (daifmt != SND_SOC_DAIFMT_CBS_CFS) {
-+              return (-EINVAL);
-+      }
-+
-+      /* Notify Sampling Frequency  */
-+      switch (params_rate(params))
-+      {
-+      case 44100:
-+      case 48000:
-+      case 88200:
-+      case 96000:
-+      case 176400:
-+      case 192000:
-+              snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x00);
-+              break;
-+
-+      case 352800:
-+      case 384000:
-+      case 705600:
-+      case 768000:
-+      case 1411200:
-+      case 1536000:
-+              snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x01);
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int i_sabre_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-+{
-+      struct snd_soc_component      *component = dai->component;
-+      struct i_sabre_codec_priv *i_sabre_codec
-+                                      = snd_soc_component_get_drvdata(component);
-+
-+      /* interface format */
-+      switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+      case SND_SOC_DAIFMT_I2S:
-+              break;
-+
-+      case SND_SOC_DAIFMT_RIGHT_J:
-+      case SND_SOC_DAIFMT_LEFT_J:
-+      default:
-+              return (-EINVAL);
-+      }
-+
-+      /* clock inversion */
-+      if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
-+              return (-EINVAL);
-+      }
-+
-+      /* Set Audio Data Format */
-+      i_sabre_codec->fmt = fmt;
-+
-+      return 0;
-+}
-+
-+static int i_sabre_codec_dac_mute(struct snd_soc_dai *dai, int mute)
-+{
-+      struct snd_soc_component *component = dai->component;
-+
-+      if (mute) {
-+              snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x01);
-+      } else {
-+              snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x00);
-+      }
-+
-+      return 0;
-+}
-+
-+
-+static const struct snd_soc_dai_ops i_sabre_codec_dai_ops = {
-+      .startup      = i_sabre_codec_dai_startup,
-+      .hw_params    = i_sabre_codec_hw_params,
-+      .set_fmt      = i_sabre_codec_set_fmt,
-+      .digital_mute = i_sabre_codec_dac_mute,
-+};
-+
-+static struct snd_soc_dai_driver i_sabre_codec_dai = {
-+      .name = "i-sabre-codec-dai",
-+      .playback = {
-+              .stream_name  = "Playback",
-+              .channels_min = 2,
-+              .channels_max = 2,
-+              .rates = SNDRV_PCM_RATE_CONTINUOUS,
-+              .rate_min = 8000,
-+              .rate_max = 1536000,
-+              .formats      = SNDRV_PCM_FMTBIT_S16_LE
-+                              | SNDRV_PCM_FMTBIT_S32_LE,
-+      },
-+      .ops = &i_sabre_codec_dai_ops,
-+};
-+
-+static struct snd_soc_component_driver i_sabre_codec_codec_driver = {
-+              .controls         = i_sabre_codec_controls,
-+              .num_controls     = ARRAY_SIZE(i_sabre_codec_controls),
-+};
-+
-+
-+static const struct regmap_config i_sabre_codec_regmap = {
-+      .reg_bits         = 8,
-+      .val_bits         = 8,
-+      .max_register     = ISABRECODEC_MAX_REG,
-+
-+      .reg_defaults     = i_sabre_codec_reg_defaults,
-+      .num_reg_defaults = ARRAY_SIZE(i_sabre_codec_reg_defaults),
-+
-+      .writeable_reg    = i_sabre_codec_writeable,
-+      .readable_reg     = i_sabre_codec_readable,
-+      .volatile_reg     = i_sabre_codec_volatile,
-+
-+      .cache_type       = REGCACHE_RBTREE,
-+};
-+
-+
-+static int i_sabre_codec_probe(struct device *dev, struct regmap *regmap)
-+{
-+      struct i_sabre_codec_priv *i_sabre_codec;
-+      int ret;
-+
-+      i_sabre_codec = devm_kzalloc(dev, sizeof(*i_sabre_codec), GFP_KERNEL);
-+      if (!i_sabre_codec) {
-+              dev_err(dev, "devm_kzalloc");
-+              return (-ENOMEM);
-+      }
-+
-+      i_sabre_codec->regmap = regmap;
-+
-+      dev_set_drvdata(dev, i_sabre_codec);
-+
-+      ret = snd_soc_register_component(dev,
-+                      &i_sabre_codec_codec_driver, &i_sabre_codec_dai, 1);
-+      if (ret != 0) {
-+              dev_err(dev, "Failed to register CODEC: %d\n", ret);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static void i_sabre_codec_remove(struct device *dev)
-+{
-+      snd_soc_unregister_component(dev);
-+}
-+
-+
-+static int i_sabre_codec_i2c_probe(
-+              struct i2c_client *i2c, const struct i2c_device_id *id)
-+{
-+      struct regmap *regmap;
-+
-+      regmap = devm_regmap_init_i2c(i2c, &i_sabre_codec_regmap);
-+      if (IS_ERR(regmap)) {
-+              return PTR_ERR(regmap);
-+      }
-+
-+      return i_sabre_codec_probe(&i2c->dev, regmap);
-+}
-+
-+static int i_sabre_codec_i2c_remove(struct i2c_client *i2c)
-+{
-+      i_sabre_codec_remove(&i2c->dev);
-+
-+      return 0;
-+}
-+
-+
-+static const struct i2c_device_id i_sabre_codec_i2c_id[] = {
-+      { "i-sabre-codec", },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(i2c, i_sabre_codec_i2c_id);
-+
-+static const struct of_device_id i_sabre_codec_of_match[] = {
-+      { .compatible = "audiophonics,i-sabre-codec", },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(of, i_sabre_codec_of_match);
-+
-+static struct i2c_driver i_sabre_codec_i2c_driver = {
-+      .driver = {
-+              .name           = "i-sabre-codec-i2c",
-+              .owner          = THIS_MODULE,
-+              .of_match_table = of_match_ptr(i_sabre_codec_of_match),
-+      },
-+      .probe    = i_sabre_codec_i2c_probe,
-+      .remove   = i_sabre_codec_i2c_remove,
-+      .id_table = i_sabre_codec_i2c_id,
-+};
-+module_i2c_driver(i_sabre_codec_i2c_driver);
-+
-+
-+MODULE_DESCRIPTION("ASoC I-Sabre Q2M codec driver");
-+MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/sound/soc/codecs/i-sabre-codec.h
-@@ -0,0 +1,42 @@
-+/*
-+ * Driver for I-Sabre Q2M
-+ *
-+ * Author: Satoru Kawase
-+ * Modified by: Xiao Qingyong
-+ *      Copyright 2018 Audiophonics
-+ *
-+ * 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.
-+ */
-+
-+#ifndef _SND_SOC_ISABRECODEC
-+#define _SND_SOC_ISABRECODEC
-+
-+
-+/* ISABRECODEC Register Address */
-+#define ISABRECODEC_REG_01    0x01    /* Virtual Device ID  :  0x01 = es9038q2m */
-+#define ISABRECODEC_REG_02    0x02    /* API revision       :  0x01 = Revision 01 */
-+#define ISABRECODEC_REG_10    0x10    /* 0x01 = above 192kHz, 0x00 = otherwise */
-+#define ISABRECODEC_REG_20    0x20    /* 0 - 100 (decimal value, 0 = min., 100 = max.) */
-+#define ISABRECODEC_REG_21    0x21    /* 0x00 = Mute OFF, 0x01 = Mute ON */
-+#define ISABRECODEC_REG_22    0x22    
-+/*
-+   0x00 = brick wall,
-+   0x01 = corrected minimum phase fast,
-+   0x02 = minimum phase slow,
-+   0x03 = minimum phase fast,
-+   0x04 = linear phase slow,
-+   0x05 = linear phase fast,
-+   0x06 = apodizing fast,
-+*/
-+//#define ISABRECODEC_REG_23  0x23    /* reserved */
-+#define ISABRECODEC_REG_24    0x24    /* 0x00 = I2S, 0x01 = SPDIF */
-+#define ISABRECODEC_MAX_REG   0x24    /* Maximum Register Number */
-+
-+#endif /* _SND_SOC_ISABRECODEC */
diff --git a/target/linux/brcm2708/patches-4.19/950-0358-ASoC-tlv320aic32x4-Add-Switch-for-Setting-Common-Mod.patch b/target/linux/brcm2708/patches-4.19/950-0358-ASoC-tlv320aic32x4-Add-Switch-for-Setting-Common-Mod.patch
new file mode 100644 (file)
index 0000000..1d57237
--- /dev/null
@@ -0,0 +1,40 @@
+From 0962637c67a56c1ae42ccb14c9e71c62f4aa1403 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:01:54 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Add Switch for Setting Common
+ Mode Voltage
+
+commit 44ceee847e27c828f2f1ef4e400e6bc0c8d04de3 upstream.
+
+Add a switch for setting common mode voltage.  This can allow
+for higher drive levels on the amplifier outputs.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -242,6 +242,12 @@ static DECLARE_TLV_DB_SCALE(tlv_driver_g
+ /* -12dB min, 0.5dB steps */
+ static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
++static const char * const lo_cm_text[] = {
++      "Full Chip", "1.65V",
++};
++
++static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
++
+ static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
+       SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
+                       AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
+@@ -255,6 +261,7 @@ static const struct snd_kcontrol_new aic
+                       AIC32X4_HPRGAIN, 6, 0x01, 1),
+       SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN,
+                       AIC32X4_LORGAIN, 6, 0x01, 1),
++      SOC_ENUM("LO Playback Common Mode Switch", lo_cm_enum),
+       SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL,
+                       AIC32X4_RMICPGAVOL, 7, 0x01, 1),
diff --git a/target/linux/brcm2708/patches-4.19/950-0358-ASoC-tlv320aic32x4-Change-author-s-name.patch b/target/linux/brcm2708/patches-4.19/950-0358-ASoC-tlv320aic32x4-Change-author-s-name.patch
deleted file mode 100644 (file)
index 8c4cdd5..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From 5942d9e650ce419236d5a7dc53c2513889ed3453 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:17:15 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Change author's name
-
-commit 7297ba6c74c5b9e78d8e936af82eecfcf7d32dfb upstream.
-
-The author of these files has changed her name.  Update
-instances in the code of her dead name to current legal
-name.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-i2c.c | 4 ++--
- sound/soc/codecs/tlv320aic32x4-spi.c | 4 ++--
- 2 files changed, 4 insertions(+), 4 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-i2c.c
-+++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
-@@ -3,7 +3,7 @@
-  *
-  * Copyright 2011 NW Digital Radio
-  *
-- * Author: Jeremy McDermond <nh6z@nh6z.net>
-+ * Author: Annaliese McDermond <nh6z@nh6z.net>
-  *
-  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
-  *
-@@ -72,5 +72,5 @@ static struct i2c_driver aic32x4_i2c_dri
- module_i2c_driver(aic32x4_i2c_driver);
- MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C");
--MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
-+MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
- MODULE_LICENSE("GPL");
---- a/sound/soc/codecs/tlv320aic32x4-spi.c
-+++ b/sound/soc/codecs/tlv320aic32x4-spi.c
-@@ -3,7 +3,7 @@
-  *
-  * Copyright 2011 NW Digital Radio
-  *
-- * Author: Jeremy McDermond <nh6z@nh6z.net>
-+ * Author: Annaliese McDermond <nh6z@nh6z.net>
-  *
-  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
-  *
-@@ -74,5 +74,5 @@ static struct spi_driver aic32x4_spi_dri
- module_spi_driver(aic32x4_spi_driver);
- MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI");
--MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
-+MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
- MODULE_LICENSE("GPL");
diff --git a/target/linux/brcm2708/patches-4.19/950-0359-ASoC-tlv320aic32x4-Add-Playback-PowerTune-Controls.patch b/target/linux/brcm2708/patches-4.19/950-0359-ASoC-tlv320aic32x4-Add-Playback-PowerTune-Controls.patch
new file mode 100644 (file)
index 0000000..9851425
--- /dev/null
@@ -0,0 +1,52 @@
+From 6e5099288c946037476abd1488e4c7ab6b818e2b Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:01:55 -0700
+Subject: [PATCH] ASoC: tlv320aic32x4: Add Playback PowerTune Controls
+
+commit d3e6e374566e1154820a9a3dc82f7eef646fcf95 upstream.
+
+PowerTune controls the power level of the chip.  On playback this
+indirectly controls things like the gain of the various output
+amplifiers.  This can allow for the decrease of output levels
+from the codec.  This adds controls for those power levels to
+the driver.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 9 +++++++++
+ sound/soc/codecs/tlv320aic32x4.h | 2 ++
+ 2 files changed, 11 insertions(+)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -248,9 +248,18 @@ static const char * const lo_cm_text[] =
+ static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
++static const char * const ptm_text[] = {
++      "P3", "P2", "P1",
++};
++
++static SOC_ENUM_SINGLE_DECL(l_ptm_enum, AIC32X4_LPLAYBACK, 2, ptm_text);
++static SOC_ENUM_SINGLE_DECL(r_ptm_enum, AIC32X4_RPLAYBACK, 2, ptm_text);
++
+ static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
+       SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
+                       AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
++      SOC_ENUM("DAC Left Playback PowerTune Switch", l_ptm_enum),
++      SOC_ENUM("DAC Right Playback PowerTune Switch", r_ptm_enum),
+       SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
+                       AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0,
+                       tlv_driver_gain),
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -78,6 +78,8 @@ int aic32x4_register_clocks(struct devic
+ #define AIC32X4_PWRCFG                AIC32X4_REG(1, 1)
+ #define AIC32X4_LDOCTL                AIC32X4_REG(1, 2)
++#define AIC32X4_LPLAYBACK     AIC32X4_REG(1, 3)
++#define AIC32X4_RPLAYBACK     AIC32X4_REG(1, 4)
+ #define AIC32X4_OUTPWRCTL     AIC32X4_REG(1, 9)
+ #define AIC32X4_CMMODE                AIC32X4_REG(1, 10)
+ #define AIC32X4_HPLROUTE      AIC32X4_REG(1, 12)
diff --git a/target/linux/brcm2708/patches-4.19/950-0359-ASoC-tlv320aic32x4-Update-copyright-and-use-SPDX-ide.patch b/target/linux/brcm2708/patches-4.19/950-0359-ASoC-tlv320aic32x4-Update-copyright-and-use-SPDX-ide.patch
deleted file mode 100644 (file)
index b967eda..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-From 1ed86adfa457ecd9668f2541dabfebd3ee82d035 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:17:16 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Update copyright and use SPDX
- identifier
-
-commit 8a1d95c393d971e624fc28f11516b0bc3a7fa706 upstream.
-
-Update the copyright dates and use the SPDX identifier instead
-of reciting the license.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-i2c.c | 14 ++------------
- sound/soc/codecs/tlv320aic32x4-spi.c | 14 ++------------
- 2 files changed, 4 insertions(+), 24 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-i2c.c
-+++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
-@@ -1,21 +1,11 @@
--/*
-- * linux/sound/soc/codecs/tlv320aic32x4-i2c.c
-+/* SPDX-License-Identifier: GPL-2.0
-  *
-- * Copyright 2011 NW Digital Radio
-+ * Copyright 2011-2019 NW Digital Radio
-  *
-  * Author: Annaliese McDermond <nh6z@nh6z.net>
-  *
-  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
-  *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * 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/i2c.h>
---- a/sound/soc/codecs/tlv320aic32x4-spi.c
-+++ b/sound/soc/codecs/tlv320aic32x4-spi.c
-@@ -1,21 +1,11 @@
--/*
-- * linux/sound/soc/codecs/tlv320aic32x4-spi.c
-+/* SPDX-License-Identifier: GPL-2.0
-  *
-- * Copyright 2011 NW Digital Radio
-+ * Copyright 2011-2019 NW Digital Radio
-  *
-  * Author: Annaliese McDermond <nh6z@nh6z.net>
-  *
-  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
-  *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * 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/spi/spi.h>
diff --git a/target/linux/brcm2708/patches-4.19/950-0360-ASoC-tlv320aic32x4-Add-Switch-for-Setting-Common-Mod.patch b/target/linux/brcm2708/patches-4.19/950-0360-ASoC-tlv320aic32x4-Add-Switch-for-Setting-Common-Mod.patch
deleted file mode 100644 (file)
index 1d57237..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From 0962637c67a56c1ae42ccb14c9e71c62f4aa1403 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:01:54 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Add Switch for Setting Common
- Mode Voltage
-
-commit 44ceee847e27c828f2f1ef4e400e6bc0c8d04de3 upstream.
-
-Add a switch for setting common mode voltage.  This can allow
-for higher drive levels on the amplifier outputs.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -242,6 +242,12 @@ static DECLARE_TLV_DB_SCALE(tlv_driver_g
- /* -12dB min, 0.5dB steps */
- static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
-+static const char * const lo_cm_text[] = {
-+      "Full Chip", "1.65V",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
-+
- static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
-       SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
-                       AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
-@@ -255,6 +261,7 @@ static const struct snd_kcontrol_new aic
-                       AIC32X4_HPRGAIN, 6, 0x01, 1),
-       SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN,
-                       AIC32X4_LORGAIN, 6, 0x01, 1),
-+      SOC_ENUM("LO Playback Common Mode Switch", lo_cm_enum),
-       SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL,
-                       AIC32X4_RMICPGAVOL, 7, 0x01, 1),
diff --git a/target/linux/brcm2708/patches-4.19/950-0360-dtoverlays-Add-Support-for-the-UDRC-DRAWS.patch b/target/linux/brcm2708/patches-4.19/950-0360-dtoverlays-Add-Support-for-the-UDRC-DRAWS.patch
new file mode 100644 (file)
index 0000000..ecc637c
--- /dev/null
@@ -0,0 +1,445 @@
+From 1d3aeba25b10d1ed2b5ae4cf0b535d821539a531 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Sun, 17 Mar 2019 16:48:36 -0700
+Subject: [PATCH] dtoverlays: Add Support for the UDRC/DRAWS
+
+Adds a new overlay to support the Northwest Digital Radio
+DRAWS and UDRC HATs.  See http://nwdigitalradio.com.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+---
+ arch/arm/boot/dts/overlays/Makefile          |   2 +
+ arch/arm/boot/dts/overlays/README            |  59 ++++++
+ arch/arm/boot/dts/overlays/draws-overlay.dts | 200 +++++++++++++++++++
+ arch/arm/boot/dts/overlays/udrc-overlay.dts  | 128 ++++++++++++
+ 4 files changed, 389 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/draws-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/udrc-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -29,6 +29,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       dionaudio-loco-v2.dtbo \
+       dpi18.dtbo \
+       dpi24.dtbo \
++      draws.dtbo \
+       dwc-otg.dtbo \
+       dwc2.dtbo \
+       enc28j60.dtbo \
+@@ -146,6 +147,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       tpm-slb9670.dtbo \
+       uart0.dtbo \
+       uart1.dtbo \
++      udrc.dtbo \
+       upstream.dtbo \
+       upstream-aux-interrupt.dtbo \
+       vc4-fkms-v3d.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -531,6 +531,59 @@ Load:   dtoverlay=dpi24
+ Params: <None>
++Name:   draws
++Info:   Configures the NW Digital Radio DRAWS Hat
++
++        The board includes an ADC to measure various board values and also
++        provides two analog user inputs on the expansion header.  The ADC
++        can be configured for various sample rates and gain values to adjust
++        the input range.  Tables describing the two parameters follow.
++
++        ADC Gain Values:
++            0 = +/- 6.144V
++            1 = +/- 4.096V
++            2 = +/- 2.048V
++            3 = +/- 1.024V
++            4 = +/- 0.512V
++            5 = +/- 0.256V
++            6 = +/- 0.256V
++            7 = +/- 0.256V
++
++        ADC Datarate Values:
++            0 = 128sps
++            1 = 250sps
++            2 = 490sps
++            3 = 920sps
++            4 = 1600sps (default)
++            5 = 2400sps
++            6 = 3300sps
++            7 = 3300sps
++Load:   dtoverlay=draws,<param>=<val>
++Params: draws_adc_ch4_gain      Sets the full scale resolution of the ADCs
++                                input voltage sensor (default 1)
++
++        draws_adc_ch4_datarate  Sets the datarate of the ADCs input voltage
++                                sensor
++
++        draws_adc_ch5_gain      Sets the full scale resolution of the ADCs
++                                5V rail voltage sensor (default 1)
++
++        draws_adc_ch5_datarate  Sets the datarate of the ADCs 4V rail voltage
++                                sensor
++
++        draws_adc_ch6_gain      Sets the full scale resolution of the ADCs
++                                AIN2 input (default 2)
++
++        draws_adc_ch6_datarate  Sets the datarate of the ADCs AIN2 input
++
++        draws_adc_ch7_gain      Sets the full scale resolution of the ADCs
++                                AIN3 input (default 2)
++
++        draws_adc_ch7_datarate  Sets the datarate of the ADCs AIN3 input
++
++        alsaname                Name of the ALSA audio device (default "draws")
++
++
+ Name:   dwc-otg
+ Info:   Selects the dwc_otg USB controller driver which has fiq support. This
+         is the default on all except the Pi Zero which defaults to dwc2.
+@@ -2117,6 +2170,12 @@ Params: txd1_pin                GPIO pin
+         rxd1_pin                GPIO pin for RXD1 (15, 33 or 41 - default 15)
++Name:   udrc
++Info:   Configures the NW Digital Radio UDRC Hat
++Load:   dtoverlay=udrc,<param>=<val>
++Params: alsaname                Name of the ALSA audio device (default "udrc")
++
++
+ Name:   upstream
+ Info:   Allow usage of downstream .dtb with upstream kernel. Comprises
+         vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
+@@ -0,0 +1,200 @@
++#include <dt-bindings/clock/bcm2835.h>
++/*
++ * Device tree overlay for the DRAWS Hardware
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++    fragment@0 {
++        target = <&i2s>;
++        __overlay__ {
++            status = "okay";
++        };
++    };
++
++    fragment@1 {
++        target-path = "/";
++        __overlay__ {
++            regulators {
++                compatible = "simple-bus";
++                #address-cells = <1>;
++                #size-cells = <0>;
++
++                udrc0_ldoin: udrc0_ldoin {
++                    compatible = "regulator-fixed";
++                    regulator-name = "ldoin";
++                    regulator-min-microvolt = <3300000>;
++                    regulator-max-microvolt = <3300000>;
++                    regulator-always-on;
++                };
++            };
++
++            pps: pps {
++                compatible = "pps-gpio";
++                pinctrl-names = "default";
++                pinctrl-0 = <&pps_pins>;
++                gpios = <&gpio 7 0>;
++                status = "okay";
++            };
++        };
++    };
++
++    fragment@2 {
++        target = <&i2c_arm>;
++        __overlay__ {
++            #address-cells = <1>;
++            #size-cells = <0>;
++            status = "okay";
++
++            tlv320aic32x4: tlv320aic32x4@18 {
++                compatible = "ti,tlv320aic32x4";
++                reg = <0x18>;
++                #sound-dai-cells = <0>;
++                status = "okay";
++
++                clocks = <&clocks BCM2835_CLOCK_GP0>;
++                clock-names = "mclk";
++                assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
++                assigned-clock-rates = <25000000>;
++
++                pinctrl-names = "default";
++                pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
++
++                reset-gpios = <&gpio 13 0>;
++
++                iov-supply = <&udrc0_ldoin>;
++                ldoin-supply = <&udrc0_ldoin>;
++            };
++
++            sc16is752: sc16is752@50 {
++                compatible = "nxp,sc16is752";
++                reg = <0x50>;
++                clocks = <&sc16is752_clk>;
++                interrupt-parent = <&gpio>;
++                interrupts = <17 2>; /* IRQ_TYPE_EDGE_FALLING */
++
++                pinctrl-names = "default";
++                pinctrl-0 = <&sc16is752_irq>;
++
++                sc16is752_clk: sc16is752_clk {
++                    compatible = "fixed-clock";
++                    #clock-cells = <0>;
++                    clock-frequency = <1843200>;
++                };
++            };
++
++            tla2024: tla2024@48 {
++                compatible = "ti,ads1015";
++                reg = <0x48>;
++                #address-cells = <1>;
++                #size-cells = <0>;
++
++                adc_ch4: channel@4 {
++                    reg = <4>;
++                    ti,gain = <1>;
++                    ti,datarate = <4>;
++                };
++
++                adc_ch5: channel@5 {
++                    reg = <5>;
++                    ti,gain = <1>;
++                    ti,datarate = <4>;
++                };
++
++                adc_ch6: channel@6 {
++                    reg = <6>;
++                    ti,gain = <2>;
++                    ti,datarate = <4>;
++                };
++
++                adc_ch7: channel@7 {
++                    reg = <7>;
++                    ti,gain = <2>;
++                    ti,datarate = <4>;
++                };
++            };
++        };
++    };
++
++    fragment@3 {
++        target = <&sound>;
++        snd: __overlay__ {
++            compatible = "simple-audio-card";
++            i2s-controller = <&i2s>;
++            status = "okay";
++
++            simple-audio-card,name = "draws";
++            simple-audio-card,format = "i2s";
++
++            simple-audio-card,bitclock-master = <&dailink0_master>;
++            simple-audio-card,frame-master = <&dailink0_master>;
++
++            simple-audio-card,widgets =
++                "Line", "Line In",
++                "Line", "Line Out";
++
++            simple-audio-card,routing =
++                "IN1_R", "Line In",
++                "IN1_L", "Line In",
++                "CM_L", "Line In",
++                "CM_R", "Line In",
++                "Line Out", "LOR",
++                "Line Out", "LOL";
++
++            dailink0_master: simple-audio-card,cpu {
++                sound-dai = <&i2s>;
++            };
++
++            simple-audio-card,codec {
++                sound-dai = <&tlv320aic32x4>;
++            };
++        };
++    };
++
++    fragment@4 {
++        target = <&gpio>;
++        __overlay__ {
++            gpclk0_pin: gpclk0_pin {
++                brcm,pins = <4>;
++                brcm,function = <4>;
++            };
++
++            aic3204_reset: aic3204_reset {
++                brcm,pins = <13>;
++                brcm,function = <1>;
++                brcm,pull = <1>;
++            };
++
++            aic3204_gpio: aic3204_gpio {
++                brcm,pins = <26>;
++            };
++
++            sc16is752_irq: sc16is752_irq {
++                brcm,pins = <17>;
++                brcm,function = <0>;
++                brcm,pull = <2>;
++            };
++
++            pps_pins: pps_pins {
++                brcm,pins = <7>;
++                brcm,function = <0>;
++                brcm,pull = <0>;
++            };
++        };
++    };
++
++    __overrides__ {
++        draws_adc_ch4_gain = <&adc_ch4>,"ti,gain:0";
++        draws_adc_ch4_datarate = <&adc_ch4>,"ti,datarate:0";
++        draws_adc_ch5_gain = <&adc_ch5>,"ti,gain:0";
++        draws_adc_ch5_datarate = <&adc_ch5>,"ti,datarate:0";
++        draws_adc_ch6_gain = <&adc_ch6>,"ti,gain:0";
++        draws_adc_ch6_datarate = <&adc_ch6>,"ti,datarate:0";
++        draws_adc_ch7_gain = <&adc_ch7>,"ti,gain:0";
++        draws_adc_ch7_datarate = <&adc_ch7>,"ti,datarate:0";
++        alsaname = <&snd>, "simple-audio-card,name";
++    };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
+@@ -0,0 +1,128 @@
++#include <dt-bindings/clock/bcm2835.h>
++/*
++ * Device tree overlay for the Universal Digital Radio Controller
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++    fragment@0 {
++        target = <&i2s>;
++        __overlay__ {
++            clocks = <&clocks BCM2835_CLOCK_PCM>;
++            clock-names = "pcm";
++            status = "okay";
++        };
++    };
++
++    fragment@1 {
++        target-path = "/";
++        __overlay__ {
++            regulators {
++                compatible = "simple-bus";
++                #address-cells = <1>;
++                #size-cells = <0>;
++
++                udrc0_ldoin: udrc0_ldoin {
++                    compatible = "regulator-fixed";
++                    regulator-name = "ldoin";
++                    regulator-min-microvolt = <3300000>;
++                    regulator-max-microvolt = <3300000>;
++                    regulator-always-on;
++                };
++            };
++        };
++    };
++
++    fragment@2 {
++        target = <&i2c1>;
++        __overlay__ {
++            #address-cells = <1>;
++            #size-cells = <0>;
++            status = "okay";
++            clocks = <&clocks BCM2835_CLOCK_VPU>;
++            clock-frequency = <400000>;
++
++            tlv320aic32x4: tlv320aic32x4@18 {
++                compatible = "ti,tlv320aic32x4";
++                #sound-dai-cells = <0>;
++                reg = <0x18>;
++                status = "okay";
++
++                clocks = <&clocks BCM2835_CLOCK_GP0>;
++                clock-names = "mclk";
++                assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
++                assigned-clock-rates = <25000000>;
++
++                pinctrl-names = "default";
++                pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
++
++                reset-gpios = <&gpio 13 0>;
++
++                iov-supply = <&udrc0_ldoin>;
++                ldoin-supply = <&udrc0_ldoin>;
++            };
++        };
++    };
++
++    fragment@3 {
++        target = <&sound>;
++        snd: __overlay__ {
++            compatible = "simple-audio-card";
++            i2s-controller = <&i2s>;
++            status = "okay";
++
++            simple-audio-card,name = "udrc";
++            simple-audio-card,format = "i2s";
++
++            simple-audio-card,bitclock-master = <&dailink0_master>;
++            simple-audio-card,frame-master = <&dailink0_master>;
++
++            simple-audio-card,widgets =
++                "Line", "Line In",
++                "Line", "Line Out";
++
++            simple-audio-card,routing =
++                "IN1_R", "Line In",
++                "IN1_L", "Line In",
++                "CM_L", "Line In",
++                "CM_R", "Line In",
++                "Line Out", "LOR",
++                "Line Out", "LOL";
++
++            dailink0_master: simple-audio-card,cpu {
++                sound-dai = <&i2s>;
++            };
++
++            simple-audio-card,codec {
++                sound-dai = <&tlv320aic32x4>;
++            };
++        };
++    };
++
++    fragment@4 {
++        target = <&gpio>;
++        __overlay__ {
++            gpclk0_pin: gpclk0_pin {
++                brcm,pins = <4>;
++                brcm,function = <4>;
++            };
++
++            aic3204_reset: aic3204_reset {
++                brcm,pins = <13>;
++                brcm,function = <1>;
++                brcm,pull = <1>;
++            };
++
++            aic3204_gpio: aic3204_gpio {
++                brcm,pins = <26>;
++            };
++        };
++    };
++
++    __overrides__ {
++        alsaname = <&snd>, "simple-audio-card,name";
++    };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0361-ASoC-tlv320aic32x4-Add-Playback-PowerTune-Controls.patch b/target/linux/brcm2708/patches-4.19/950-0361-ASoC-tlv320aic32x4-Add-Playback-PowerTune-Controls.patch
deleted file mode 100644 (file)
index 9851425..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 6e5099288c946037476abd1488e4c7ab6b818e2b Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:01:55 -0700
-Subject: [PATCH] ASoC: tlv320aic32x4: Add Playback PowerTune Controls
-
-commit d3e6e374566e1154820a9a3dc82f7eef646fcf95 upstream.
-
-PowerTune controls the power level of the chip.  On playback this
-indirectly controls things like the gain of the various output
-amplifiers.  This can allow for the decrease of output levels
-from the codec.  This adds controls for those power levels to
-the driver.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 9 +++++++++
- sound/soc/codecs/tlv320aic32x4.h | 2 ++
- 2 files changed, 11 insertions(+)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -248,9 +248,18 @@ static const char * const lo_cm_text[] =
- static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
-+static const char * const ptm_text[] = {
-+      "P3", "P2", "P1",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(l_ptm_enum, AIC32X4_LPLAYBACK, 2, ptm_text);
-+static SOC_ENUM_SINGLE_DECL(r_ptm_enum, AIC32X4_RPLAYBACK, 2, ptm_text);
-+
- static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
-       SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
-                       AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
-+      SOC_ENUM("DAC Left Playback PowerTune Switch", l_ptm_enum),
-+      SOC_ENUM("DAC Right Playback PowerTune Switch", r_ptm_enum),
-       SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
-                       AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0,
-                       tlv_driver_gain),
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -78,6 +78,8 @@ int aic32x4_register_clocks(struct devic
- #define AIC32X4_PWRCFG                AIC32X4_REG(1, 1)
- #define AIC32X4_LDOCTL                AIC32X4_REG(1, 2)
-+#define AIC32X4_LPLAYBACK     AIC32X4_REG(1, 3)
-+#define AIC32X4_RPLAYBACK     AIC32X4_REG(1, 4)
- #define AIC32X4_OUTPWRCTL     AIC32X4_REG(1, 9)
- #define AIC32X4_CMMODE                AIC32X4_REG(1, 10)
- #define AIC32X4_HPLROUTE      AIC32X4_REG(1, 12)
diff --git a/target/linux/brcm2708/patches-4.19/950-0361-dwc_otg-only-do_split-when-we-actually-need-to-do-a-.patch b/target/linux/brcm2708/patches-4.19/950-0361-dwc_otg-only-do_split-when-we-actually-need-to-do-a-.patch
new file mode 100644 (file)
index 0000000..d2a9973
--- /dev/null
@@ -0,0 +1,55 @@
+From 0c988aed71773be4481b886ccf03c40a52f57cdb Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Mon, 8 Apr 2019 12:45:23 +0100
+Subject: [PATCH] dwc_otg: only do_split when we actually need to do a
+ split
+
+The previous test would fail if the root port was in fullspeed mode
+and there was a hub between the FS device and the root port. While
+the transfer worked, the schedule mangling performed for high-speed
+split transfers would break leading to an 8ms polling interval.
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+@@ -167,8 +167,10 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+       char *speed, *type;
+       int dev_speed;
+       uint32_t hub_addr, hub_port;
++      hprt0_data_t hprt;
+       dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
++      hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
+       /* Initialize QH */
+       qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
+@@ -191,9 +193,8 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+       qh->nak_frame = 0xffff;
+-      if (((dev_speed == USB_SPEED_LOW) ||
+-           (dev_speed == USB_SPEED_FULL)) &&
+-          (hub_addr != 0 && hub_addr != 1)) {
++      if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED &&
++                      dev_speed != USB_SPEED_HIGH) {
+               DWC_DEBUGPL(DBG_HCD,
+                           "QH init: EP %d: TT found at hub addr %d, for port %d\n",
+                           dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
+@@ -204,7 +205,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+       if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
+               /* Compute scheduling parameters once and save them. */
+-              hprt0_data_t hprt;
+               /** @todo Account for split transfers in the bus time. */
+               int bytecount =
+@@ -219,7 +219,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+                                                   SCHEDULE_SLOP);
+               qh->interval = urb->interval;
+-              hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
+               if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) {
+                       if (dev_speed == USB_SPEED_LOW ||
+                                       dev_speed == USB_SPEED_FULL) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch b/target/linux/brcm2708/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch
new file mode 100644 (file)
index 0000000..84c99ff
--- /dev/null
@@ -0,0 +1,490 @@
+From 9c823e2ee1ec1b815b8ec29c231b112c5e397202 Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:42:17 +0200
+Subject: [PATCH] Input: ili210x - fetch touchscreen geometry from DT
+
+commit f67cc3e927d8414ad3872e046764534ea1f5db0d upstream
+
+Fetching the geometry from the ILI251x registers seems unreliable and
+sometimes returns all zeroes. Add support for fetching the geometry and
+axis inversion from DT instead.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ drivers/input/touchscreen/ili210x.c | 321 +++++++++++++++++-----------
+ 1 file changed, 194 insertions(+), 127 deletions(-)
+
+--- a/drivers/input/touchscreen/ili210x.c
++++ b/drivers/input/touchscreen/ili210x.c
+@@ -4,11 +4,15 @@
+ #include <linux/slab.h>
+ #include <linux/input.h>
+ #include <linux/input/mt.h>
++#include <linux/input/touchscreen.h>
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+-#include <linux/input/ili210x.h>
++#include <linux/gpio/consumer.h>
++#include <linux/of_device.h>
++#include <asm/unaligned.h>
+-#define MAX_TOUCHES           2
++#define ILI210X_TOUCHES               2
++#define ILI251X_TOUCHES               10
+ #define DEFAULT_POLL_PERIOD   20
+ /* Touchscreen commands */
+@@ -17,41 +21,32 @@
+ #define REG_FIRMWARE_VERSION  0x40
+ #define REG_CALIBRATE         0xcc
+-struct finger {
+-      u8 x_low;
+-      u8 x_high;
+-      u8 y_low;
+-      u8 y_high;
+-} __packed;
+-
+-struct touchdata {
+-      u8 status;
+-      struct finger finger[MAX_TOUCHES];
+-} __packed;
+-
+-struct panel_info {
+-      struct finger finger_max;
+-      u8 xchannel_num;
+-      u8 ychannel_num;
+-} __packed;
+-
+ struct firmware_version {
+       u8 id;
+       u8 major;
+       u8 minor;
+ } __packed;
++enum ili2xxx_model {
++      MODEL_ILI210X,
++      MODEL_ILI251X,
++};
++
+ struct ili210x {
+       struct i2c_client *client;
+       struct input_dev *input;
+-      bool (*get_pendown_state)(void);
+       unsigned int poll_period;
+       struct delayed_work dwork;
++      struct gpio_desc *reset_gpio;
++      struct touchscreen_properties prop;
++      enum ili2xxx_model model;
++      unsigned int max_touches;
+ };
+ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
+                           size_t len)
+ {
++      struct ili210x *priv = i2c_get_clientdata(client);
+       struct i2c_msg msg[2] = {
+               {
+                       .addr   = client->addr,
+@@ -67,7 +62,38 @@ static int ili210x_read_reg(struct i2c_c
+               }
+       };
+-      if (i2c_transfer(client->adapter, msg, 2) != 2) {
++      if (priv->model == MODEL_ILI251X) {
++              if (i2c_transfer(client->adapter, msg, 1) != 1) {
++                      dev_err(&client->dev, "i2c transfer failed\n");
++                      return -EIO;
++              }
++
++              usleep_range(5000, 5500);
++
++              if (i2c_transfer(client->adapter, msg + 1, 1) != 1) {
++                      dev_err(&client->dev, "i2c transfer failed\n");
++                      return -EIO;
++              }
++      } else {
++              if (i2c_transfer(client->adapter, msg, 2) != 2) {
++                      dev_err(&client->dev, "i2c transfer failed\n");
++                      return -EIO;
++              }
++      }
++
++      return 0;
++}
++
++static int ili210x_read(struct i2c_client *client, void *buf, size_t len)
++{
++      struct i2c_msg msg = {
++              .addr   = client->addr,
++              .flags  = I2C_M_RD,
++              .len    = len,
++              .buf    = buf,
++      };
++
++      if (i2c_transfer(client->adapter, &msg, 1) != 1) {
+               dev_err(&client->dev, "i2c transfer failed\n");
+               return -EIO;
+       }
+@@ -75,42 +101,72 @@ static int ili210x_read_reg(struct i2c_c
+       return 0;
+ }
+-static void ili210x_report_events(struct input_dev *input,
+-                                const struct touchdata *touchdata)
++static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
++                                      unsigned int finger,
++                                      unsigned int *x, unsigned int *y)
+ {
+-      int i;
+-      bool touch;
+-      unsigned int x, y;
+-      const struct finger *finger;
++      if (finger >= ILI210X_TOUCHES)
++              return false;
+-      for (i = 0; i < MAX_TOUCHES; i++) {
+-              input_mt_slot(input, i);
++      if (touchdata[0] & BIT(finger))
++              return false;
+-              finger = &touchdata->finger[i];
++      *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
++      *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
+-              touch = touchdata->status & (1 << i);
+-              input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+-              if (touch) {
+-                      x = finger->x_low | (finger->x_high << 8);
+-                      y = finger->y_low | (finger->y_high << 8);
++      return true;
++}
++
++static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
++                                      unsigned int finger,
++                                      unsigned int *x, unsigned int *y)
++{
++      if (finger >= ILI251X_TOUCHES)
++              return false;
++
++      *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
++      if (!(*x & BIT(15)))    /* Touch indication */
++              return false;
++
++      *x &= 0x3fff;
++      *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
++
++      return true;
++}
++
++static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
++{
++      struct input_dev *input = priv->input;
++      int i;
++      bool contact = false, touch = false;
++      unsigned int x = 0, y = 0;
+-                      input_report_abs(input, ABS_MT_POSITION_X, x);
+-                      input_report_abs(input, ABS_MT_POSITION_Y, y);
++      for (i = 0; i < priv->max_touches; i++) {
++              if (priv->model == MODEL_ILI210X) {
++                      touch = ili210x_touchdata_to_coords(priv, touchdata,
++                                                          i, &x, &y);
++              } else if (priv->model == MODEL_ILI251X) {
++                      touch = ili251x_touchdata_to_coords(priv, touchdata,
++                                                          i, &x, &y);
++                      if (touch)
++                              contact = true;
+               }
++
++              input_mt_slot(input, i);
++              input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
++              if (!touch)
++                      continue;
++              touchscreen_report_pos(input, &priv->prop, x, y,
++                                     true);
+       }
+       input_mt_report_pointer_emulation(input, false);
+       input_sync(input);
+-}
+-static bool get_pendown_state(const struct ili210x *priv)
+-{
+-      bool state = false;
+-
+-      if (priv->get_pendown_state)
+-              state = priv->get_pendown_state();
++      if (priv->model == MODEL_ILI210X)
++              contact = touchdata[0] & 0xf3;
+-      return state;
++      return contact;
+ }
+ static void ili210x_work(struct work_struct *work)
+@@ -118,20 +174,29 @@ static void ili210x_work(struct work_str
+       struct ili210x *priv = container_of(work, struct ili210x,
+                                           dwork.work);
+       struct i2c_client *client = priv->client;
+-      struct touchdata touchdata;
+-      int error;
++      u8 touchdata[64] = { 0 };
++      bool touch;
++      int error = -EINVAL;
++
++      if (priv->model == MODEL_ILI210X) {
++              error = ili210x_read_reg(client, REG_TOUCHDATA,
++                                       touchdata, sizeof(touchdata));
++      } else if (priv->model == MODEL_ILI251X) {
++              error = ili210x_read_reg(client, REG_TOUCHDATA,
++                                       touchdata, 31);
++              if (!error && touchdata[0] == 2)
++                      error = ili210x_read(client, &touchdata[31], 20);
++      }
+-      error = ili210x_read_reg(client, REG_TOUCHDATA,
+-                               &touchdata, sizeof(touchdata));
+       if (error) {
+               dev_err(&client->dev,
+                       "Unable to get touchdata, err = %d\n", error);
+               return;
+       }
+-      ili210x_report_events(priv->input, &touchdata);
++      touch = ili210x_report_events(priv, touchdata);
+-      if ((touchdata.status & 0xf3) || get_pendown_state(priv))
++      if (touch)
+               schedule_delayed_work(&priv->dwork,
+                                     msecs_to_jiffies(priv->poll_period));
+ }
+@@ -180,30 +245,76 @@ static const struct attribute_group ili2
+       .attrs = ili210x_attributes,
+ };
++static void ili210x_power_down(void *data)
++{
++      struct gpio_desc *reset_gpio = data;
++
++      gpiod_set_value_cansleep(reset_gpio, 1);
++}
++
++static void ili210x_cancel_work(void *data)
++{
++      struct ili210x *priv = data;
++
++      cancel_delayed_work_sync(&priv->dwork);
++}
++
+ static int ili210x_i2c_probe(struct i2c_client *client,
+                                      const struct i2c_device_id *id)
+ {
+       struct device *dev = &client->dev;
+-      const struct ili210x_platform_data *pdata = dev_get_platdata(dev);
+       struct ili210x *priv;
++      struct gpio_desc *reset_gpio;
+       struct input_dev *input;
+-      struct panel_info panel;
+       struct firmware_version firmware;
+-      int xmax, ymax;
++      enum ili2xxx_model model;
+       int error;
+-      dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
++      model = (enum ili2xxx_model)id->driver_data;
+-      if (!pdata) {
+-              dev_err(dev, "No platform data!\n");
+-              return -EINVAL;
+-      }
++      dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
+       if (client->irq <= 0) {
+               dev_err(dev, "No IRQ!\n");
+               return -EINVAL;
+       }
++      reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
++      if (IS_ERR(reset_gpio))
++              return PTR_ERR(reset_gpio);
++
++      if (reset_gpio) {
++              error = devm_add_action_or_reset(dev, ili210x_power_down,
++                                               reset_gpio);
++              if (error)
++                      return error;
++
++              usleep_range(50, 100);
++              gpiod_set_value_cansleep(reset_gpio, 0);
++              msleep(100);
++      }
++
++      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      input = devm_input_allocate_device(dev);
++      if (!input)
++              return -ENOMEM;
++
++      priv->client = client;
++      priv->input = input;
++      priv->poll_period = DEFAULT_POLL_PERIOD;
++      INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
++      priv->reset_gpio = reset_gpio;
++      priv->model = model;
++      if (model == MODEL_ILI210X)
++              priv->max_touches = ILI210X_TOUCHES;
++      if (model == MODEL_ILI251X)
++              priv->max_touches = ILI251X_TOUCHES;
++
++      i2c_set_clientdata(client, priv);
++
+       /* Get firmware version */
+       error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
+                                &firmware, sizeof(firmware));
+@@ -213,70 +324,40 @@ static int ili210x_i2c_probe(struct i2c_
+               return error;
+       }
+-      /* get panel info */
+-      error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
+-      if (error) {
+-              dev_err(dev, "Failed to get panel information, err: %d\n",
+-                      error);
+-              return error;
+-      }
+-
+-      xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
+-      ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
+-
+-      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+-      input = input_allocate_device();
+-      if (!priv || !input) {
+-              error = -ENOMEM;
+-              goto err_free_mem;
+-      }
+-
+-      priv->client = client;
+-      priv->input = input;
+-      priv->get_pendown_state = pdata->get_pendown_state;
+-      priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD;
+-      INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
+-
+       /* Setup input device */
+       input->name = "ILI210x Touchscreen";
+       input->id.bustype = BUS_I2C;
+       input->dev.parent = dev;
+-      __set_bit(EV_SYN, input->evbit);
+-      __set_bit(EV_KEY, input->evbit);
+-      __set_bit(EV_ABS, input->evbit);
+-      __set_bit(BTN_TOUCH, input->keybit);
+-
+-      /* Single touch */
+-      input_set_abs_params(input, ABS_X, 0, xmax, 0, 0);
+-      input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
+-
+       /* Multi touch */
+-      input_mt_init_slots(input, MAX_TOUCHES, 0);
+-      input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
+-      input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
++      input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
++      input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
++      touchscreen_parse_properties(input, true, &priv->prop);
++      input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
+-      i2c_set_clientdata(client, priv);
++      error = devm_add_action(dev, ili210x_cancel_work, priv);
++      if (error)
++              return error;
+-      error = request_irq(client->irq, ili210x_irq, pdata->irq_flags,
+-                          client->name, priv);
++      error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
++                               client->name, priv);
+       if (error) {
+               dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
+                       error);
+-              goto err_free_mem;
++              return error;
+       }
+-      error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
++      error = devm_device_add_group(dev, &ili210x_attr_group);
+       if (error) {
+               dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
+                       error);
+-              goto err_free_irq;
++              return error;
+       }
+       error = input_register_device(priv->input);
+       if (error) {
+               dev_err(dev, "Cannot register input device, err: %d\n", error);
+-              goto err_remove_sysfs;
++              return error;
+       }
+       device_init_wakeup(dev, 1);
+@@ -286,28 +367,6 @@ static int ili210x_i2c_probe(struct i2c_
+               client->irq, firmware.id, firmware.major, firmware.minor);
+       return 0;
+-
+-err_remove_sysfs:
+-      sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
+-err_free_irq:
+-      free_irq(client->irq, priv);
+-err_free_mem:
+-      input_free_device(input);
+-      kfree(priv);
+-      return error;
+-}
+-
+-static int ili210x_i2c_remove(struct i2c_client *client)
+-{
+-      struct ili210x *priv = i2c_get_clientdata(client);
+-
+-      sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
+-      free_irq(priv->client->irq, priv);
+-      cancel_delayed_work_sync(&priv->dwork);
+-      input_unregister_device(priv->input);
+-      kfree(priv);
+-
+-      return 0;
+ }
+ static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
+@@ -334,19 +393,27 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
+                        ili210x_i2c_suspend, ili210x_i2c_resume);
+ static const struct i2c_device_id ili210x_i2c_id[] = {
+-      { "ili210x", 0 },
++      { "ili210x", MODEL_ILI210X },
++      { "ili251x", MODEL_ILI251X },
+       { }
+ };
+ MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
++static const struct of_device_id ili210x_dt_ids[] = {
++      { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
++      { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
++      { },
++};
++MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
++
+ static struct i2c_driver ili210x_ts_driver = {
+       .driver = {
+               .name = "ili210x_i2c",
+               .pm = &ili210x_i2c_pm,
++              .of_match_table = ili210x_dt_ids,
+       },
+       .id_table = ili210x_i2c_id,
+       .probe = ili210x_i2c_probe,
+-      .remove = ili210x_i2c_remove,
+ };
+ module_i2c_driver(ili210x_ts_driver);
diff --git a/target/linux/brcm2708/patches-4.19/950-0362-dtoverlays-Add-Support-for-the-UDRC-DRAWS.patch b/target/linux/brcm2708/patches-4.19/950-0362-dtoverlays-Add-Support-for-the-UDRC-DRAWS.patch
deleted file mode 100644 (file)
index ecc637c..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-From 1d3aeba25b10d1ed2b5ae4cf0b535d821539a531 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Sun, 17 Mar 2019 16:48:36 -0700
-Subject: [PATCH] dtoverlays: Add Support for the UDRC/DRAWS
-
-Adds a new overlay to support the Northwest Digital Radio
-DRAWS and UDRC HATs.  See http://nwdigitalradio.com.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
----
- arch/arm/boot/dts/overlays/Makefile          |   2 +
- arch/arm/boot/dts/overlays/README            |  59 ++++++
- arch/arm/boot/dts/overlays/draws-overlay.dts | 200 +++++++++++++++++++
- arch/arm/boot/dts/overlays/udrc-overlay.dts  | 128 ++++++++++++
- 4 files changed, 389 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/draws-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/udrc-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -29,6 +29,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       dionaudio-loco-v2.dtbo \
-       dpi18.dtbo \
-       dpi24.dtbo \
-+      draws.dtbo \
-       dwc-otg.dtbo \
-       dwc2.dtbo \
-       enc28j60.dtbo \
-@@ -146,6 +147,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       tpm-slb9670.dtbo \
-       uart0.dtbo \
-       uart1.dtbo \
-+      udrc.dtbo \
-       upstream.dtbo \
-       upstream-aux-interrupt.dtbo \
-       vc4-fkms-v3d.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -531,6 +531,59 @@ Load:   dtoverlay=dpi24
- Params: <None>
-+Name:   draws
-+Info:   Configures the NW Digital Radio DRAWS Hat
-+
-+        The board includes an ADC to measure various board values and also
-+        provides two analog user inputs on the expansion header.  The ADC
-+        can be configured for various sample rates and gain values to adjust
-+        the input range.  Tables describing the two parameters follow.
-+
-+        ADC Gain Values:
-+            0 = +/- 6.144V
-+            1 = +/- 4.096V
-+            2 = +/- 2.048V
-+            3 = +/- 1.024V
-+            4 = +/- 0.512V
-+            5 = +/- 0.256V
-+            6 = +/- 0.256V
-+            7 = +/- 0.256V
-+
-+        ADC Datarate Values:
-+            0 = 128sps
-+            1 = 250sps
-+            2 = 490sps
-+            3 = 920sps
-+            4 = 1600sps (default)
-+            5 = 2400sps
-+            6 = 3300sps
-+            7 = 3300sps
-+Load:   dtoverlay=draws,<param>=<val>
-+Params: draws_adc_ch4_gain      Sets the full scale resolution of the ADCs
-+                                input voltage sensor (default 1)
-+
-+        draws_adc_ch4_datarate  Sets the datarate of the ADCs input voltage
-+                                sensor
-+
-+        draws_adc_ch5_gain      Sets the full scale resolution of the ADCs
-+                                5V rail voltage sensor (default 1)
-+
-+        draws_adc_ch5_datarate  Sets the datarate of the ADCs 4V rail voltage
-+                                sensor
-+
-+        draws_adc_ch6_gain      Sets the full scale resolution of the ADCs
-+                                AIN2 input (default 2)
-+
-+        draws_adc_ch6_datarate  Sets the datarate of the ADCs AIN2 input
-+
-+        draws_adc_ch7_gain      Sets the full scale resolution of the ADCs
-+                                AIN3 input (default 2)
-+
-+        draws_adc_ch7_datarate  Sets the datarate of the ADCs AIN3 input
-+
-+        alsaname                Name of the ALSA audio device (default "draws")
-+
-+
- Name:   dwc-otg
- Info:   Selects the dwc_otg USB controller driver which has fiq support. This
-         is the default on all except the Pi Zero which defaults to dwc2.
-@@ -2117,6 +2170,12 @@ Params: txd1_pin                GPIO pin
-         rxd1_pin                GPIO pin for RXD1 (15, 33 or 41 - default 15)
-+Name:   udrc
-+Info:   Configures the NW Digital Radio UDRC Hat
-+Load:   dtoverlay=udrc,<param>=<val>
-+Params: alsaname                Name of the ALSA audio device (default "udrc")
-+
-+
- Name:   upstream
- Info:   Allow usage of downstream .dtb with upstream kernel. Comprises
-         vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
-@@ -0,0 +1,200 @@
-+#include <dt-bindings/clock/bcm2835.h>
-+/*
-+ * Device tree overlay for the DRAWS Hardware
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+    fragment@0 {
-+        target = <&i2s>;
-+        __overlay__ {
-+            status = "okay";
-+        };
-+    };
-+
-+    fragment@1 {
-+        target-path = "/";
-+        __overlay__ {
-+            regulators {
-+                compatible = "simple-bus";
-+                #address-cells = <1>;
-+                #size-cells = <0>;
-+
-+                udrc0_ldoin: udrc0_ldoin {
-+                    compatible = "regulator-fixed";
-+                    regulator-name = "ldoin";
-+                    regulator-min-microvolt = <3300000>;
-+                    regulator-max-microvolt = <3300000>;
-+                    regulator-always-on;
-+                };
-+            };
-+
-+            pps: pps {
-+                compatible = "pps-gpio";
-+                pinctrl-names = "default";
-+                pinctrl-0 = <&pps_pins>;
-+                gpios = <&gpio 7 0>;
-+                status = "okay";
-+            };
-+        };
-+    };
-+
-+    fragment@2 {
-+        target = <&i2c_arm>;
-+        __overlay__ {
-+            #address-cells = <1>;
-+            #size-cells = <0>;
-+            status = "okay";
-+
-+            tlv320aic32x4: tlv320aic32x4@18 {
-+                compatible = "ti,tlv320aic32x4";
-+                reg = <0x18>;
-+                #sound-dai-cells = <0>;
-+                status = "okay";
-+
-+                clocks = <&clocks BCM2835_CLOCK_GP0>;
-+                clock-names = "mclk";
-+                assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
-+                assigned-clock-rates = <25000000>;
-+
-+                pinctrl-names = "default";
-+                pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
-+
-+                reset-gpios = <&gpio 13 0>;
-+
-+                iov-supply = <&udrc0_ldoin>;
-+                ldoin-supply = <&udrc0_ldoin>;
-+            };
-+
-+            sc16is752: sc16is752@50 {
-+                compatible = "nxp,sc16is752";
-+                reg = <0x50>;
-+                clocks = <&sc16is752_clk>;
-+                interrupt-parent = <&gpio>;
-+                interrupts = <17 2>; /* IRQ_TYPE_EDGE_FALLING */
-+
-+                pinctrl-names = "default";
-+                pinctrl-0 = <&sc16is752_irq>;
-+
-+                sc16is752_clk: sc16is752_clk {
-+                    compatible = "fixed-clock";
-+                    #clock-cells = <0>;
-+                    clock-frequency = <1843200>;
-+                };
-+            };
-+
-+            tla2024: tla2024@48 {
-+                compatible = "ti,ads1015";
-+                reg = <0x48>;
-+                #address-cells = <1>;
-+                #size-cells = <0>;
-+
-+                adc_ch4: channel@4 {
-+                    reg = <4>;
-+                    ti,gain = <1>;
-+                    ti,datarate = <4>;
-+                };
-+
-+                adc_ch5: channel@5 {
-+                    reg = <5>;
-+                    ti,gain = <1>;
-+                    ti,datarate = <4>;
-+                };
-+
-+                adc_ch6: channel@6 {
-+                    reg = <6>;
-+                    ti,gain = <2>;
-+                    ti,datarate = <4>;
-+                };
-+
-+                adc_ch7: channel@7 {
-+                    reg = <7>;
-+                    ti,gain = <2>;
-+                    ti,datarate = <4>;
-+                };
-+            };
-+        };
-+    };
-+
-+    fragment@3 {
-+        target = <&sound>;
-+        snd: __overlay__ {
-+            compatible = "simple-audio-card";
-+            i2s-controller = <&i2s>;
-+            status = "okay";
-+
-+            simple-audio-card,name = "draws";
-+            simple-audio-card,format = "i2s";
-+
-+            simple-audio-card,bitclock-master = <&dailink0_master>;
-+            simple-audio-card,frame-master = <&dailink0_master>;
-+
-+            simple-audio-card,widgets =
-+                "Line", "Line In",
-+                "Line", "Line Out";
-+
-+            simple-audio-card,routing =
-+                "IN1_R", "Line In",
-+                "IN1_L", "Line In",
-+                "CM_L", "Line In",
-+                "CM_R", "Line In",
-+                "Line Out", "LOR",
-+                "Line Out", "LOL";
-+
-+            dailink0_master: simple-audio-card,cpu {
-+                sound-dai = <&i2s>;
-+            };
-+
-+            simple-audio-card,codec {
-+                sound-dai = <&tlv320aic32x4>;
-+            };
-+        };
-+    };
-+
-+    fragment@4 {
-+        target = <&gpio>;
-+        __overlay__ {
-+            gpclk0_pin: gpclk0_pin {
-+                brcm,pins = <4>;
-+                brcm,function = <4>;
-+            };
-+
-+            aic3204_reset: aic3204_reset {
-+                brcm,pins = <13>;
-+                brcm,function = <1>;
-+                brcm,pull = <1>;
-+            };
-+
-+            aic3204_gpio: aic3204_gpio {
-+                brcm,pins = <26>;
-+            };
-+
-+            sc16is752_irq: sc16is752_irq {
-+                brcm,pins = <17>;
-+                brcm,function = <0>;
-+                brcm,pull = <2>;
-+            };
-+
-+            pps_pins: pps_pins {
-+                brcm,pins = <7>;
-+                brcm,function = <0>;
-+                brcm,pull = <0>;
-+            };
-+        };
-+    };
-+
-+    __overrides__ {
-+        draws_adc_ch4_gain = <&adc_ch4>,"ti,gain:0";
-+        draws_adc_ch4_datarate = <&adc_ch4>,"ti,datarate:0";
-+        draws_adc_ch5_gain = <&adc_ch5>,"ti,gain:0";
-+        draws_adc_ch5_datarate = <&adc_ch5>,"ti,datarate:0";
-+        draws_adc_ch6_gain = <&adc_ch6>,"ti,gain:0";
-+        draws_adc_ch6_datarate = <&adc_ch6>,"ti,datarate:0";
-+        draws_adc_ch7_gain = <&adc_ch7>,"ti,gain:0";
-+        draws_adc_ch7_datarate = <&adc_ch7>,"ti,datarate:0";
-+        alsaname = <&snd>, "simple-audio-card,name";
-+    };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
-@@ -0,0 +1,128 @@
-+#include <dt-bindings/clock/bcm2835.h>
-+/*
-+ * Device tree overlay for the Universal Digital Radio Controller
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+    fragment@0 {
-+        target = <&i2s>;
-+        __overlay__ {
-+            clocks = <&clocks BCM2835_CLOCK_PCM>;
-+            clock-names = "pcm";
-+            status = "okay";
-+        };
-+    };
-+
-+    fragment@1 {
-+        target-path = "/";
-+        __overlay__ {
-+            regulators {
-+                compatible = "simple-bus";
-+                #address-cells = <1>;
-+                #size-cells = <0>;
-+
-+                udrc0_ldoin: udrc0_ldoin {
-+                    compatible = "regulator-fixed";
-+                    regulator-name = "ldoin";
-+                    regulator-min-microvolt = <3300000>;
-+                    regulator-max-microvolt = <3300000>;
-+                    regulator-always-on;
-+                };
-+            };
-+        };
-+    };
-+
-+    fragment@2 {
-+        target = <&i2c1>;
-+        __overlay__ {
-+            #address-cells = <1>;
-+            #size-cells = <0>;
-+            status = "okay";
-+            clocks = <&clocks BCM2835_CLOCK_VPU>;
-+            clock-frequency = <400000>;
-+
-+            tlv320aic32x4: tlv320aic32x4@18 {
-+                compatible = "ti,tlv320aic32x4";
-+                #sound-dai-cells = <0>;
-+                reg = <0x18>;
-+                status = "okay";
-+
-+                clocks = <&clocks BCM2835_CLOCK_GP0>;
-+                clock-names = "mclk";
-+                assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
-+                assigned-clock-rates = <25000000>;
-+
-+                pinctrl-names = "default";
-+                pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
-+
-+                reset-gpios = <&gpio 13 0>;
-+
-+                iov-supply = <&udrc0_ldoin>;
-+                ldoin-supply = <&udrc0_ldoin>;
-+            };
-+        };
-+    };
-+
-+    fragment@3 {
-+        target = <&sound>;
-+        snd: __overlay__ {
-+            compatible = "simple-audio-card";
-+            i2s-controller = <&i2s>;
-+            status = "okay";
-+
-+            simple-audio-card,name = "udrc";
-+            simple-audio-card,format = "i2s";
-+
-+            simple-audio-card,bitclock-master = <&dailink0_master>;
-+            simple-audio-card,frame-master = <&dailink0_master>;
-+
-+            simple-audio-card,widgets =
-+                "Line", "Line In",
-+                "Line", "Line Out";
-+
-+            simple-audio-card,routing =
-+                "IN1_R", "Line In",
-+                "IN1_L", "Line In",
-+                "CM_L", "Line In",
-+                "CM_R", "Line In",
-+                "Line Out", "LOR",
-+                "Line Out", "LOL";
-+
-+            dailink0_master: simple-audio-card,cpu {
-+                sound-dai = <&i2s>;
-+            };
-+
-+            simple-audio-card,codec {
-+                sound-dai = <&tlv320aic32x4>;
-+            };
-+        };
-+    };
-+
-+    fragment@4 {
-+        target = <&gpio>;
-+        __overlay__ {
-+            gpclk0_pin: gpclk0_pin {
-+                brcm,pins = <4>;
-+                brcm,function = <4>;
-+            };
-+
-+            aic3204_reset: aic3204_reset {
-+                brcm,pins = <13>;
-+                brcm,function = <1>;
-+                brcm,pull = <1>;
-+            };
-+
-+            aic3204_gpio: aic3204_gpio {
-+                brcm,pins = <26>;
-+            };
-+        };
-+    };
-+
-+    __overrides__ {
-+        alsaname = <&snd>, "simple-audio-card,name";
-+    };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0363-Input-ili210x-add-DT-binding-document.patch b/target/linux/brcm2708/patches-4.19/950-0363-Input-ili210x-add-DT-binding-document.patch
new file mode 100644 (file)
index 0000000..5eb3703
--- /dev/null
@@ -0,0 +1,47 @@
+From 9ee66e1acf33fd1dcf4beb8a6fce4fdade01ab05 Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:49:51 +0200
+Subject: [PATCH] Input: ili210x - add DT binding document
+
+commit 41a852e002e65ab7a1e6841b485d72d022e95df2 upstream
+
+Add DT binding document for the Ilitek ILI210x and ILI251x
+touchscreen controllers.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ .../bindings/input/ilitek,ili2xxx.txt         | 26 +++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
+@@ -0,0 +1,26 @@
++Ilitek ILI210x/ILI251x touchscreen controller
++
++Required properties:
++- compatible:
++    ilitek,ili210x for ILI210x
++    ilitek,ili251x for ILI251x
++
++- reg: The I2C address of the device
++
++- interrupts: The sink for the touchscreen's IRQ output
++    See ../interrupt-controller/interrupts.txt
++
++Optional properties for main touchpad device:
++
++- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low)
++
++Example:
++
++      touchscreen@41 {
++              compatible = "ilitek,ili251x";
++              reg = <0x41>;
++              interrupt-parent = <&gpio4>;
++              interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
++              reset-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>;
++      };
++
diff --git a/target/linux/brcm2708/patches-4.19/950-0363-dwc_otg-only-do_split-when-we-actually-need-to-do-a-.patch b/target/linux/brcm2708/patches-4.19/950-0363-dwc_otg-only-do_split-when-we-actually-need-to-do-a-.patch
deleted file mode 100644 (file)
index d2a9973..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From 0c988aed71773be4481b886ccf03c40a52f57cdb Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Mon, 8 Apr 2019 12:45:23 +0100
-Subject: [PATCH] dwc_otg: only do_split when we actually need to do a
- split
-
-The previous test would fail if the root port was in fullspeed mode
-and there was a hub between the FS device and the root port. While
-the transfer worked, the schedule mangling performed for high-speed
-split transfers would break leading to an 8ms polling interval.
----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 9 ++++-----
- 1 file changed, 4 insertions(+), 5 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
-@@ -167,8 +167,10 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
-       char *speed, *type;
-       int dev_speed;
-       uint32_t hub_addr, hub_port;
-+      hprt0_data_t hprt;
-       dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
-+      hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
-       /* Initialize QH */
-       qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
-@@ -191,9 +193,8 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
-       qh->nak_frame = 0xffff;
--      if (((dev_speed == USB_SPEED_LOW) ||
--           (dev_speed == USB_SPEED_FULL)) &&
--          (hub_addr != 0 && hub_addr != 1)) {
-+      if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED &&
-+                      dev_speed != USB_SPEED_HIGH) {
-               DWC_DEBUGPL(DBG_HCD,
-                           "QH init: EP %d: TT found at hub addr %d, for port %d\n",
-                           dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
-@@ -204,7 +205,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
-       if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
-               /* Compute scheduling parameters once and save them. */
--              hprt0_data_t hprt;
-               /** @todo Account for split transfers in the bus time. */
-               int bytecount =
-@@ -219,7 +219,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
-                                                   SCHEDULE_SLOP);
-               qh->interval = urb->interval;
--              hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
-               if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) {
-                       if (dev_speed == USB_SPEED_LOW ||
-                                       dev_speed == USB_SPEED_FULL) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0364-BCM2708-Add-core-Device-Tree-support-ilitek251x.patch b/target/linux/brcm2708/patches-4.19/950-0364-BCM2708-Add-core-Device-Tree-support-ilitek251x.patch
new file mode 100644 (file)
index 0000000..0967821
--- /dev/null
@@ -0,0 +1,91 @@
+From c0dfc87e355a7c6e434122e1a4fcc69729970610 Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 17:06:44 +0200
+Subject: [PATCH] BCM2708: Add core Device Tree support, ilitek251x
+
+Signed-off-by: Samuel Hsu <hsu@distec.de>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             | 11 +++++
+ .../boot/dts/overlays/ilitek251x-overlay.dts  | 45 +++++++++++++++++++
+ 3 files changed, 57 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -67,6 +67,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       i2c0-bcm2708.dtbo \
+       i2c1-bcm2708.dtbo \
+       i2s-gpio28-31.dtbo \
++      ilitek251x.dtbo \
+       iqaudio-dac.dtbo \
+       iqaudio-dacplus.dtbo \
+       iqaudio-digi-wm8804-audio.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1146,6 +1146,17 @@ Load:   dtoverlay=i2s-gpio28-31
+ Params: <None>
++Name:   ilitek251x
++Info:   Enables I2C connected Ilitek 251x multiple touch controller using
++        GPIO 4 (pin 7 on GPIO header) for interrupt.
++Load:   dtoverlay=ilitek251x,<param>=<val>
++Params: interrupt               GPIO used for interrupt (default 4)
++        sizex                   Touchscreen size x, horizontal resolution of
++                                touchscreen (in pixels)
++        sizey                   Touchscreen size y, vertical resolution of
++                                touchscreen (in pixels)
++
++
+ Name:   iqaudio-dac
+ Info:   Configures the IQaudio DAC audio card
+ Load:   dtoverlay=iqaudio-dac,<param>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
+@@ -0,0 +1,45 @@
++// Device tree overlay for I2C connected Ilitek multiple touch controller
++/dts-v1/;
++/plugin/;
++
++ / {
++      compatible = "brcm,bcm2708";
++
++      fragment@0 {
++              target = <&gpio>;
++              __overlay__ {           
++                      ili251x_pins: ili251x_pins {
++                              brcm,pins = <4>; // interrupt
++                              brcm,function = <0>; // in
++                              brcm,pull = <2>; // pull-up //
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      ili251x: ili251x@41 {
++                              compatible = "ilitek,ili251x";
++                              reg = <0x41>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&ili251x_pins>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <4 8>; // high-to-low edge triggered
++                              touchscreen-size-x = <16384>;
++                              touchscreen-size-y = <9600>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              interrupt = <&ili251x_pins>,"brcm,pins:0",
++                      <&ili251x>,"interrupts:0";
++              sizex = <&ili251x>,"touchscreen-size-x:0";
++              sizey = <&ili251x>,"touchscreen-size-y:0";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0364-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch b/target/linux/brcm2708/patches-4.19/950-0364-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch
deleted file mode 100644 (file)
index 84c99ff..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-From 9c823e2ee1ec1b815b8ec29c231b112c5e397202 Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 16:42:17 +0200
-Subject: [PATCH] Input: ili210x - fetch touchscreen geometry from DT
-
-commit f67cc3e927d8414ad3872e046764534ea1f5db0d upstream
-
-Fetching the geometry from the ILI251x registers seems unreliable and
-sometimes returns all zeroes. Add support for fetching the geometry and
-axis inversion from DT instead.
-
-Signed-off-by: Marek Vasut <marex@denx.de>
-Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
----
- drivers/input/touchscreen/ili210x.c | 321 +++++++++++++++++-----------
- 1 file changed, 194 insertions(+), 127 deletions(-)
-
---- a/drivers/input/touchscreen/ili210x.c
-+++ b/drivers/input/touchscreen/ili210x.c
-@@ -4,11 +4,15 @@
- #include <linux/slab.h>
- #include <linux/input.h>
- #include <linux/input/mt.h>
-+#include <linux/input/touchscreen.h>
- #include <linux/delay.h>
- #include <linux/workqueue.h>
--#include <linux/input/ili210x.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/of_device.h>
-+#include <asm/unaligned.h>
--#define MAX_TOUCHES           2
-+#define ILI210X_TOUCHES               2
-+#define ILI251X_TOUCHES               10
- #define DEFAULT_POLL_PERIOD   20
- /* Touchscreen commands */
-@@ -17,41 +21,32 @@
- #define REG_FIRMWARE_VERSION  0x40
- #define REG_CALIBRATE         0xcc
--struct finger {
--      u8 x_low;
--      u8 x_high;
--      u8 y_low;
--      u8 y_high;
--} __packed;
--
--struct touchdata {
--      u8 status;
--      struct finger finger[MAX_TOUCHES];
--} __packed;
--
--struct panel_info {
--      struct finger finger_max;
--      u8 xchannel_num;
--      u8 ychannel_num;
--} __packed;
--
- struct firmware_version {
-       u8 id;
-       u8 major;
-       u8 minor;
- } __packed;
-+enum ili2xxx_model {
-+      MODEL_ILI210X,
-+      MODEL_ILI251X,
-+};
-+
- struct ili210x {
-       struct i2c_client *client;
-       struct input_dev *input;
--      bool (*get_pendown_state)(void);
-       unsigned int poll_period;
-       struct delayed_work dwork;
-+      struct gpio_desc *reset_gpio;
-+      struct touchscreen_properties prop;
-+      enum ili2xxx_model model;
-+      unsigned int max_touches;
- };
- static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
-                           size_t len)
- {
-+      struct ili210x *priv = i2c_get_clientdata(client);
-       struct i2c_msg msg[2] = {
-               {
-                       .addr   = client->addr,
-@@ -67,7 +62,38 @@ static int ili210x_read_reg(struct i2c_c
-               }
-       };
--      if (i2c_transfer(client->adapter, msg, 2) != 2) {
-+      if (priv->model == MODEL_ILI251X) {
-+              if (i2c_transfer(client->adapter, msg, 1) != 1) {
-+                      dev_err(&client->dev, "i2c transfer failed\n");
-+                      return -EIO;
-+              }
-+
-+              usleep_range(5000, 5500);
-+
-+              if (i2c_transfer(client->adapter, msg + 1, 1) != 1) {
-+                      dev_err(&client->dev, "i2c transfer failed\n");
-+                      return -EIO;
-+              }
-+      } else {
-+              if (i2c_transfer(client->adapter, msg, 2) != 2) {
-+                      dev_err(&client->dev, "i2c transfer failed\n");
-+                      return -EIO;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int ili210x_read(struct i2c_client *client, void *buf, size_t len)
-+{
-+      struct i2c_msg msg = {
-+              .addr   = client->addr,
-+              .flags  = I2C_M_RD,
-+              .len    = len,
-+              .buf    = buf,
-+      };
-+
-+      if (i2c_transfer(client->adapter, &msg, 1) != 1) {
-               dev_err(&client->dev, "i2c transfer failed\n");
-               return -EIO;
-       }
-@@ -75,42 +101,72 @@ static int ili210x_read_reg(struct i2c_c
-       return 0;
- }
--static void ili210x_report_events(struct input_dev *input,
--                                const struct touchdata *touchdata)
-+static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
-+                                      unsigned int finger,
-+                                      unsigned int *x, unsigned int *y)
- {
--      int i;
--      bool touch;
--      unsigned int x, y;
--      const struct finger *finger;
-+      if (finger >= ILI210X_TOUCHES)
-+              return false;
--      for (i = 0; i < MAX_TOUCHES; i++) {
--              input_mt_slot(input, i);
-+      if (touchdata[0] & BIT(finger))
-+              return false;
--              finger = &touchdata->finger[i];
-+      *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
-+      *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
--              touch = touchdata->status & (1 << i);
--              input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
--              if (touch) {
--                      x = finger->x_low | (finger->x_high << 8);
--                      y = finger->y_low | (finger->y_high << 8);
-+      return true;
-+}
-+
-+static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
-+                                      unsigned int finger,
-+                                      unsigned int *x, unsigned int *y)
-+{
-+      if (finger >= ILI251X_TOUCHES)
-+              return false;
-+
-+      *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
-+      if (!(*x & BIT(15)))    /* Touch indication */
-+              return false;
-+
-+      *x &= 0x3fff;
-+      *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
-+
-+      return true;
-+}
-+
-+static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
-+{
-+      struct input_dev *input = priv->input;
-+      int i;
-+      bool contact = false, touch = false;
-+      unsigned int x = 0, y = 0;
--                      input_report_abs(input, ABS_MT_POSITION_X, x);
--                      input_report_abs(input, ABS_MT_POSITION_Y, y);
-+      for (i = 0; i < priv->max_touches; i++) {
-+              if (priv->model == MODEL_ILI210X) {
-+                      touch = ili210x_touchdata_to_coords(priv, touchdata,
-+                                                          i, &x, &y);
-+              } else if (priv->model == MODEL_ILI251X) {
-+                      touch = ili251x_touchdata_to_coords(priv, touchdata,
-+                                                          i, &x, &y);
-+                      if (touch)
-+                              contact = true;
-               }
-+
-+              input_mt_slot(input, i);
-+              input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-+              if (!touch)
-+                      continue;
-+              touchscreen_report_pos(input, &priv->prop, x, y,
-+                                     true);
-       }
-       input_mt_report_pointer_emulation(input, false);
-       input_sync(input);
--}
--static bool get_pendown_state(const struct ili210x *priv)
--{
--      bool state = false;
--
--      if (priv->get_pendown_state)
--              state = priv->get_pendown_state();
-+      if (priv->model == MODEL_ILI210X)
-+              contact = touchdata[0] & 0xf3;
--      return state;
-+      return contact;
- }
- static void ili210x_work(struct work_struct *work)
-@@ -118,20 +174,29 @@ static void ili210x_work(struct work_str
-       struct ili210x *priv = container_of(work, struct ili210x,
-                                           dwork.work);
-       struct i2c_client *client = priv->client;
--      struct touchdata touchdata;
--      int error;
-+      u8 touchdata[64] = { 0 };
-+      bool touch;
-+      int error = -EINVAL;
-+
-+      if (priv->model == MODEL_ILI210X) {
-+              error = ili210x_read_reg(client, REG_TOUCHDATA,
-+                                       touchdata, sizeof(touchdata));
-+      } else if (priv->model == MODEL_ILI251X) {
-+              error = ili210x_read_reg(client, REG_TOUCHDATA,
-+                                       touchdata, 31);
-+              if (!error && touchdata[0] == 2)
-+                      error = ili210x_read(client, &touchdata[31], 20);
-+      }
--      error = ili210x_read_reg(client, REG_TOUCHDATA,
--                               &touchdata, sizeof(touchdata));
-       if (error) {
-               dev_err(&client->dev,
-                       "Unable to get touchdata, err = %d\n", error);
-               return;
-       }
--      ili210x_report_events(priv->input, &touchdata);
-+      touch = ili210x_report_events(priv, touchdata);
--      if ((touchdata.status & 0xf3) || get_pendown_state(priv))
-+      if (touch)
-               schedule_delayed_work(&priv->dwork,
-                                     msecs_to_jiffies(priv->poll_period));
- }
-@@ -180,30 +245,76 @@ static const struct attribute_group ili2
-       .attrs = ili210x_attributes,
- };
-+static void ili210x_power_down(void *data)
-+{
-+      struct gpio_desc *reset_gpio = data;
-+
-+      gpiod_set_value_cansleep(reset_gpio, 1);
-+}
-+
-+static void ili210x_cancel_work(void *data)
-+{
-+      struct ili210x *priv = data;
-+
-+      cancel_delayed_work_sync(&priv->dwork);
-+}
-+
- static int ili210x_i2c_probe(struct i2c_client *client,
-                                      const struct i2c_device_id *id)
- {
-       struct device *dev = &client->dev;
--      const struct ili210x_platform_data *pdata = dev_get_platdata(dev);
-       struct ili210x *priv;
-+      struct gpio_desc *reset_gpio;
-       struct input_dev *input;
--      struct panel_info panel;
-       struct firmware_version firmware;
--      int xmax, ymax;
-+      enum ili2xxx_model model;
-       int error;
--      dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
-+      model = (enum ili2xxx_model)id->driver_data;
--      if (!pdata) {
--              dev_err(dev, "No platform data!\n");
--              return -EINVAL;
--      }
-+      dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
-       if (client->irq <= 0) {
-               dev_err(dev, "No IRQ!\n");
-               return -EINVAL;
-       }
-+      reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
-+      if (IS_ERR(reset_gpio))
-+              return PTR_ERR(reset_gpio);
-+
-+      if (reset_gpio) {
-+              error = devm_add_action_or_reset(dev, ili210x_power_down,
-+                                               reset_gpio);
-+              if (error)
-+                      return error;
-+
-+              usleep_range(50, 100);
-+              gpiod_set_value_cansleep(reset_gpio, 0);
-+              msleep(100);
-+      }
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      input = devm_input_allocate_device(dev);
-+      if (!input)
-+              return -ENOMEM;
-+
-+      priv->client = client;
-+      priv->input = input;
-+      priv->poll_period = DEFAULT_POLL_PERIOD;
-+      INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
-+      priv->reset_gpio = reset_gpio;
-+      priv->model = model;
-+      if (model == MODEL_ILI210X)
-+              priv->max_touches = ILI210X_TOUCHES;
-+      if (model == MODEL_ILI251X)
-+              priv->max_touches = ILI251X_TOUCHES;
-+
-+      i2c_set_clientdata(client, priv);
-+
-       /* Get firmware version */
-       error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
-                                &firmware, sizeof(firmware));
-@@ -213,70 +324,40 @@ static int ili210x_i2c_probe(struct i2c_
-               return error;
-       }
--      /* get panel info */
--      error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
--      if (error) {
--              dev_err(dev, "Failed to get panel information, err: %d\n",
--                      error);
--              return error;
--      }
--
--      xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
--      ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
--
--      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
--      input = input_allocate_device();
--      if (!priv || !input) {
--              error = -ENOMEM;
--              goto err_free_mem;
--      }
--
--      priv->client = client;
--      priv->input = input;
--      priv->get_pendown_state = pdata->get_pendown_state;
--      priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD;
--      INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
--
-       /* Setup input device */
-       input->name = "ILI210x Touchscreen";
-       input->id.bustype = BUS_I2C;
-       input->dev.parent = dev;
--      __set_bit(EV_SYN, input->evbit);
--      __set_bit(EV_KEY, input->evbit);
--      __set_bit(EV_ABS, input->evbit);
--      __set_bit(BTN_TOUCH, input->keybit);
--
--      /* Single touch */
--      input_set_abs_params(input, ABS_X, 0, xmax, 0, 0);
--      input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
--
-       /* Multi touch */
--      input_mt_init_slots(input, MAX_TOUCHES, 0);
--      input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
--      input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
-+      input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
-+      input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
-+      touchscreen_parse_properties(input, true, &priv->prop);
-+      input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
--      i2c_set_clientdata(client, priv);
-+      error = devm_add_action(dev, ili210x_cancel_work, priv);
-+      if (error)
-+              return error;
--      error = request_irq(client->irq, ili210x_irq, pdata->irq_flags,
--                          client->name, priv);
-+      error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
-+                               client->name, priv);
-       if (error) {
-               dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
-                       error);
--              goto err_free_mem;
-+              return error;
-       }
--      error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
-+      error = devm_device_add_group(dev, &ili210x_attr_group);
-       if (error) {
-               dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
-                       error);
--              goto err_free_irq;
-+              return error;
-       }
-       error = input_register_device(priv->input);
-       if (error) {
-               dev_err(dev, "Cannot register input device, err: %d\n", error);
--              goto err_remove_sysfs;
-+              return error;
-       }
-       device_init_wakeup(dev, 1);
-@@ -286,28 +367,6 @@ static int ili210x_i2c_probe(struct i2c_
-               client->irq, firmware.id, firmware.major, firmware.minor);
-       return 0;
--
--err_remove_sysfs:
--      sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
--err_free_irq:
--      free_irq(client->irq, priv);
--err_free_mem:
--      input_free_device(input);
--      kfree(priv);
--      return error;
--}
--
--static int ili210x_i2c_remove(struct i2c_client *client)
--{
--      struct ili210x *priv = i2c_get_clientdata(client);
--
--      sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
--      free_irq(priv->client->irq, priv);
--      cancel_delayed_work_sync(&priv->dwork);
--      input_unregister_device(priv->input);
--      kfree(priv);
--
--      return 0;
- }
- static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
-@@ -334,19 +393,27 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
-                        ili210x_i2c_suspend, ili210x_i2c_resume);
- static const struct i2c_device_id ili210x_i2c_id[] = {
--      { "ili210x", 0 },
-+      { "ili210x", MODEL_ILI210X },
-+      { "ili251x", MODEL_ILI251X },
-       { }
- };
- MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
-+static const struct of_device_id ili210x_dt_ids[] = {
-+      { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
-+      { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
-+      { },
-+};
-+MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
-+
- static struct i2c_driver ili210x_ts_driver = {
-       .driver = {
-               .name = "ili210x_i2c",
-               .pm = &ili210x_i2c_pm,
-+              .of_match_table = ili210x_dt_ids,
-       },
-       .id_table = ili210x_i2c_id,
-       .probe = ili210x_i2c_probe,
--      .remove = ili210x_i2c_remove,
- };
- module_i2c_driver(ili210x_ts_driver);
diff --git a/target/linux/brcm2708/patches-4.19/950-0365-Input-ili210x-add-DT-binding-document.patch b/target/linux/brcm2708/patches-4.19/950-0365-Input-ili210x-add-DT-binding-document.patch
deleted file mode 100644 (file)
index 5eb3703..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From 9ee66e1acf33fd1dcf4beb8a6fce4fdade01ab05 Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 16:49:51 +0200
-Subject: [PATCH] Input: ili210x - add DT binding document
-
-commit 41a852e002e65ab7a1e6841b485d72d022e95df2 upstream
-
-Add DT binding document for the Ilitek ILI210x and ILI251x
-touchscreen controllers.
-
-Signed-off-by: Marek Vasut <marex@denx.de>
-Reviewed-by: Rob Herring <robh@kernel.org>
-Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
----
- .../bindings/input/ilitek,ili2xxx.txt         | 26 +++++++++++++++++++
- 1 file changed, 26 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
-@@ -0,0 +1,26 @@
-+Ilitek ILI210x/ILI251x touchscreen controller
-+
-+Required properties:
-+- compatible:
-+    ilitek,ili210x for ILI210x
-+    ilitek,ili251x for ILI251x
-+
-+- reg: The I2C address of the device
-+
-+- interrupts: The sink for the touchscreen's IRQ output
-+    See ../interrupt-controller/interrupts.txt
-+
-+Optional properties for main touchpad device:
-+
-+- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low)
-+
-+Example:
-+
-+      touchscreen@41 {
-+              compatible = "ilitek,ili251x";
-+              reg = <0x41>;
-+              interrupt-parent = <&gpio4>;
-+              interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
-+              reset-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>;
-+      };
-+
diff --git a/target/linux/brcm2708/patches-4.19/950-0365-dwc_otg-fix-locking-around-dequeueing-and-killing-UR.patch b/target/linux/brcm2708/patches-4.19/950-0365-dwc_otg-fix-locking-around-dequeueing-and-killing-UR.patch
new file mode 100644 (file)
index 0000000..53e2c98
--- /dev/null
@@ -0,0 +1,63 @@
+From ea7ff2070d564858c445cfdbd883ea00927c0ada Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Tue, 9 Apr 2019 16:40:48 +0100
+Subject: [PATCH] dwc_otg: fix locking around dequeueing and killing
+ URBs
+
+kill_urbs_in_qh_list() is practically only ever called with the fiq lock
+already held, so don't spinlock twice in the case where we need to cancel
+an isochronous transfer.
+
+Also fix up a case where the global interrupt register could be read with
+the fiq lock not held.
+
+Fixes the deadlock seen in https://github.com/raspberrypi/linux/issues/2907
+---
+ drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 9 +++++++--
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c      | 4 ----
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+@@ -1344,16 +1344,21 @@ static inline uint32_t dwc_otg_read_comm
+                */
+               gintmsk_common.b.portintr = 1;
+       }
+-      gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
+-      gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
+       if(fiq_enable) {
+               local_fiq_disable();
++              fiq_fsm_spin_lock(&hcd->fiq_state->lock);
++              gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
++              gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
+               /* Pull in the interrupts that the FIQ has masked */
+               gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
+               gintmsk.d32 |= gintmsk_common.d32;
+               /* for the upstairs function to reenable - have to read it here in case FIQ triggers again */
+               reenable_gintmsk->d32 = gintmsk.d32;
++              fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
+               local_fiq_enable();
++      } else {
++              gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
++              gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
+       }
+       gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -195,15 +195,11 @@ static void kill_urbs_in_qh_list(dwc_otg
+                        * but not yet been through the IRQ handler.
+                        */
+                       if (fiq_fsm_enable && (hcd->fiq_state->channel[qh->channel->hc_num].fsm != FIQ_PASSTHROUGH)) {
+-                              local_fiq_disable();
+-                              fiq_fsm_spin_lock(&hcd->fiq_state->lock);
+                               qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
+                               qh->channel->halt_pending = 1;
+                               if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
+                                       hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
+                                       hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
+-                              fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
+-                              local_fiq_enable();
+                       } else {
+                               dwc_otg_hc_halt(hcd->core_if, qh->channel,
+                                               DWC_OTG_HC_XFER_URB_DEQUEUE);
diff --git a/target/linux/brcm2708/patches-4.19/950-0366-BCM2708-Add-core-Device-Tree-support-ilitek251x.patch b/target/linux/brcm2708/patches-4.19/950-0366-BCM2708-Add-core-Device-Tree-support-ilitek251x.patch
deleted file mode 100644 (file)
index 0967821..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-From c0dfc87e355a7c6e434122e1a4fcc69729970610 Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 17:06:44 +0200
-Subject: [PATCH] BCM2708: Add core Device Tree support, ilitek251x
-
-Signed-off-by: Samuel Hsu <hsu@distec.de>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             | 11 +++++
- .../boot/dts/overlays/ilitek251x-overlay.dts  | 45 +++++++++++++++++++
- 3 files changed, 57 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -67,6 +67,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       i2c0-bcm2708.dtbo \
-       i2c1-bcm2708.dtbo \
-       i2s-gpio28-31.dtbo \
-+      ilitek251x.dtbo \
-       iqaudio-dac.dtbo \
-       iqaudio-dacplus.dtbo \
-       iqaudio-digi-wm8804-audio.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1146,6 +1146,17 @@ Load:   dtoverlay=i2s-gpio28-31
- Params: <None>
-+Name:   ilitek251x
-+Info:   Enables I2C connected Ilitek 251x multiple touch controller using
-+        GPIO 4 (pin 7 on GPIO header) for interrupt.
-+Load:   dtoverlay=ilitek251x,<param>=<val>
-+Params: interrupt               GPIO used for interrupt (default 4)
-+        sizex                   Touchscreen size x, horizontal resolution of
-+                                touchscreen (in pixels)
-+        sizey                   Touchscreen size y, vertical resolution of
-+                                touchscreen (in pixels)
-+
-+
- Name:   iqaudio-dac
- Info:   Configures the IQaudio DAC audio card
- Load:   dtoverlay=iqaudio-dac,<param>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-@@ -0,0 +1,45 @@
-+// Device tree overlay for I2C connected Ilitek multiple touch controller
-+/dts-v1/;
-+/plugin/;
-+
-+ / {
-+      compatible = "brcm,bcm2708";
-+
-+      fragment@0 {
-+              target = <&gpio>;
-+              __overlay__ {           
-+                      ili251x_pins: ili251x_pins {
-+                              brcm,pins = <4>; // interrupt
-+                              brcm,function = <0>; // in
-+                              brcm,pull = <2>; // pull-up //
-+                      };
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      ili251x: ili251x@41 {
-+                              compatible = "ilitek,ili251x";
-+                              reg = <0x41>;
-+                              pinctrl-names = "default";
-+                              pinctrl-0 = <&ili251x_pins>;
-+                              interrupt-parent = <&gpio>;
-+                              interrupts = <4 8>; // high-to-low edge triggered
-+                              touchscreen-size-x = <16384>;
-+                              touchscreen-size-y = <9600>;
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              interrupt = <&ili251x_pins>,"brcm,pins:0",
-+                      <&ili251x>,"interrupts:0";
-+              sizex = <&ili251x>,"touchscreen-size-x:0";
-+              sizey = <&ili251x>,"touchscreen-size-y:0";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0366-rtc-rv3028-Add-backup-switchover-mode-support.patch b/target/linux/brcm2708/patches-4.19/950-0366-rtc-rv3028-Add-backup-switchover-mode-support.patch
new file mode 100644 (file)
index 0000000..7eac710
--- /dev/null
@@ -0,0 +1,50 @@
+From fb4e195012c405a04b1a7a86e240ceada0c8aa65 Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:53:14 +0000
+Subject: [PATCH] rtc: rv3028: Add backup switchover mode support
+
+Signed-off-by: Phil Howard <phil@pimoroni.com>
+---
+ drivers/rtc/rtc-rv3028.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/drivers/rtc/rtc-rv3028.c
++++ b/drivers/rtc/rtc-rv3028.c
+@@ -74,6 +74,7 @@
+ #define RV3028_BACKUP_TCE             BIT(5)
+ #define RV3028_BACKUP_TCR_MASK                GENMASK(1,0)
++#define RV3028_BACKUP_BSM_MASK                0x0C
+ #define OFFSET_STEP_PPT                       953674
+@@ -601,6 +602,7 @@ static int rv3028_probe(struct i2c_clien
+       struct rv3028_data *rv3028;
+       int ret, status;
+       u32 ohms;
++      u8 bsm;
+       struct nvmem_config nvmem_cfg = {
+               .name = "rv3028_nvram",
+               .word_size = 1,
+@@ -671,6 +673,21 @@ static int rv3028_probe(struct i2c_clien
+       if (ret)
+               return ret;
++      /* setup backup switchover mode */
++      if (!device_property_read_u8(&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;
++              } else {
++                      dev_warn(&client->dev, "invalid backup switchover mode value\n");
++              }
++      }
++
+       /* setup trickle charger */
+       if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
+                                     &ohms)) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0367-dt-bindings-rv3028-backup-switchover-support.patch b/target/linux/brcm2708/patches-4.19/950-0367-dt-bindings-rv3028-backup-switchover-support.patch
new file mode 100644 (file)
index 0000000..040bd60
--- /dev/null
@@ -0,0 +1,20 @@
+From 48598900ebd06f5880b01fcc60e240ea4a04858c Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:57:07 +0000
+Subject: [PATCH] dt-bindings: rv3028 backup switchover support
+
+Signed-off-by: Phil Howard <phil@pimoroni.com>
+---
+ Documentation/devicetree/bindings/rtc/rtc.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/rtc/rtc.txt
++++ b/Documentation/devicetree/bindings/rtc/rtc.txt
+@@ -26,6 +26,7 @@ below.
+ - trickle-diode-disable :   Do not use internal trickle charger diode Should be
+                             given if internal trickle charger diode should be
+                             disabled
++- backup-switchover-mode :  Configure RTC backup power supply switch behaviour
+ - wakeup-source :           Enables wake up of host system on alarm
+ - quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
+                             expressed in femto Farad (fF).
diff --git a/target/linux/brcm2708/patches-4.19/950-0367-dwc_otg-fix-locking-around-dequeueing-and-killing-UR.patch b/target/linux/brcm2708/patches-4.19/950-0367-dwc_otg-fix-locking-around-dequeueing-and-killing-UR.patch
deleted file mode 100644 (file)
index 53e2c98..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From ea7ff2070d564858c445cfdbd883ea00927c0ada Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Tue, 9 Apr 2019 16:40:48 +0100
-Subject: [PATCH] dwc_otg: fix locking around dequeueing and killing
- URBs
-
-kill_urbs_in_qh_list() is practically only ever called with the fiq lock
-already held, so don't spinlock twice in the case where we need to cancel
-an isochronous transfer.
-
-Also fix up a case where the global interrupt register could be read with
-the fiq lock not held.
-
-Fixes the deadlock seen in https://github.com/raspberrypi/linux/issues/2907
----
- drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 9 +++++++--
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c      | 4 ----
- 2 files changed, 7 insertions(+), 6 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
-@@ -1344,16 +1344,21 @@ static inline uint32_t dwc_otg_read_comm
-                */
-               gintmsk_common.b.portintr = 1;
-       }
--      gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
--      gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
-       if(fiq_enable) {
-               local_fiq_disable();
-+              fiq_fsm_spin_lock(&hcd->fiq_state->lock);
-+              gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
-+              gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
-               /* Pull in the interrupts that the FIQ has masked */
-               gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
-               gintmsk.d32 |= gintmsk_common.d32;
-               /* for the upstairs function to reenable - have to read it here in case FIQ triggers again */
-               reenable_gintmsk->d32 = gintmsk.d32;
-+              fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
-               local_fiq_enable();
-+      } else {
-+              gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
-+              gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
-       }
-       gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -195,15 +195,11 @@ static void kill_urbs_in_qh_list(dwc_otg
-                        * but not yet been through the IRQ handler.
-                        */
-                       if (fiq_fsm_enable && (hcd->fiq_state->channel[qh->channel->hc_num].fsm != FIQ_PASSTHROUGH)) {
--                              local_fiq_disable();
--                              fiq_fsm_spin_lock(&hcd->fiq_state->lock);
-                               qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
-                               qh->channel->halt_pending = 1;
-                               if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
-                                       hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
-                                       hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
--                              fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
--                              local_fiq_enable();
-                       } else {
-                               dwc_otg_hc_halt(hcd->core_if, qh->channel,
-                                               DWC_OTG_HC_XFER_URB_DEQUEUE);
diff --git a/target/linux/brcm2708/patches-4.19/950-0368-overlays-Add-rv3028-backup-switchover-support-to-i2c.patch b/target/linux/brcm2708/patches-4.19/950-0368-overlays-Add-rv3028-backup-switchover-support-to-i2c.patch
new file mode 100644 (file)
index 0000000..769f246
--- /dev/null
@@ -0,0 +1,34 @@
+From a2fdc7a590566d99d5261badeecb644664ff0fb3 Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:59:55 +0000
+Subject: [PATCH] overlays: Add rv3028 backup switchover support to
+ i2c-rtc
+
+Signed-off-by: Phil Howard <phil@pimoroni.com>
+---
+ arch/arm/boot/dts/overlays/README              | 3 +++
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1013,6 +1013,9 @@ Params: abx80x                  Select o
+         wakeup-source           Specify that the RTC can be used as a wakeup
+                                 source
++        backup-switchover-mode  Backup power supply switch mode. Must be 0 for
++                                off or 1 for Vdd < VBackup (RV3028 only)
++
+ Name:   i2c-rtc-gpio
+ Info:   Adds support for a number of I2C Real Time Clock devices
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -200,6 +200,7 @@
+               trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+                                       <&abx80x>,"abracon,tc-resistor",
+                                       <&rv3028>,"trickle-resistor-ohms:0";
++              backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+               wakeup-source = <&ds1339>,"wakeup-source?",
+                               <&ds3231>,"wakeup-source?",
+                               <&mcp7940x>,"wakeup-source?",
diff --git a/target/linux/brcm2708/patches-4.19/950-0368-rtc-rv3028-Add-backup-switchover-mode-support.patch b/target/linux/brcm2708/patches-4.19/950-0368-rtc-rv3028-Add-backup-switchover-mode-support.patch
deleted file mode 100644 (file)
index 7eac710..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-From fb4e195012c405a04b1a7a86e240ceada0c8aa65 Mon Sep 17 00:00:00 2001
-From: Phil Howard <phil@gadgetoid.com>
-Date: Fri, 29 Mar 2019 10:53:14 +0000
-Subject: [PATCH] rtc: rv3028: Add backup switchover mode support
-
-Signed-off-by: Phil Howard <phil@pimoroni.com>
----
- drivers/rtc/rtc-rv3028.c | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
---- a/drivers/rtc/rtc-rv3028.c
-+++ b/drivers/rtc/rtc-rv3028.c
-@@ -74,6 +74,7 @@
- #define RV3028_BACKUP_TCE             BIT(5)
- #define RV3028_BACKUP_TCR_MASK                GENMASK(1,0)
-+#define RV3028_BACKUP_BSM_MASK                0x0C
- #define OFFSET_STEP_PPT                       953674
-@@ -601,6 +602,7 @@ static int rv3028_probe(struct i2c_clien
-       struct rv3028_data *rv3028;
-       int ret, status;
-       u32 ohms;
-+      u8 bsm;
-       struct nvmem_config nvmem_cfg = {
-               .name = "rv3028_nvram",
-               .word_size = 1,
-@@ -671,6 +673,21 @@ static int rv3028_probe(struct i2c_clien
-       if (ret)
-               return ret;
-+      /* setup backup switchover mode */
-+      if (!device_property_read_u8(&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;
-+              } else {
-+                      dev_warn(&client->dev, "invalid backup switchover mode value\n");
-+              }
-+      }
-+
-       /* setup trickle charger */
-       if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
-                                     &ohms)) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0369-Maxim-MAX98357A-I2S-DAC-overlay-2935.patch b/target/linux/brcm2708/patches-4.19/950-0369-Maxim-MAX98357A-I2S-DAC-overlay-2935.patch
new file mode 100644 (file)
index 0000000..e149912
--- /dev/null
@@ -0,0 +1,130 @@
+From 5962d99b5efed4297ed5c1807d21b406ab86aef1 Mon Sep 17 00:00:00 2001
+From: wavelet2 <20504977+wavelet2@users.noreply.github.com>
+Date: Mon, 15 Apr 2019 10:00:20 +0100
+Subject: [PATCH] Maxim MAX98357A I2S DAC overlay (#2935)
+
+Add overlay for Maxim MAX98357A I2S DAC.
+
+Signed-off-by: Richard Steedman <richard.steedman@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  9 ++
+ .../boot/dts/overlays/max98357a-overlay.dts   | 84 +++++++++++++++++++
+ 3 files changed, 94 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/max98357a-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -75,6 +75,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       justboom-dac.dtbo \
+       justboom-digi.dtbo \
+       ltc294x.dtbo \
++      max98357a.dtbo \
+       mbed-dac.dtbo \
+       mcp23017.dtbo \
+       mcp23s17.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1276,6 +1276,15 @@ Params: ltc2941                 Select t
+                                 See the datasheet for more information.
++Name:   max98357a
++Info:   Configures the Maxim MAX98357A I2S DAC
++Load:   dtoverlay=max98357a,<param>=<val>
++Params: no-sdmode               Driver does not manage the state of the DAC's
++                                SD_MODE pin (i.e. chip is always on).
++        sdmode-pin              integer, GPIO pin connected to the SD_MODE input
++                                of the DAC (default GPIO4 if parameter omitted).
++
++
+ Name:   mbed-dac
+ Info:   Configures the mbed AudioCODEC (TLV320AIC23B)
+ Load:   dtoverlay=mbed-dac
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
+@@ -0,0 +1,84 @@
++// Overlay for Maxim MAX98357A audio DAC
++
++// dtparams:
++//     no-sdmode  - SD_MODE pin not managed by driver.
++//     sdmode-pin - Specify GPIO pin to which SD_MODE is connected (default 4).
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++      /* Enable I2S */
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      /* DAC whose SD_MODE pin is managed by driver (via GPIO pin) */
++      fragment@1 {
++              target-path = "/";
++              __overlay__ {
++                      max98357a_dac: max98357a {
++                              compatible = "maxim,max98357a";
++                              #sound-dai-cells = <0>;
++                              sdmode-gpios = <&gpio 4 0>;   /* 2nd word overwritten by sdmode-pin parameter */
++                              status = "okay";
++                      };
++              };
++      };
++
++      /* DAC whose SD_MODE pin is not managed by driver */
++      fragment@2 {
++              target-path = "/";
++              __dormant__ {
++                      max98357a_nsd: max98357a {
++                              compatible = "maxim,max98357a";
++                              #sound-dai-cells = <0>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      /* Soundcard connecting I2S to DAC with SD_MODE */
++      fragment@3 {
++              target = <&sound>;
++              __overlay__ {
++                      compatible = "simple-audio-card";
++                      simple-audio-card,format = "i2s";
++                      simple-audio-card,name = "MAX98357A";
++                      status = "okay";
++                      simple-audio-card,cpu {
++                              sound-dai = <&i2s>;
++                      };
++                      simple-audio-card,codec {
++                              sound-dai = <&max98357a_dac>;
++                      };
++              };
++      };
++
++      /* Soundcard connecting I2S to DAC without SD_MODE */
++      fragment@4 {
++              target = <&sound>;
++              __dormant__ {
++                      compatible = "simple-audio-card";
++                      simple-audio-card,format = "i2s";
++                      simple-audio-card,name = "MAX98357A";
++                      status = "okay";
++                      simple-audio-card,cpu {
++                              sound-dai = <&i2s>;
++                      };
++                      simple-audio-card,codec {
++                              sound-dai = <&max98357a_nsd>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              no-sdmode  = <0>,"-1+2-3+4";
++              sdmode-pin = <&max98357a_dac>,"sdmode-gpios:4";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0369-dt-bindings-rv3028-backup-switchover-support.patch b/target/linux/brcm2708/patches-4.19/950-0369-dt-bindings-rv3028-backup-switchover-support.patch
deleted file mode 100644 (file)
index 040bd60..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From 48598900ebd06f5880b01fcc60e240ea4a04858c Mon Sep 17 00:00:00 2001
-From: Phil Howard <phil@gadgetoid.com>
-Date: Fri, 29 Mar 2019 10:57:07 +0000
-Subject: [PATCH] dt-bindings: rv3028 backup switchover support
-
-Signed-off-by: Phil Howard <phil@pimoroni.com>
----
- Documentation/devicetree/bindings/rtc/rtc.txt | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/Documentation/devicetree/bindings/rtc/rtc.txt
-+++ b/Documentation/devicetree/bindings/rtc/rtc.txt
-@@ -26,6 +26,7 @@ below.
- - trickle-diode-disable :   Do not use internal trickle charger diode Should be
-                             given if internal trickle charger diode should be
-                             disabled
-+- backup-switchover-mode :  Configure RTC backup power supply switch behaviour
- - wakeup-source :           Enables wake up of host system on alarm
- - quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
-                             expressed in femto Farad (fF).
diff --git a/target/linux/brcm2708/patches-4.19/950-0370-overlays-Add-rv3028-backup-switchover-support-to-i2c.patch b/target/linux/brcm2708/patches-4.19/950-0370-overlays-Add-rv3028-backup-switchover-support-to-i2c.patch
deleted file mode 100644 (file)
index 769f246..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From a2fdc7a590566d99d5261badeecb644664ff0fb3 Mon Sep 17 00:00:00 2001
-From: Phil Howard <phil@gadgetoid.com>
-Date: Fri, 29 Mar 2019 10:59:55 +0000
-Subject: [PATCH] overlays: Add rv3028 backup switchover support to
- i2c-rtc
-
-Signed-off-by: Phil Howard <phil@pimoroni.com>
----
- arch/arm/boot/dts/overlays/README              | 3 +++
- arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 1 +
- 2 files changed, 4 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1013,6 +1013,9 @@ Params: abx80x                  Select o
-         wakeup-source           Specify that the RTC can be used as a wakeup
-                                 source
-+        backup-switchover-mode  Backup power supply switch mode. Must be 0 for
-+                                off or 1 for Vdd < VBackup (RV3028 only)
-+
- Name:   i2c-rtc-gpio
- Info:   Adds support for a number of I2C Real Time Clock devices
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -200,6 +200,7 @@
-               trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
-                                       <&abx80x>,"abracon,tc-resistor",
-                                       <&rv3028>,"trickle-resistor-ohms:0";
-+              backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
-               wakeup-source = <&ds1339>,"wakeup-source?",
-                               <&ds3231>,"wakeup-source?",
-                               <&mcp7940x>,"wakeup-source?",
diff --git a/target/linux/brcm2708/patches-4.19/950-0370-sound-Fixes-for-audioinjector-octo-under-4.19.patch b/target/linux/brcm2708/patches-4.19/950-0370-sound-Fixes-for-audioinjector-octo-under-4.19.patch
new file mode 100644 (file)
index 0000000..27c81bc
--- /dev/null
@@ -0,0 +1,108 @@
+From d003eff5bc4d19902867ad585292780a94746705 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 21 Mar 2019 11:19:46 +0000
+Subject: [PATCH] sound: Fixes for audioinjector-octo under 4.19
+
+1. Move the DT alias declaration to the I2C shim in the cases
+where the shim is enabled. This works around a problem caused by a
+4.19 commit [1] that generates DT/OF uevents for I2C drivers.
+
+2. Fix the diagnostics in an error path of the soundcard driver to
+correctly identify the reason for the failure to load.
+
+3. Move the declaration of the clock node in the overlay outside
+the I2C node to avoid warnings.
+
+4. Sort the overlay nodes so that dependencies are only to earlier
+fragments, in an attempt to get runtime dtoverlay application to
+work (it still doesn't...)
+
+See: https://github.com/Audio-Injector/Octo/issues/14
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+
+[1] af503716ac14 ("i2c: core: report OF style module alias for devices registered via OF")
+---
+ .../overlays/audioinjector-addons-overlay.dts | 19 ++++++++++++-------
+ sound/soc/bcm/audioinjector-octo-soundcard.c  |  2 +-
+ sound/soc/codecs/cs42xx8-i2c.c                |  7 +++++++
+ sound/soc/codecs/cs42xx8.c                    |  2 ++
+ 4 files changed, 22 insertions(+), 8 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
+@@ -13,6 +13,17 @@
+       };
+       fragment@1 {
++              target-path = "/";
++              __overlay__ {
++                      cs42448_mclk: codec-mclk {
++                              compatible = "fixed-clock";
++                              #clock-cells = <0>;
++                              clock-frequency = <49152000>;
++                      };
++              };
++      };
++
++      fragment@2 {
+               target = <&i2c1>;
+               __overlay__ {
+                       #address-cells = <1>;
+@@ -27,16 +38,10 @@
+                               clock-names = "mclk";
+                               status = "okay";
+                       };
+-
+-                      cs42448_mclk: codec-mclk {
+-                              compatible = "fixed-clock";
+-                              #clock-cells = <0>;
+-                              clock-frequency = <49152000>;
+-                      };
+               };
+       };
+-      fragment@2 {
++      fragment@3 {
+               target = <&sound>;
+               snd: __overlay__ {
+                       compatible = "ai,audioinjector-octo-soundcard";
+--- a/sound/soc/bcm/audioinjector-octo-soundcard.c
++++ b/sound/soc/bcm/audioinjector-octo-soundcard.c
+@@ -297,7 +297,7 @@ static int audioinjector_octo_probe(stru
+                       dai->codec_name = NULL;
+                       dai->codec_of_node = codec_node;
+               } else
+-                      if (!dai->cpu_of_node) {
++                      if (!i2s_node) {
+                               dev_err(&pdev->dev,
+                               "i2s-controller missing or invalid in DT\n");
+                               return -EINVAL;
+--- a/sound/soc/codecs/cs42xx8-i2c.c
++++ b/sound/soc/codecs/cs42xx8-i2c.c
+@@ -45,6 +45,13 @@ static struct i2c_device_id cs42xx8_i2c_
+ };
+ MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
++const struct of_device_id cs42xx8_of_match[] = {
++      { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
++      { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
++      { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
++
+ static struct i2c_driver cs42xx8_i2c_driver = {
+       .driver = {
+               .name = "cs42xx8",
+--- a/sound/soc/codecs/cs42xx8.c
++++ b/sound/soc/codecs/cs42xx8.c
+@@ -436,8 +436,10 @@ const struct of_device_id cs42xx8_of_mat
+       { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
+       { /* sentinel */ }
+ };
++#if !IS_ENABLED(CONFIG_SND_SOC_CS42XX8_I2C)
+ MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
+ EXPORT_SYMBOL_GPL(cs42xx8_of_match);
++#endif
+ int cs42xx8_probe(struct device *dev, struct regmap *regmap)
+ {
diff --git a/target/linux/brcm2708/patches-4.19/950-0371-Maxim-MAX98357A-I2S-DAC-overlay-2935.patch b/target/linux/brcm2708/patches-4.19/950-0371-Maxim-MAX98357A-I2S-DAC-overlay-2935.patch
deleted file mode 100644 (file)
index e149912..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-From 5962d99b5efed4297ed5c1807d21b406ab86aef1 Mon Sep 17 00:00:00 2001
-From: wavelet2 <20504977+wavelet2@users.noreply.github.com>
-Date: Mon, 15 Apr 2019 10:00:20 +0100
-Subject: [PATCH] Maxim MAX98357A I2S DAC overlay (#2935)
-
-Add overlay for Maxim MAX98357A I2S DAC.
-
-Signed-off-by: Richard Steedman <richard.steedman@gmail.com>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             |  9 ++
- .../boot/dts/overlays/max98357a-overlay.dts   | 84 +++++++++++++++++++
- 3 files changed, 94 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/max98357a-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -75,6 +75,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       justboom-dac.dtbo \
-       justboom-digi.dtbo \
-       ltc294x.dtbo \
-+      max98357a.dtbo \
-       mbed-dac.dtbo \
-       mcp23017.dtbo \
-       mcp23s17.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1276,6 +1276,15 @@ Params: ltc2941                 Select t
-                                 See the datasheet for more information.
-+Name:   max98357a
-+Info:   Configures the Maxim MAX98357A I2S DAC
-+Load:   dtoverlay=max98357a,<param>=<val>
-+Params: no-sdmode               Driver does not manage the state of the DAC's
-+                                SD_MODE pin (i.e. chip is always on).
-+        sdmode-pin              integer, GPIO pin connected to the SD_MODE input
-+                                of the DAC (default GPIO4 if parameter omitted).
-+
-+
- Name:   mbed-dac
- Info:   Configures the mbed AudioCODEC (TLV320AIC23B)
- Load:   dtoverlay=mbed-dac
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
-@@ -0,0 +1,84 @@
-+// Overlay for Maxim MAX98357A audio DAC
-+
-+// dtparams:
-+//     no-sdmode  - SD_MODE pin not managed by driver.
-+//     sdmode-pin - Specify GPIO pin to which SD_MODE is connected (default 4).
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+      /* Enable I2S */
-+      fragment@0 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      /* DAC whose SD_MODE pin is managed by driver (via GPIO pin) */
-+      fragment@1 {
-+              target-path = "/";
-+              __overlay__ {
-+                      max98357a_dac: max98357a {
-+                              compatible = "maxim,max98357a";
-+                              #sound-dai-cells = <0>;
-+                              sdmode-gpios = <&gpio 4 0>;   /* 2nd word overwritten by sdmode-pin parameter */
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      /* DAC whose SD_MODE pin is not managed by driver */
-+      fragment@2 {
-+              target-path = "/";
-+              __dormant__ {
-+                      max98357a_nsd: max98357a {
-+                              compatible = "maxim,max98357a";
-+                              #sound-dai-cells = <0>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      /* Soundcard connecting I2S to DAC with SD_MODE */
-+      fragment@3 {
-+              target = <&sound>;
-+              __overlay__ {
-+                      compatible = "simple-audio-card";
-+                      simple-audio-card,format = "i2s";
-+                      simple-audio-card,name = "MAX98357A";
-+                      status = "okay";
-+                      simple-audio-card,cpu {
-+                              sound-dai = <&i2s>;
-+                      };
-+                      simple-audio-card,codec {
-+                              sound-dai = <&max98357a_dac>;
-+                      };
-+              };
-+      };
-+
-+      /* Soundcard connecting I2S to DAC without SD_MODE */
-+      fragment@4 {
-+              target = <&sound>;
-+              __dormant__ {
-+                      compatible = "simple-audio-card";
-+                      simple-audio-card,format = "i2s";
-+                      simple-audio-card,name = "MAX98357A";
-+                      status = "okay";
-+                      simple-audio-card,cpu {
-+                              sound-dai = <&i2s>;
-+                      };
-+                      simple-audio-card,codec {
-+                              sound-dai = <&max98357a_nsd>;
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              no-sdmode  = <0>,"-1+2-3+4";
-+              sdmode-pin = <&max98357a_dac>,"sdmode-gpios:4";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0371-overlays-Add-PiGlow-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0371-overlays-Add-PiGlow-overlay.patch
new file mode 100644 (file)
index 0000000..4c3e76a
--- /dev/null
@@ -0,0 +1,147 @@
+From 615467f56356a2054d3a86854d391b7a2e0d5811 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 29 Apr 2019 19:35:33 +0200
+Subject: [PATCH] overlays: Add PiGlow overlay
+
+The PiGlow is a small add-on board for the Raspberry Pi that provides
+18 individually controllable LEDs (SN3218) and uses the following pins:
+
+P1 & P17 (3V3)
+P2 (5V)
+P3 (SDA)
+P5 (SCL)
+P14 (GND)
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  6 ++
+ arch/arm/boot/dts/overlays/piglow-overlay.dts | 97 +++++++++++++++++++
+ 3 files changed, 104 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/piglow-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -97,6 +97,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       pi3-disable-wifi.dtbo \
+       pi3-miniuart-bt.dtbo \
+       pibell.dtbo \
++      piglow.dtbo \
+       piscreen.dtbo \
+       piscreen2r.dtbo \
+       pisound.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1532,6 +1532,12 @@ Params: alsaname                Set the
+                                 "PiBell")
++Name:   piglow
++Info:   Configures the PiGlow by pimoroni.com
++Load:   dtoverlay=piglow
++Params: <None>
++
++
+ Name:   piscreen
+ Info:   PiScreen display by OzzMaker.com
+ Load:   dtoverlay=piscreen,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
+@@ -0,0 +1,97 @@
++// Definitions for SN3218 LED driver from Si-En Technology on PiGlow
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2708";
++
++      fragment@0 {
++              target = <&i2c_arm>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      sn3218@54 {
++                              compatible = "si-en,sn3218";
++                              reg = <0x54>;
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              status = "okay";
++
++                              led@1 {
++                                      reg = <1>;
++                                      label = "piglow:red:led1";
++                              };
++                              led@2 {
++                                      reg = <2>;
++                                      label = "piglow:orange:led2";
++                              };
++                              led@3 {
++                                      reg = <3>;
++                                      label = "piglow:yellow:led3";
++                              };
++                              led@4 {
++                                      reg = <4>;
++                                      label = "piglow:green:led4";
++                              };
++                              led@5 {
++                                      reg = <5>;
++                                      label = "piglow:blue:led5";
++                              };
++                              led@6 {
++                                      reg = <6>;
++                                      label = "piglow:green:led6";
++                              };
++                              led@7 {
++                                      reg = <7>;
++                                      label = "piglow:red:led7";
++                              };
++                              led@8 {
++                                      reg = <8>;
++                                      label = "piglow:orange:led8";
++                              };
++                              led@9 {
++                                      reg = <9>;
++                                      label = "piglow:yellow:led9";
++                              };
++                              led@10 {
++                                      reg = <10>;
++                                      label = "piglow:white:led10";
++                              };
++                              led@11 {
++                                      reg = <11>;
++                                      label = "piglow:white:led11";
++                              };
++                              led@12 {
++                                      reg = <12>;
++                                      label = "piglow:blue:led12";
++                              };
++                              led@13 {
++                                      reg = <13>;
++                                      label = "piglow:white:led13";
++                              };
++                              led@14 {
++                                      reg = <14>;
++                                      label = "piglow:green:led14";
++                              };
++                              led@15 {
++                                      reg = <15>;
++                                      label = "piglow:blue:led15";
++                              };
++                              led@16 {
++                                      reg = <16>;
++                                      label = "piglow:yellow:led16";
++                              };
++                              led@17 {
++                                      reg = <17>;
++                                      label = "piglow:orange:led17";
++                              };
++                              led@18 {
++                                      reg = <18>;
++                                      label = "piglow:red:led18";
++                              };
++                      };
++              };
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0372-sound-Fixes-for-audioinjector-octo-under-4.19.patch b/target/linux/brcm2708/patches-4.19/950-0372-sound-Fixes-for-audioinjector-octo-under-4.19.patch
deleted file mode 100644 (file)
index 27c81bc..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-From d003eff5bc4d19902867ad585292780a94746705 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 21 Mar 2019 11:19:46 +0000
-Subject: [PATCH] sound: Fixes for audioinjector-octo under 4.19
-
-1. Move the DT alias declaration to the I2C shim in the cases
-where the shim is enabled. This works around a problem caused by a
-4.19 commit [1] that generates DT/OF uevents for I2C drivers.
-
-2. Fix the diagnostics in an error path of the soundcard driver to
-correctly identify the reason for the failure to load.
-
-3. Move the declaration of the clock node in the overlay outside
-the I2C node to avoid warnings.
-
-4. Sort the overlay nodes so that dependencies are only to earlier
-fragments, in an attempt to get runtime dtoverlay application to
-work (it still doesn't...)
-
-See: https://github.com/Audio-Injector/Octo/issues/14
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
-
-[1] af503716ac14 ("i2c: core: report OF style module alias for devices registered via OF")
----
- .../overlays/audioinjector-addons-overlay.dts | 19 ++++++++++++-------
- sound/soc/bcm/audioinjector-octo-soundcard.c  |  2 +-
- sound/soc/codecs/cs42xx8-i2c.c                |  7 +++++++
- sound/soc/codecs/cs42xx8.c                    |  2 ++
- 4 files changed, 22 insertions(+), 8 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-@@ -13,6 +13,17 @@
-       };
-       fragment@1 {
-+              target-path = "/";
-+              __overlay__ {
-+                      cs42448_mclk: codec-mclk {
-+                              compatible = "fixed-clock";
-+                              #clock-cells = <0>;
-+                              clock-frequency = <49152000>;
-+                      };
-+              };
-+      };
-+
-+      fragment@2 {
-               target = <&i2c1>;
-               __overlay__ {
-                       #address-cells = <1>;
-@@ -27,16 +38,10 @@
-                               clock-names = "mclk";
-                               status = "okay";
-                       };
--
--                      cs42448_mclk: codec-mclk {
--                              compatible = "fixed-clock";
--                              #clock-cells = <0>;
--                              clock-frequency = <49152000>;
--                      };
-               };
-       };
--      fragment@2 {
-+      fragment@3 {
-               target = <&sound>;
-               snd: __overlay__ {
-                       compatible = "ai,audioinjector-octo-soundcard";
---- a/sound/soc/bcm/audioinjector-octo-soundcard.c
-+++ b/sound/soc/bcm/audioinjector-octo-soundcard.c
-@@ -297,7 +297,7 @@ static int audioinjector_octo_probe(stru
-                       dai->codec_name = NULL;
-                       dai->codec_of_node = codec_node;
-               } else
--                      if (!dai->cpu_of_node) {
-+                      if (!i2s_node) {
-                               dev_err(&pdev->dev,
-                               "i2s-controller missing or invalid in DT\n");
-                               return -EINVAL;
---- a/sound/soc/codecs/cs42xx8-i2c.c
-+++ b/sound/soc/codecs/cs42xx8-i2c.c
-@@ -45,6 +45,13 @@ static struct i2c_device_id cs42xx8_i2c_
- };
- MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
-+const struct of_device_id cs42xx8_of_match[] = {
-+      { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
-+      { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
-+
- static struct i2c_driver cs42xx8_i2c_driver = {
-       .driver = {
-               .name = "cs42xx8",
---- a/sound/soc/codecs/cs42xx8.c
-+++ b/sound/soc/codecs/cs42xx8.c
-@@ -436,8 +436,10 @@ const struct of_device_id cs42xx8_of_mat
-       { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
-       { /* sentinel */ }
- };
-+#if !IS_ENABLED(CONFIG_SND_SOC_CS42XX8_I2C)
- MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
- EXPORT_SYMBOL_GPL(cs42xx8_of_match);
-+#endif
- int cs42xx8_probe(struct device *dev, struct regmap *regmap)
- {
diff --git a/target/linux/brcm2708/patches-4.19/950-0372-staging-bcm2835-audio-Clean-up-mutex-locks.patch b/target/linux/brcm2708/patches-4.19/950-0372-staging-bcm2835-audio-Clean-up-mutex-locks.patch
new file mode 100644 (file)
index 0000000..531fe9e
--- /dev/null
@@ -0,0 +1,301 @@
+From 96588b9ccaddd69a832a07e2e3f2f3299e6d6c3a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:30 +0200
+Subject: [PATCH] staging: bcm2835-audio: Clean up mutex locks
+
+commit ce4bb1aa271a97047b80ac917a5d91b54925913b upstream.
+
+snd-bcm2835 driver takes the lock with mutex_lock_interruptible() in
+all places, which don't make sense.  Replace them with the simple
+mutex_lock().
+
+Also taking a mutex lock right after creating it for each PCM object
+is nonsense, too.  It cannot be racy at that point.  We can get rid of
+it.
+
+Last but not least, initializing chip->audio_mutex at each place is
+error-prone.  Initialize properly at creating the chip object in
+snd_bcm2835_create() instead.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 18 +++----
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 33 ++-----------
+ .../bcm2835-audio/bcm2835-vchiq.c             | 47 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.c     |  1 +
+ 4 files changed, 20 insertions(+), 79 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -77,8 +77,7 @@ static int snd_bcm2835_ctl_get(struct sn
+ {
+       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+-      if (mutex_lock_interruptible(&chip->audio_mutex))
+-              return -EINTR;
++      mutex_lock(&chip->audio_mutex);
+       BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
+@@ -99,8 +98,7 @@ static int snd_bcm2835_ctl_put(struct sn
+       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+       int changed = 0;
+-      if (mutex_lock_interruptible(&chip->audio_mutex))
+-              return -EINTR;
++      mutex_lock(&chip->audio_mutex);
+       if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
+               audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
+@@ -187,8 +185,7 @@ static int snd_bcm2835_spdif_default_get
+       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+       int i;
+-      if (mutex_lock_interruptible(&chip->audio_mutex))
+-              return -EINTR;
++      mutex_lock(&chip->audio_mutex);
+       for (i = 0; i < 4; i++)
+               ucontrol->value.iec958.status[i] =
+@@ -205,8 +202,7 @@ static int snd_bcm2835_spdif_default_put
+       unsigned int val = 0;
+       int i, change;
+-      if (mutex_lock_interruptible(&chip->audio_mutex))
+-              return -EINTR;
++      mutex_lock(&chip->audio_mutex);
+       for (i = 0; i < 4; i++)
+               val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
+@@ -251,8 +247,7 @@ static int snd_bcm2835_spdif_stream_get(
+       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+       int i;
+-      if (mutex_lock_interruptible(&chip->audio_mutex))
+-              return -EINTR;
++      mutex_lock(&chip->audio_mutex);
+       for (i = 0; i < 4; i++)
+               ucontrol->value.iec958.status[i] =
+@@ -269,8 +264,7 @@ static int snd_bcm2835_spdif_stream_put(
+       unsigned int val = 0;
+       int i, change;
+-      if (mutex_lock_interruptible(&chip->audio_mutex))
+-              return -EINTR;
++      mutex_lock(&chip->audio_mutex);
+       for (i = 0; i < 4; i++)
+               val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -99,10 +99,7 @@ static int snd_bcm2835_playback_open_gen
+       int idx;
+       int err;
+-      if (mutex_lock_interruptible(&chip->audio_mutex)) {
+-              audio_error("Interrupted whilst waiting for lock\n");
+-              return -EINTR;
+-      }
++      mutex_lock(&chip->audio_mutex);
+       audio_info("Alsa open (%d)\n", substream->number);
+       idx = substream->number;
+@@ -194,10 +191,7 @@ static int snd_bcm2835_playback_close(st
+       struct bcm2835_alsa_stream *alsa_stream;
+       chip = snd_pcm_substream_chip(substream);
+-      if (mutex_lock_interruptible(&chip->audio_mutex)) {
+-              audio_error("Interrupted whilst waiting for lock\n");
+-              return -EINTR;
+-      }
++      mutex_lock(&chip->audio_mutex);
+       runtime = substream->runtime;
+       alsa_stream = runtime->private_data;
+@@ -274,8 +268,7 @@ static int snd_bcm2835_pcm_prepare(struc
+       int channels;
+       int err;
+-      if (mutex_lock_interruptible(&chip->audio_mutex))
+-              return -EINTR;
++      mutex_lock(&chip->audio_mutex);
+       /* notify the vchiq that it should enter spdif passthrough mode by
+        * setting channels=0 (see
+@@ -449,14 +442,9 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+       struct snd_pcm *pcm;
+       int err;
+-      mutex_init(&chip->audio_mutex);
+-      if (mutex_lock_interruptible(&chip->audio_mutex)) {
+-              audio_error("Interrupted whilst waiting for lock\n");
+-              return -EINTR;
+-      }
+       err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
+       if (err < 0)
+-              goto out;
++              return err;
+       pcm->private_data = chip;
+       strcpy(pcm->name, "bcm2835 ALSA");
+       chip->pcm = pcm;
+@@ -474,9 +462,6 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+                                             snd_bcm2835_playback_hw.buffer_bytes_max,
+                                             snd_bcm2835_playback_hw.buffer_bytes_max);
+-out:
+-      mutex_unlock(&chip->audio_mutex);
+-
+       return 0;
+ }
+@@ -485,13 +470,9 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+       struct snd_pcm *pcm;
+       int err;
+-      if (mutex_lock_interruptible(&chip->audio_mutex)) {
+-              audio_error("Interrupted whilst waiting for lock\n");
+-              return -EINTR;
+-      }
+       err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
+       if (err < 0)
+-              goto out;
++              return err;
+       pcm->private_data = chip;
+       strcpy(pcm->name, "bcm2835 IEC958/HDMI");
+@@ -504,8 +485,6 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+               snd_dma_continuous_data(GFP_KERNEL),
+               snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
+-out:
+-      mutex_unlock(&chip->audio_mutex);
+       return 0;
+ }
+@@ -518,8 +497,6 @@ int snd_bcm2835_new_simple_pcm(struct bc
+       struct snd_pcm *pcm;
+       int err;
+-      mutex_init(&chip->audio_mutex);
+-
+       err = snd_pcm_new(chip->card, name, 0, numchannels,
+                         0, &pcm);
+       if (err)
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -319,11 +319,7 @@ static int vc_vchi_audio_deinit(struct b
+       }
+       LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+-                      instance->num_connections);
+-              return -EINTR;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       /* Close all VCHI service connections */
+       for (i = 0; i < instance->num_connections; i++) {
+@@ -434,11 +430,7 @@ int bcm2835_audio_open(struct bcm2835_al
+       instance = alsa_stream->instance;
+       LOG_DBG(" instance (%p)\n", instance);
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
+-              ret = -EINTR;
+-              goto free_wq;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       vchi_service_use(instance->vchi_handle[0]);
+       m.type = VC_AUDIO_MSG_TYPE_OPEN;
+@@ -479,11 +471,7 @@ static int bcm2835_audio_set_ctls_chan(s
+       LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
+                chip->dest, chip->volume);
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+-                      instance->num_connections);
+-              return -EINTR;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       vchi_service_use(instance->vchi_handle[0]);
+       instance->result = -1;
+@@ -569,10 +557,7 @@ int bcm2835_audio_set_params(struct bcm2
+               return -EINVAL;
+       }
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
+-              return -EINTR;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       vchi_service_use(instance->vchi_handle[0]);
+       instance->result = -1;
+@@ -629,11 +614,7 @@ static int bcm2835_audio_start_worker(st
+       int status;
+       int ret;
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+-                      instance->num_connections);
+-              return -EINTR;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       vchi_service_use(instance->vchi_handle[0]);
+       m.type = VC_AUDIO_MSG_TYPE_START;
+@@ -665,11 +646,7 @@ static int bcm2835_audio_stop_worker(str
+       int status;
+       int ret;
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+-                      instance->num_connections);
+-              return -EINTR;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       vchi_service_use(instance->vchi_handle[0]);
+       m.type = VC_AUDIO_MSG_TYPE_STOP;
+@@ -704,11 +681,7 @@ int bcm2835_audio_close(struct bcm2835_a
+       my_workqueue_quit(alsa_stream);
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+-                      instance->num_connections);
+-              return -EINTR;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       vchi_service_use(instance->vchi_handle[0]);
+       m.type = VC_AUDIO_MSG_TYPE_CLOSE;
+@@ -761,11 +734,7 @@ static int bcm2835_audio_write_worker(st
+       LOG_INFO(" Writing %d bytes from %p\n", count, src);
+-      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+-              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+-                      instance->num_connections);
+-              return -EINTR;
+-      }
++      mutex_lock(&instance->vchi_mutex);
+       vchi_service_use(instance->vchi_handle[0]);
+       if (instance->peer_version == 0 &&
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -149,6 +149,7 @@ static int snd_bcm2835_create(struct snd
+               return -ENOMEM;
+       chip->card = card;
++      mutex_init(&chip->audio_mutex);
+       chip->vchi_ctx = devres_find(card->dev->parent,
+                                    bcm2835_devm_free_vchi_ctx, NULL, NULL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0373-overlays-Add-PiGlow-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0373-overlays-Add-PiGlow-overlay.patch
deleted file mode 100644 (file)
index 4c3e76a..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-From 615467f56356a2054d3a86854d391b7a2e0d5811 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Mon, 29 Apr 2019 19:35:33 +0200
-Subject: [PATCH] overlays: Add PiGlow overlay
-
-The PiGlow is a small add-on board for the Raspberry Pi that provides
-18 individually controllable LEDs (SN3218) and uses the following pins:
-
-P1 & P17 (3V3)
-P2 (5V)
-P3 (SDA)
-P5 (SCL)
-P14 (GND)
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             |  6 ++
- arch/arm/boot/dts/overlays/piglow-overlay.dts | 97 +++++++++++++++++++
- 3 files changed, 104 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/piglow-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -97,6 +97,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       pi3-disable-wifi.dtbo \
-       pi3-miniuart-bt.dtbo \
-       pibell.dtbo \
-+      piglow.dtbo \
-       piscreen.dtbo \
-       piscreen2r.dtbo \
-       pisound.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1532,6 +1532,12 @@ Params: alsaname                Set the
-                                 "PiBell")
-+Name:   piglow
-+Info:   Configures the PiGlow by pimoroni.com
-+Load:   dtoverlay=piglow
-+Params: <None>
-+
-+
- Name:   piscreen
- Info:   PiScreen display by OzzMaker.com
- Load:   dtoverlay=piscreen,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
-@@ -0,0 +1,97 @@
-+// Definitions for SN3218 LED driver from Si-En Technology on PiGlow
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2708";
-+
-+      fragment@0 {
-+              target = <&i2c_arm>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      sn3218@54 {
-+                              compatible = "si-en,sn3218";
-+                              reg = <0x54>;
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              status = "okay";
-+
-+                              led@1 {
-+                                      reg = <1>;
-+                                      label = "piglow:red:led1";
-+                              };
-+                              led@2 {
-+                                      reg = <2>;
-+                                      label = "piglow:orange:led2";
-+                              };
-+                              led@3 {
-+                                      reg = <3>;
-+                                      label = "piglow:yellow:led3";
-+                              };
-+                              led@4 {
-+                                      reg = <4>;
-+                                      label = "piglow:green:led4";
-+                              };
-+                              led@5 {
-+                                      reg = <5>;
-+                                      label = "piglow:blue:led5";
-+                              };
-+                              led@6 {
-+                                      reg = <6>;
-+                                      label = "piglow:green:led6";
-+                              };
-+                              led@7 {
-+                                      reg = <7>;
-+                                      label = "piglow:red:led7";
-+                              };
-+                              led@8 {
-+                                      reg = <8>;
-+                                      label = "piglow:orange:led8";
-+                              };
-+                              led@9 {
-+                                      reg = <9>;
-+                                      label = "piglow:yellow:led9";
-+                              };
-+                              led@10 {
-+                                      reg = <10>;
-+                                      label = "piglow:white:led10";
-+                              };
-+                              led@11 {
-+                                      reg = <11>;
-+                                      label = "piglow:white:led11";
-+                              };
-+                              led@12 {
-+                                      reg = <12>;
-+                                      label = "piglow:blue:led12";
-+                              };
-+                              led@13 {
-+                                      reg = <13>;
-+                                      label = "piglow:white:led13";
-+                              };
-+                              led@14 {
-+                                      reg = <14>;
-+                                      label = "piglow:green:led14";
-+                              };
-+                              led@15 {
-+                                      reg = <15>;
-+                                      label = "piglow:blue:led15";
-+                              };
-+                              led@16 {
-+                                      reg = <16>;
-+                                      label = "piglow:yellow:led16";
-+                              };
-+                              led@17 {
-+                                      reg = <17>;
-+                                      label = "piglow:orange:led17";
-+                              };
-+                              led@18 {
-+                                      reg = <18>;
-+                                      label = "piglow:red:led18";
-+                              };
-+                      };
-+              };
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0373-staging-bcm2835-audio-Remove-redundant-spdif-stream-.patch b/target/linux/brcm2708/patches-4.19/950-0373-staging-bcm2835-audio-Remove-redundant-spdif-stream-.patch
new file mode 100644 (file)
index 0000000..ac5c0a0
--- /dev/null
@@ -0,0 +1,89 @@
+From a1a77a925422be3f0c48002c2aa6c6d898a37f95 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:31 +0200
+Subject: [PATCH] staging: bcm2835-audio: Remove redundant spdif stream
+ ctls
+
+commit ab91e26229eaca2832df51e13c1285aea3be33ab upstream.
+
+The "IEC958 Playback Stream" control does basically the very same
+thing as "IEC958 Playback Default" redundantly.  The former should
+have been stream-specific and restored after closing the stream, but
+we don't do in that way.
+
+Since it's nothing but confusion, remove this fake.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 51 -------------------
+ 1 file changed, 51 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -233,48 +233,6 @@ static int snd_bcm2835_spdif_mask_get(st
+       return 0;
+ }
+-static int snd_bcm2835_spdif_stream_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 snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol,
+-      struct snd_ctl_elem_value *ucontrol)
+-{
+-      struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+-      int i;
+-
+-      mutex_lock(&chip->audio_mutex);
+-
+-      for (i = 0; i < 4; i++)
+-              ucontrol->value.iec958.status[i] =
+-              (chip->spdif_status >> (i * 8)) & 0xff;
+-
+-      mutex_unlock(&chip->audio_mutex);
+-      return 0;
+-}
+-
+-static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol,
+-      struct snd_ctl_elem_value *ucontrol)
+-{
+-      struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+-      unsigned int val = 0;
+-      int i, change;
+-
+-      mutex_lock(&chip->audio_mutex);
+-
+-      for (i = 0; i < 4; i++)
+-              val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
+-      change = val != chip->spdif_status;
+-      chip->spdif_status = val;
+-
+-      mutex_unlock(&chip->audio_mutex);
+-      return change;
+-}
+-
+ static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -290,15 +248,6 @@ static struct snd_kcontrol_new snd_bcm28
+               .info = snd_bcm2835_spdif_mask_info,
+               .get = snd_bcm2835_spdif_mask_get,
+       },
+-      {
+-              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+-              SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+-              .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+-              .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
+-              .info = snd_bcm2835_spdif_stream_info,
+-              .get = snd_bcm2835_spdif_stream_get,
+-              .put = snd_bcm2835_spdif_stream_put,
+-      },
+ };
+ int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
diff --git a/target/linux/brcm2708/patches-4.19/950-0374-staging-bcm2835-audio-Clean-up-include-files-in-bcm2.patch b/target/linux/brcm2708/patches-4.19/950-0374-staging-bcm2835-audio-Clean-up-include-files-in-bcm2.patch
new file mode 100644 (file)
index 0000000..e1cf501
--- /dev/null
@@ -0,0 +1,43 @@
+From 8eb8e04a27188f6abc22d09b4a1fffbec10d45f4 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:32 +0200
+Subject: [PATCH] staging: bcm2835-audio: Clean up include files in
+ bcm2835-ctl.c
+
+commit 821950d3da4bf97bcfedcb812176a0f26b833db0 upstream.
+
+Only a few of them are really needed.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c     | 15 ---------------
+ 1 file changed, 15 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -1,23 +1,8 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
+-#include <linux/platform_device.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/jiffies.h>
+-#include <linux/slab.h>
+-#include <linux/time.h>
+-#include <linux/wait.h>
+-#include <linux/delay.h>
+-#include <linux/moduleparam.h>
+-#include <linux/sched.h>
+-
+ #include <sound/core.h>
+ #include <sound/control.h>
+-#include <sound/pcm.h>
+-#include <sound/pcm_params.h>
+-#include <sound/rawmidi.h>
+-#include <sound/initval.h>
+ #include <sound/tlv.h>
+ #include <sound/asoundef.h>
diff --git a/target/linux/brcm2708/patches-4.19/950-0374-staging-bcm2835-audio-Clean-up-mutex-locks.patch b/target/linux/brcm2708/patches-4.19/950-0374-staging-bcm2835-audio-Clean-up-mutex-locks.patch
deleted file mode 100644 (file)
index 531fe9e..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-From 96588b9ccaddd69a832a07e2e3f2f3299e6d6c3a Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:30 +0200
-Subject: [PATCH] staging: bcm2835-audio: Clean up mutex locks
-
-commit ce4bb1aa271a97047b80ac917a5d91b54925913b upstream.
-
-snd-bcm2835 driver takes the lock with mutex_lock_interruptible() in
-all places, which don't make sense.  Replace them with the simple
-mutex_lock().
-
-Also taking a mutex lock right after creating it for each PCM object
-is nonsense, too.  It cannot be racy at that point.  We can get rid of
-it.
-
-Last but not least, initializing chip->audio_mutex at each place is
-error-prone.  Initialize properly at creating the chip object in
-snd_bcm2835_create() instead.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 18 +++----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 33 ++-----------
- .../bcm2835-audio/bcm2835-vchiq.c             | 47 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.c     |  1 +
- 4 files changed, 20 insertions(+), 79 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -77,8 +77,7 @@ static int snd_bcm2835_ctl_get(struct sn
- {
-       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
--      if (mutex_lock_interruptible(&chip->audio_mutex))
--              return -EINTR;
-+      mutex_lock(&chip->audio_mutex);
-       BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
-@@ -99,8 +98,7 @@ static int snd_bcm2835_ctl_put(struct sn
-       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
-       int changed = 0;
--      if (mutex_lock_interruptible(&chip->audio_mutex))
--              return -EINTR;
-+      mutex_lock(&chip->audio_mutex);
-       if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
-               audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
-@@ -187,8 +185,7 @@ static int snd_bcm2835_spdif_default_get
-       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
-       int i;
--      if (mutex_lock_interruptible(&chip->audio_mutex))
--              return -EINTR;
-+      mutex_lock(&chip->audio_mutex);
-       for (i = 0; i < 4; i++)
-               ucontrol->value.iec958.status[i] =
-@@ -205,8 +202,7 @@ static int snd_bcm2835_spdif_default_put
-       unsigned int val = 0;
-       int i, change;
--      if (mutex_lock_interruptible(&chip->audio_mutex))
--              return -EINTR;
-+      mutex_lock(&chip->audio_mutex);
-       for (i = 0; i < 4; i++)
-               val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
-@@ -251,8 +247,7 @@ static int snd_bcm2835_spdif_stream_get(
-       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
-       int i;
--      if (mutex_lock_interruptible(&chip->audio_mutex))
--              return -EINTR;
-+      mutex_lock(&chip->audio_mutex);
-       for (i = 0; i < 4; i++)
-               ucontrol->value.iec958.status[i] =
-@@ -269,8 +264,7 @@ static int snd_bcm2835_spdif_stream_put(
-       unsigned int val = 0;
-       int i, change;
--      if (mutex_lock_interruptible(&chip->audio_mutex))
--              return -EINTR;
-+      mutex_lock(&chip->audio_mutex);
-       for (i = 0; i < 4; i++)
-               val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -99,10 +99,7 @@ static int snd_bcm2835_playback_open_gen
-       int idx;
-       int err;
--      if (mutex_lock_interruptible(&chip->audio_mutex)) {
--              audio_error("Interrupted whilst waiting for lock\n");
--              return -EINTR;
--      }
-+      mutex_lock(&chip->audio_mutex);
-       audio_info("Alsa open (%d)\n", substream->number);
-       idx = substream->number;
-@@ -194,10 +191,7 @@ static int snd_bcm2835_playback_close(st
-       struct bcm2835_alsa_stream *alsa_stream;
-       chip = snd_pcm_substream_chip(substream);
--      if (mutex_lock_interruptible(&chip->audio_mutex)) {
--              audio_error("Interrupted whilst waiting for lock\n");
--              return -EINTR;
--      }
-+      mutex_lock(&chip->audio_mutex);
-       runtime = substream->runtime;
-       alsa_stream = runtime->private_data;
-@@ -274,8 +268,7 @@ static int snd_bcm2835_pcm_prepare(struc
-       int channels;
-       int err;
--      if (mutex_lock_interruptible(&chip->audio_mutex))
--              return -EINTR;
-+      mutex_lock(&chip->audio_mutex);
-       /* notify the vchiq that it should enter spdif passthrough mode by
-        * setting channels=0 (see
-@@ -449,14 +442,9 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
-       struct snd_pcm *pcm;
-       int err;
--      mutex_init(&chip->audio_mutex);
--      if (mutex_lock_interruptible(&chip->audio_mutex)) {
--              audio_error("Interrupted whilst waiting for lock\n");
--              return -EINTR;
--      }
-       err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
-       if (err < 0)
--              goto out;
-+              return err;
-       pcm->private_data = chip;
-       strcpy(pcm->name, "bcm2835 ALSA");
-       chip->pcm = pcm;
-@@ -474,9 +462,6 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
-                                             snd_bcm2835_playback_hw.buffer_bytes_max,
-                                             snd_bcm2835_playback_hw.buffer_bytes_max);
--out:
--      mutex_unlock(&chip->audio_mutex);
--
-       return 0;
- }
-@@ -485,13 +470,9 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
-       struct snd_pcm *pcm;
-       int err;
--      if (mutex_lock_interruptible(&chip->audio_mutex)) {
--              audio_error("Interrupted whilst waiting for lock\n");
--              return -EINTR;
--      }
-       err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
-       if (err < 0)
--              goto out;
-+              return err;
-       pcm->private_data = chip;
-       strcpy(pcm->name, "bcm2835 IEC958/HDMI");
-@@ -504,8 +485,6 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-               snd_dma_continuous_data(GFP_KERNEL),
-               snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
--out:
--      mutex_unlock(&chip->audio_mutex);
-       return 0;
- }
-@@ -518,8 +497,6 @@ int snd_bcm2835_new_simple_pcm(struct bc
-       struct snd_pcm *pcm;
-       int err;
--      mutex_init(&chip->audio_mutex);
--
-       err = snd_pcm_new(chip->card, name, 0, numchannels,
-                         0, &pcm);
-       if (err)
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -319,11 +319,7 @@ static int vc_vchi_audio_deinit(struct b
-       }
-       LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
--                      instance->num_connections);
--              return -EINTR;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       /* Close all VCHI service connections */
-       for (i = 0; i < instance->num_connections; i++) {
-@@ -434,11 +430,7 @@ int bcm2835_audio_open(struct bcm2835_al
-       instance = alsa_stream->instance;
-       LOG_DBG(" instance (%p)\n", instance);
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
--              ret = -EINTR;
--              goto free_wq;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       vchi_service_use(instance->vchi_handle[0]);
-       m.type = VC_AUDIO_MSG_TYPE_OPEN;
-@@ -479,11 +471,7 @@ static int bcm2835_audio_set_ctls_chan(s
-       LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
-                chip->dest, chip->volume);
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
--                      instance->num_connections);
--              return -EINTR;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       vchi_service_use(instance->vchi_handle[0]);
-       instance->result = -1;
-@@ -569,10 +557,7 @@ int bcm2835_audio_set_params(struct bcm2
-               return -EINVAL;
-       }
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
--              return -EINTR;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       vchi_service_use(instance->vchi_handle[0]);
-       instance->result = -1;
-@@ -629,11 +614,7 @@ static int bcm2835_audio_start_worker(st
-       int status;
-       int ret;
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
--                      instance->num_connections);
--              return -EINTR;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       vchi_service_use(instance->vchi_handle[0]);
-       m.type = VC_AUDIO_MSG_TYPE_START;
-@@ -665,11 +646,7 @@ static int bcm2835_audio_stop_worker(str
-       int status;
-       int ret;
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
--                      instance->num_connections);
--              return -EINTR;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       vchi_service_use(instance->vchi_handle[0]);
-       m.type = VC_AUDIO_MSG_TYPE_STOP;
-@@ -704,11 +681,7 @@ int bcm2835_audio_close(struct bcm2835_a
-       my_workqueue_quit(alsa_stream);
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
--                      instance->num_connections);
--              return -EINTR;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       vchi_service_use(instance->vchi_handle[0]);
-       m.type = VC_AUDIO_MSG_TYPE_CLOSE;
-@@ -761,11 +734,7 @@ static int bcm2835_audio_write_worker(st
-       LOG_INFO(" Writing %d bytes from %p\n", count, src);
--      if (mutex_lock_interruptible(&instance->vchi_mutex)) {
--              LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
--                      instance->num_connections);
--              return -EINTR;
--      }
-+      mutex_lock(&instance->vchi_mutex);
-       vchi_service_use(instance->vchi_handle[0]);
-       if (instance->peer_version == 0 &&
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -149,6 +149,7 @@ static int snd_bcm2835_create(struct snd
-               return -ENOMEM;
-       chip->card = card;
-+      mutex_init(&chip->audio_mutex);
-       chip->vchi_ctx = devres_find(card->dev->parent,
-                                    bcm2835_devm_free_vchi_ctx, NULL, NULL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0375-staging-bcm2835-audio-Remove-redundant-spdif-stream-.patch b/target/linux/brcm2708/patches-4.19/950-0375-staging-bcm2835-audio-Remove-redundant-spdif-stream-.patch
deleted file mode 100644 (file)
index ac5c0a0..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-From a1a77a925422be3f0c48002c2aa6c6d898a37f95 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:31 +0200
-Subject: [PATCH] staging: bcm2835-audio: Remove redundant spdif stream
- ctls
-
-commit ab91e26229eaca2832df51e13c1285aea3be33ab upstream.
-
-The "IEC958 Playback Stream" control does basically the very same
-thing as "IEC958 Playback Default" redundantly.  The former should
-have been stream-specific and restored after closing the stream, but
-we don't do in that way.
-
-Since it's nothing but confusion, remove this fake.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 51 -------------------
- 1 file changed, 51 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -233,48 +233,6 @@ static int snd_bcm2835_spdif_mask_get(st
-       return 0;
- }
--static int snd_bcm2835_spdif_stream_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 snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol,
--      struct snd_ctl_elem_value *ucontrol)
--{
--      struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
--      int i;
--
--      mutex_lock(&chip->audio_mutex);
--
--      for (i = 0; i < 4; i++)
--              ucontrol->value.iec958.status[i] =
--              (chip->spdif_status >> (i * 8)) & 0xff;
--
--      mutex_unlock(&chip->audio_mutex);
--      return 0;
--}
--
--static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol,
--      struct snd_ctl_elem_value *ucontrol)
--{
--      struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
--      unsigned int val = 0;
--      int i, change;
--
--      mutex_lock(&chip->audio_mutex);
--
--      for (i = 0; i < 4; i++)
--              val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
--      change = val != chip->spdif_status;
--      chip->spdif_status = val;
--
--      mutex_unlock(&chip->audio_mutex);
--      return change;
--}
--
- static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
-@@ -290,15 +248,6 @@ static struct snd_kcontrol_new snd_bcm28
-               .info = snd_bcm2835_spdif_mask_info,
-               .get = snd_bcm2835_spdif_mask_get,
-       },
--      {
--              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
--              SNDRV_CTL_ELEM_ACCESS_INACTIVE,
--              .iface = SNDRV_CTL_ELEM_IFACE_PCM,
--              .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
--              .info = snd_bcm2835_spdif_stream_info,
--              .get = snd_bcm2835_spdif_stream_get,
--              .put = snd_bcm2835_spdif_stream_put,
--      },
- };
- int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
diff --git a/target/linux/brcm2708/patches-4.19/950-0375-staging-bcm2835-audio-Remove-redundant-substream-mas.patch b/target/linux/brcm2708/patches-4.19/950-0375-staging-bcm2835-audio-Remove-redundant-substream-mas.patch
new file mode 100644 (file)
index 0000000..b2af974
--- /dev/null
@@ -0,0 +1,111 @@
+From 1120b4699738a3ee748314c433a96e45182a3411 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:33 +0200
+Subject: [PATCH] staging: bcm2835-audio: Remove redundant substream
+ mask checks
+
+commit 14b1f4cba853a11c7b381ad919622f38eb194bd7 upstream.
+
+The avail_substreams bit mask is checked for the possible racy
+accesses, but this cannot happen in practice; i.e. the assignment and
+the check are superfluous.
+
+Let's rip them off.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c   |  2 --
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c   |  8 --------
+ .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 17 +++++++----------
+ .../vc04_services/bcm2835-audio/bcm2835.c       |  5 +----
+ .../vc04_services/bcm2835-audio/bcm2835.h       |  2 --
+ 5 files changed, 8 insertions(+), 26 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -64,8 +64,6 @@ static int snd_bcm2835_ctl_get(struct sn
+       mutex_lock(&chip->audio_mutex);
+-      BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
+-
+       if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
+               ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
+       else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -118,14 +118,6 @@ static int snd_bcm2835_playback_open_gen
+               goto out;
+       }
+-      /* Check if we are ready */
+-      if (!(chip->avail_substreams & (1 << idx))) {
+-              /* We are not ready yet */
+-              audio_error("substream(%d) device is not ready yet\n", idx);
+-              err = -EAGAIN;
+-              goto out;
+-      }
+-
+       alsa_stream = kzalloc(sizeof(*alsa_stream), GFP_KERNEL);
+       if (!alsa_stream) {
+               err = -ENOMEM;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -523,16 +523,13 @@ int bcm2835_audio_set_ctls(struct bcm283
+       /* change ctls for all substreams */
+       for (i = 0; i < MAX_SUBSTREAMS; i++) {
+-              if (chip->avail_substreams & (1 << i)) {
+-                      if (!chip->alsa_stream[i]) {
+-                              LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i, chip->alsa_stream[i], chip->avail_substreams);
+-                              ret = 0;
+-                      } else if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
+-                              LOG_ERR("Couldn't set the controls for stream %d\n", i);
+-                              ret = -1;
+-                      } else {
+-                              LOG_DBG(" Controls set for stream %d\n", i);
+-                      }
++              if (!chip->alsa_stream[i])
++                      continue;
++              if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
++                      LOG_ERR("Couldn't set the controls for stream %d\n", i);
++                      ret = -1;
++              } else {
++                      LOG_DBG(" Controls set for stream %d\n", i);
+               }
+       }
+       return ret;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -280,7 +280,7 @@ static int snd_add_child_device(struct d
+       struct snd_card *card;
+       struct device *child;
+       struct bcm2835_chip *chip;
+-      int err, i;
++      int err;
+       child = snd_create_device(device, &audio_driver->driver,
+                                 audio_driver->driver.name);
+@@ -325,9 +325,6 @@ static int snd_add_child_device(struct d
+               return err;
+       }
+-      for (i = 0; i < numchans; i++)
+-              chip->avail_substreams |= (1 << i);
+-
+       err = snd_card_register(card);
+       if (err) {
+               dev_err(child, "Failed to register card, error %d\n", err);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -98,8 +98,6 @@ struct bcm2835_chip {
+       struct snd_card *card;
+       struct snd_pcm *pcm;
+       struct snd_pcm *pcm_spdif;
+-      /* Bitmat for valid reg_base and irq numbers */
+-      unsigned int avail_substreams;
+       struct device *dev;
+       struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
diff --git a/target/linux/brcm2708/patches-4.19/950-0376-staging-bcm2835-audio-Clean-up-include-files-in-bcm2.patch b/target/linux/brcm2708/patches-4.19/950-0376-staging-bcm2835-audio-Clean-up-include-files-in-bcm2.patch
deleted file mode 100644 (file)
index e1cf501..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-From 8eb8e04a27188f6abc22d09b4a1fffbec10d45f4 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:32 +0200
-Subject: [PATCH] staging: bcm2835-audio: Clean up include files in
- bcm2835-ctl.c
-
-commit 821950d3da4bf97bcfedcb812176a0f26b833db0 upstream.
-
-Only a few of them are really needed.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c     | 15 ---------------
- 1 file changed, 15 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -1,23 +1,8 @@
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
--#include <linux/platform_device.h>
--#include <linux/init.h>
--#include <linux/io.h>
--#include <linux/jiffies.h>
--#include <linux/slab.h>
--#include <linux/time.h>
--#include <linux/wait.h>
--#include <linux/delay.h>
--#include <linux/moduleparam.h>
--#include <linux/sched.h>
--
- #include <sound/core.h>
- #include <sound/control.h>
--#include <sound/pcm.h>
--#include <sound/pcm_params.h>
--#include <sound/rawmidi.h>
--#include <sound/initval.h>
- #include <sound/tlv.h>
- #include <sound/asoundef.h>
diff --git a/target/linux/brcm2708/patches-4.19/950-0376-staging-bcm2835-audio-Fix-mute-controls-volume-handl.patch b/target/linux/brcm2708/patches-4.19/950-0376-staging-bcm2835-audio-Fix-mute-controls-volume-handl.patch
new file mode 100644 (file)
index 0000000..de29b17
--- /dev/null
@@ -0,0 +1,273 @@
+From 31e4f118a750f4ddb2aeaaf02c5f3630fb50a176 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:34 +0200
+Subject: [PATCH] staging: bcm2835-audio: Fix mute controls, volume
+ handling cleanup
+
+commit 495e5a0d83d3902c741771f267a702ae19da8ab6 upstream.
+
+In the current code, the mute control is dealt in a special manner,
+modifying the current volume and saving the old volume, etc.  This is
+inconsistent (e.g. change the volume while muted, then unmute), and
+way too complex.
+
+Also, the whole volume handling code has conversion between ALSA
+volume and raw volume values, which can lead to another
+inconsistency and complexity.
+
+This patch simplifies these points:
+- The ALSA volume value is saved in chip->volume
+- volume->mute saves the mute state
+- The mute state is evaluated only when the actual volume is passed to
+  the hardware, bcm2835_audio_set_ctls()
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 84 +++++++------------
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  6 +-
+ .../bcm2835-audio/bcm2835-vchiq.c             | 32 ++-----
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  5 +-
+ 4 files changed, 45 insertions(+), 82 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -12,6 +12,21 @@
+ #define CTRL_VOL_MAX 400
+ #define CTRL_VOL_MIN -10239 /* originally -10240 */
++static int bcm2835_audio_set_chip_ctls(struct bcm2835_chip *chip)
++{
++      int i, err = 0;
++
++      /* change ctls for all substreams */
++      for (i = 0; i < MAX_SUBSTREAMS; i++) {
++              if (chip->alsa_stream[i]) {
++                      err = bcm2835_audio_set_ctls(chip->alsa_stream[i]);
++                      if (err < 0)
++                              break;
++              }
++      }
++      return err;
++}
++
+ static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *uinfo)
+ {
+@@ -34,29 +49,6 @@ static int snd_bcm2835_ctl_info(struct s
+       return 0;
+ }
+-/* toggles mute on or off depending on the value of nmute, and returns
+- * 1 if the mute value was changed, otherwise 0
+- */
+-static int toggle_mute(struct bcm2835_chip *chip, int nmute)
+-{
+-      /* if settings are ok, just return 0 */
+-      if (chip->mute == nmute)
+-              return 0;
+-
+-      /* if the sound is muted then we need to unmute */
+-      if (chip->mute == CTRL_VOL_MUTE) {
+-              chip->volume = chip->old_volume; /* copy the old volume back */
+-              audio_info("Unmuting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
+-      } else /* otherwise we mute */ {
+-              chip->old_volume = chip->volume;
+-              chip->volume = 26214; /* set volume to minimum level AKA mute */
+-              audio_info("Muting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
+-      }
+-
+-      chip->mute = nmute;
+-      return 1;
+-}
+-
+ static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -65,7 +57,7 @@ static int snd_bcm2835_ctl_get(struct sn
+       mutex_lock(&chip->audio_mutex);
+       if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
+-              ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
++              ucontrol->value.integer.value[0] = chip->volume;
+       else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
+               ucontrol->value.integer.value[0] = chip->mute;
+       else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
+@@ -79,38 +71,26 @@ static int snd_bcm2835_ctl_put(struct sn
+                               struct snd_ctl_elem_value *ucontrol)
+ {
+       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++      int val, *valp;
+       int changed = 0;
+-      mutex_lock(&chip->audio_mutex);
+-
+-      if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
+-              audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
+-              if (chip->mute == CTRL_VOL_MUTE) {
+-                      /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
+-                      changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
+-                      goto unlock;
+-              }
+-              if (changed || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
+-                      chip->volume = alsa2chip(ucontrol->value.integer.value[0]);
+-                      changed = 1;
+-              }
+-
+-      } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
+-              /* Now implemented */
+-              audio_info(" Mute attempted\n");
+-              changed = toggle_mute(chip, ucontrol->value.integer.value[0]);
++      if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
++              valp = &chip->volume;
++      else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
++              valp = &chip->mute;
++      else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
++              valp = &chip->dest;
++      else
++              return -EINVAL;
+-      } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
+-              if (ucontrol->value.integer.value[0] != chip->dest) {
+-                      chip->dest = ucontrol->value.integer.value[0];
+-                      changed = 1;
+-              }
++      val = ucontrol->value.integer.value[0];
++      mutex_lock(&chip->audio_mutex);
++      if (val != *valp) {
++              *valp = val;
++              changed = 1;
++              if (bcm2835_audio_set_chip_ctls(chip))
++                      dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
+       }
+-
+-      if (changed && bcm2835_audio_set_ctls(chip))
+-              dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
+-
+-unlock:
+       mutex_unlock(&chip->audio_mutex);
+       return changed;
+ }
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -280,7 +280,7 @@ static int snd_bcm2835_pcm_prepare(struc
+       bcm2835_audio_setup(alsa_stream);
+       /* in preparation of the stream, set the controls (volume level) of the stream */
+-      bcm2835_audio_set_ctls(alsa_stream->chip);
++      bcm2835_audio_set_ctls(alsa_stream);
+       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+@@ -441,7 +441,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+       strcpy(pcm->name, "bcm2835 ALSA");
+       chip->pcm = pcm;
+       chip->dest = AUDIO_DEST_AUTO;
+-      chip->volume = alsa2chip(0);
++      chip->volume = 0;
+       chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
+       /* set operators */
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+@@ -498,7 +498,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
+       strcpy(pcm->name, name);
+       chip->pcm = pcm;
+       chip->dest = route;
+-      chip->volume = alsa2chip(0);
++      chip->volume = 0;
+       chip->mute = CTRL_VOL_UNMUTE;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -460,11 +460,11 @@ free_wq:
+       return ret;
+ }
+-static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream,
+-                                     struct bcm2835_chip *chip)
++int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       struct vc_audio_msg m;
+       struct bcm2835_audio_instance *instance = alsa_stream->instance;
++      struct bcm2835_chip *chip = alsa_stream->chip;
+       int status;
+       int ret;
+@@ -478,7 +478,10 @@ static int bcm2835_audio_set_ctls_chan(s
+       m.type = VC_AUDIO_MSG_TYPE_CONTROL;
+       m.u.control.dest = chip->dest;
+-      m.u.control.volume = chip->volume;
++      if (!chip->mute)
++              m.u.control.volume = CHIP_MIN_VOLUME;
++      else
++              m.u.control.volume = alsa2chip(chip->volume);
+       /* Create the message available completion */
+       init_completion(&instance->msg_avail_comp);
+@@ -514,27 +517,6 @@ unlock:
+       return ret;
+ }
+-int bcm2835_audio_set_ctls(struct bcm2835_chip *chip)
+-{
+-      int i;
+-      int ret = 0;
+-
+-      LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);
+-
+-      /* change ctls for all substreams */
+-      for (i = 0; i < MAX_SUBSTREAMS; i++) {
+-              if (!chip->alsa_stream[i])
+-                      continue;
+-              if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
+-                      LOG_ERR("Couldn't set the controls for stream %d\n", i);
+-                      ret = -1;
+-              } else {
+-                      LOG_DBG(" Controls set for stream %d\n", i);
+-              }
+-      }
+-      return ret;
+-}
+-
+ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
+                            unsigned int channels, unsigned int samplerate,
+                            unsigned int bps)
+@@ -548,7 +530,7 @@ int bcm2835_audio_set_params(struct bcm2
+                channels, samplerate, bps);
+       /* resend ctls - alsa_stream may not have been open when first send */
+-      ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);
++      ret = bcm2835_audio_set_ctls(alsa_stream);
+       if (ret) {
+               LOG_ERR(" Alsa controls not supported\n");
+               return -EINVAL;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -74,6 +74,8 @@ enum {
+ // convert chip to alsa volume
+ #define chip2alsa(vol) -(((vol) * 100) >> 8)
++#define CHIP_MIN_VOLUME               26214 /* minimum level aka mute */
++
+ /* Some constants for values .. */
+ enum snd_bcm2835_route {
+       AUDIO_DEST_AUTO = 0,
+@@ -102,7 +104,6 @@ struct bcm2835_chip {
+       struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
+       int volume;
+-      int old_volume; /* stores the volume value whist muted */
+       int dest;
+       int mute;
+@@ -160,7 +161,7 @@ int bcm2835_audio_set_params(struct bcm2
+ int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
+-int bcm2835_audio_set_ctls(struct bcm2835_chip *chip);
++int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
+                       unsigned int count,
+                       void *src);
diff --git a/target/linux/brcm2708/patches-4.19/950-0377-staging-bcm2835-audio-Remove-redundant-function-call.patch b/target/linux/brcm2708/patches-4.19/950-0377-staging-bcm2835-audio-Remove-redundant-function-call.patch
new file mode 100644 (file)
index 0000000..482c9ba
--- /dev/null
@@ -0,0 +1,95 @@
+From 79a3c1a4419b2bf04f6ff5ef84cd74b0456fdd9a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:35 +0200
+Subject: [PATCH] staging: bcm2835-audio: Remove redundant function
+ calls
+
+commit 124950ebe9fa8547c59e8d4acc8d6c59e6278ed6 upstream.
+
+bcm2835_audio_setup(), bcm2835_audio_flush_buffers() and
+bcm2835_audio_flush_playback_buffers() functions do implement
+nothing.
+
+Also, bcm2835_audio_set_ctls() is already called inside
+bcm2835_audio_set_params(), so the later call is superfluous.
+
+This patch removes these superfluous implementations.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  5 -----
+ .../bcm2835-audio/bcm2835-vchiq.c             | 21 -------------------
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  3 ---
+ 3 files changed, 29 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -277,11 +277,6 @@ static int snd_bcm2835_pcm_prepare(struc
+       if (err < 0)
+               audio_error(" error setting hw params\n");
+-      bcm2835_audio_setup(alsa_stream);
+-
+-      /* in preparation of the stream, set the controls (volume level) of the stream */
+-      bcm2835_audio_set_ctls(alsa_stream);
+-
+       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+       alsa_stream->pcm_indirect.hw_buffer_size =
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -580,12 +580,6 @@ unlock:
+       return ret;
+ }
+-int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-
+-      return 0;
+-}
+-
+ static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       struct vc_audio_msg m;
+@@ -774,21 +768,6 @@ unlock:
+       return ret;
+ }
+-/**
+- * Returns all buffers from arm->vc
+- */
+-void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-}
+-
+-/**
+- * Forces VC to flush(drop) its filled playback buffers and
+- * return them the us. (VC->ARM)
+- */
+-void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-}
+-
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       unsigned int count = atomic_read(&alsa_stream->retrieved);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -158,7 +158,6 @@ int bcm2835_audio_close(struct bcm2835_a
+ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
+                            unsigned int channels, unsigned int samplerate,
+                            unsigned int bps);
+-int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
+@@ -167,7 +166,5 @@ int bcm2835_audio_write(struct bcm2835_a
+                       void *src);
+ void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
+-void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream);
+-void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream);
+ #endif /* __SOUND_ARM_BCM2835_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0377-staging-bcm2835-audio-Remove-redundant-substream-mas.patch b/target/linux/brcm2708/patches-4.19/950-0377-staging-bcm2835-audio-Remove-redundant-substream-mas.patch
deleted file mode 100644 (file)
index b2af974..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-From 1120b4699738a3ee748314c433a96e45182a3411 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:33 +0200
-Subject: [PATCH] staging: bcm2835-audio: Remove redundant substream
- mask checks
-
-commit 14b1f4cba853a11c7b381ad919622f38eb194bd7 upstream.
-
-The avail_substreams bit mask is checked for the possible racy
-accesses, but this cannot happen in practice; i.e. the assignment and
-the check are superfluous.
-
-Let's rip them off.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c   |  2 --
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c   |  8 --------
- .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 17 +++++++----------
- .../vc04_services/bcm2835-audio/bcm2835.c       |  5 +----
- .../vc04_services/bcm2835-audio/bcm2835.h       |  2 --
- 5 files changed, 8 insertions(+), 26 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -64,8 +64,6 @@ static int snd_bcm2835_ctl_get(struct sn
-       mutex_lock(&chip->audio_mutex);
--      BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
--
-       if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
-               ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
-       else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -118,14 +118,6 @@ static int snd_bcm2835_playback_open_gen
-               goto out;
-       }
--      /* Check if we are ready */
--      if (!(chip->avail_substreams & (1 << idx))) {
--              /* We are not ready yet */
--              audio_error("substream(%d) device is not ready yet\n", idx);
--              err = -EAGAIN;
--              goto out;
--      }
--
-       alsa_stream = kzalloc(sizeof(*alsa_stream), GFP_KERNEL);
-       if (!alsa_stream) {
-               err = -ENOMEM;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -523,16 +523,13 @@ int bcm2835_audio_set_ctls(struct bcm283
-       /* change ctls for all substreams */
-       for (i = 0; i < MAX_SUBSTREAMS; i++) {
--              if (chip->avail_substreams & (1 << i)) {
--                      if (!chip->alsa_stream[i]) {
--                              LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i, chip->alsa_stream[i], chip->avail_substreams);
--                              ret = 0;
--                      } else if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
--                              LOG_ERR("Couldn't set the controls for stream %d\n", i);
--                              ret = -1;
--                      } else {
--                              LOG_DBG(" Controls set for stream %d\n", i);
--                      }
-+              if (!chip->alsa_stream[i])
-+                      continue;
-+              if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
-+                      LOG_ERR("Couldn't set the controls for stream %d\n", i);
-+                      ret = -1;
-+              } else {
-+                      LOG_DBG(" Controls set for stream %d\n", i);
-               }
-       }
-       return ret;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -280,7 +280,7 @@ static int snd_add_child_device(struct d
-       struct snd_card *card;
-       struct device *child;
-       struct bcm2835_chip *chip;
--      int err, i;
-+      int err;
-       child = snd_create_device(device, &audio_driver->driver,
-                                 audio_driver->driver.name);
-@@ -325,9 +325,6 @@ static int snd_add_child_device(struct d
-               return err;
-       }
--      for (i = 0; i < numchans; i++)
--              chip->avail_substreams |= (1 << i);
--
-       err = snd_card_register(card);
-       if (err) {
-               dev_err(child, "Failed to register card, error %d\n", err);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -98,8 +98,6 @@ struct bcm2835_chip {
-       struct snd_card *card;
-       struct snd_pcm *pcm;
-       struct snd_pcm *pcm_spdif;
--      /* Bitmat for valid reg_base and irq numbers */
--      unsigned int avail_substreams;
-       struct device *dev;
-       struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
diff --git a/target/linux/brcm2708/patches-4.19/950-0378-staging-bcm2835-audio-Fix-mute-controls-volume-handl.patch b/target/linux/brcm2708/patches-4.19/950-0378-staging-bcm2835-audio-Fix-mute-controls-volume-handl.patch
deleted file mode 100644 (file)
index de29b17..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-From 31e4f118a750f4ddb2aeaaf02c5f3630fb50a176 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:34 +0200
-Subject: [PATCH] staging: bcm2835-audio: Fix mute controls, volume
- handling cleanup
-
-commit 495e5a0d83d3902c741771f267a702ae19da8ab6 upstream.
-
-In the current code, the mute control is dealt in a special manner,
-modifying the current volume and saving the old volume, etc.  This is
-inconsistent (e.g. change the volume while muted, then unmute), and
-way too complex.
-
-Also, the whole volume handling code has conversion between ALSA
-volume and raw volume values, which can lead to another
-inconsistency and complexity.
-
-This patch simplifies these points:
-- The ALSA volume value is saved in chip->volume
-- volume->mute saves the mute state
-- The mute state is evaluated only when the actual volume is passed to
-  the hardware, bcm2835_audio_set_ctls()
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 84 +++++++------------
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  6 +-
- .../bcm2835-audio/bcm2835-vchiq.c             | 32 ++-----
- .../vc04_services/bcm2835-audio/bcm2835.h     |  5 +-
- 4 files changed, 45 insertions(+), 82 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -12,6 +12,21 @@
- #define CTRL_VOL_MAX 400
- #define CTRL_VOL_MIN -10239 /* originally -10240 */
-+static int bcm2835_audio_set_chip_ctls(struct bcm2835_chip *chip)
-+{
-+      int i, err = 0;
-+
-+      /* change ctls for all substreams */
-+      for (i = 0; i < MAX_SUBSTREAMS; i++) {
-+              if (chip->alsa_stream[i]) {
-+                      err = bcm2835_audio_set_ctls(chip->alsa_stream[i]);
-+                      if (err < 0)
-+                              break;
-+              }
-+      }
-+      return err;
-+}
-+
- static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_info *uinfo)
- {
-@@ -34,29 +49,6 @@ static int snd_bcm2835_ctl_info(struct s
-       return 0;
- }
--/* toggles mute on or off depending on the value of nmute, and returns
-- * 1 if the mute value was changed, otherwise 0
-- */
--static int toggle_mute(struct bcm2835_chip *chip, int nmute)
--{
--      /* if settings are ok, just return 0 */
--      if (chip->mute == nmute)
--              return 0;
--
--      /* if the sound is muted then we need to unmute */
--      if (chip->mute == CTRL_VOL_MUTE) {
--              chip->volume = chip->old_volume; /* copy the old volume back */
--              audio_info("Unmuting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
--      } else /* otherwise we mute */ {
--              chip->old_volume = chip->volume;
--              chip->volume = 26214; /* set volume to minimum level AKA mute */
--              audio_info("Muting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
--      }
--
--      chip->mute = nmute;
--      return 1;
--}
--
- static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
- {
-@@ -65,7 +57,7 @@ static int snd_bcm2835_ctl_get(struct sn
-       mutex_lock(&chip->audio_mutex);
-       if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
--              ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
-+              ucontrol->value.integer.value[0] = chip->volume;
-       else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
-               ucontrol->value.integer.value[0] = chip->mute;
-       else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
-@@ -79,38 +71,26 @@ static int snd_bcm2835_ctl_put(struct sn
-                               struct snd_ctl_elem_value *ucontrol)
- {
-       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
-+      int val, *valp;
-       int changed = 0;
--      mutex_lock(&chip->audio_mutex);
--
--      if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
--              audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
--              if (chip->mute == CTRL_VOL_MUTE) {
--                      /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
--                      changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
--                      goto unlock;
--              }
--              if (changed || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
--                      chip->volume = alsa2chip(ucontrol->value.integer.value[0]);
--                      changed = 1;
--              }
--
--      } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
--              /* Now implemented */
--              audio_info(" Mute attempted\n");
--              changed = toggle_mute(chip, ucontrol->value.integer.value[0]);
-+      if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
-+              valp = &chip->volume;
-+      else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
-+              valp = &chip->mute;
-+      else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
-+              valp = &chip->dest;
-+      else
-+              return -EINVAL;
--      } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
--              if (ucontrol->value.integer.value[0] != chip->dest) {
--                      chip->dest = ucontrol->value.integer.value[0];
--                      changed = 1;
--              }
-+      val = ucontrol->value.integer.value[0];
-+      mutex_lock(&chip->audio_mutex);
-+      if (val != *valp) {
-+              *valp = val;
-+              changed = 1;
-+              if (bcm2835_audio_set_chip_ctls(chip))
-+                      dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
-       }
--
--      if (changed && bcm2835_audio_set_ctls(chip))
--              dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
--
--unlock:
-       mutex_unlock(&chip->audio_mutex);
-       return changed;
- }
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -280,7 +280,7 @@ static int snd_bcm2835_pcm_prepare(struc
-       bcm2835_audio_setup(alsa_stream);
-       /* in preparation of the stream, set the controls (volume level) of the stream */
--      bcm2835_audio_set_ctls(alsa_stream->chip);
-+      bcm2835_audio_set_ctls(alsa_stream);
-       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-@@ -441,7 +441,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
-       strcpy(pcm->name, "bcm2835 ALSA");
-       chip->pcm = pcm;
-       chip->dest = AUDIO_DEST_AUTO;
--      chip->volume = alsa2chip(0);
-+      chip->volume = 0;
-       chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
-       /* set operators */
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-@@ -498,7 +498,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
-       strcpy(pcm->name, name);
-       chip->pcm = pcm;
-       chip->dest = route;
--      chip->volume = alsa2chip(0);
-+      chip->volume = 0;
-       chip->mute = CTRL_VOL_UNMUTE;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -460,11 +460,11 @@ free_wq:
-       return ret;
- }
--static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream,
--                                     struct bcm2835_chip *chip)
-+int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
- {
-       struct vc_audio_msg m;
-       struct bcm2835_audio_instance *instance = alsa_stream->instance;
-+      struct bcm2835_chip *chip = alsa_stream->chip;
-       int status;
-       int ret;
-@@ -478,7 +478,10 @@ static int bcm2835_audio_set_ctls_chan(s
-       m.type = VC_AUDIO_MSG_TYPE_CONTROL;
-       m.u.control.dest = chip->dest;
--      m.u.control.volume = chip->volume;
-+      if (!chip->mute)
-+              m.u.control.volume = CHIP_MIN_VOLUME;
-+      else
-+              m.u.control.volume = alsa2chip(chip->volume);
-       /* Create the message available completion */
-       init_completion(&instance->msg_avail_comp);
-@@ -514,27 +517,6 @@ unlock:
-       return ret;
- }
--int bcm2835_audio_set_ctls(struct bcm2835_chip *chip)
--{
--      int i;
--      int ret = 0;
--
--      LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);
--
--      /* change ctls for all substreams */
--      for (i = 0; i < MAX_SUBSTREAMS; i++) {
--              if (!chip->alsa_stream[i])
--                      continue;
--              if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
--                      LOG_ERR("Couldn't set the controls for stream %d\n", i);
--                      ret = -1;
--              } else {
--                      LOG_DBG(" Controls set for stream %d\n", i);
--              }
--      }
--      return ret;
--}
--
- int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
-                            unsigned int channels, unsigned int samplerate,
-                            unsigned int bps)
-@@ -548,7 +530,7 @@ int bcm2835_audio_set_params(struct bcm2
-                channels, samplerate, bps);
-       /* resend ctls - alsa_stream may not have been open when first send */
--      ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);
-+      ret = bcm2835_audio_set_ctls(alsa_stream);
-       if (ret) {
-               LOG_ERR(" Alsa controls not supported\n");
-               return -EINVAL;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -74,6 +74,8 @@ enum {
- // convert chip to alsa volume
- #define chip2alsa(vol) -(((vol) * 100) >> 8)
-+#define CHIP_MIN_VOLUME               26214 /* minimum level aka mute */
-+
- /* Some constants for values .. */
- enum snd_bcm2835_route {
-       AUDIO_DEST_AUTO = 0,
-@@ -102,7 +104,6 @@ struct bcm2835_chip {
-       struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
-       int volume;
--      int old_volume; /* stores the volume value whist muted */
-       int dest;
-       int mute;
-@@ -160,7 +161,7 @@ int bcm2835_audio_set_params(struct bcm2
- int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
--int bcm2835_audio_set_ctls(struct bcm2835_chip *chip);
-+int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
-                       unsigned int count,
-                       void *src);
diff --git a/target/linux/brcm2708/patches-4.19/950-0378-staging-bcm2835-audio-Remove-superfluous-open-flag.patch b/target/linux/brcm2708/patches-4.19/950-0378-staging-bcm2835-audio-Remove-superfluous-open-flag.patch
new file mode 100644 (file)
index 0000000..121846d
--- /dev/null
@@ -0,0 +1,61 @@
+From af2fe52ef43c1aa6a24d1c51ad3ccddc39a12c51 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:36 +0200
+Subject: [PATCH] staging: bcm2835-audio: Remove superfluous open flag
+
+commit ad13924de6b07cb52714ea1809c57b2e72a24504 upstream.
+
+All the alsa_stream->open flag checks in the current code are
+redundant, and they cannot be racy.  For the code simplification,
+let's remove the flag and its check.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../staging/vc04_services/bcm2835-audio/bcm2835-pcm.c    | 9 ++-------
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.h    | 1 -
+ 2 files changed, 2 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -57,8 +57,7 @@ void bcm2835_playback_fifo(struct bcm283
+       audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
+               alsa_stream ? alsa_stream->substream : 0);
+-      if (alsa_stream->open)
+-              consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
++      consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
+       /* We get called only if playback was triggered, So, the number of buffers we retrieve in
+        * each iteration are the buffers that have been played out already
+@@ -154,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
+       chip->alsa_stream[idx] = alsa_stream;
+       chip->opened |= (1 << idx);
+-      alsa_stream->open = 1;
+       alsa_stream->draining = 1;
+ out:
+@@ -205,10 +203,7 @@ static int snd_bcm2835_playback_close(st
+       alsa_stream->period_size = 0;
+       alsa_stream->buffer_size = 0;
+-      if (alsa_stream->open) {
+-              alsa_stream->open = 0;
+-              bcm2835_audio_close(alsa_stream);
+-      }
++      bcm2835_audio_close(alsa_stream);
+       if (alsa_stream->chip)
+               alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
+       /*
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
+       spinlock_t lock;
+-      int open;
+       int running;
+       int draining;
diff --git a/target/linux/brcm2708/patches-4.19/950-0379-staging-bcm2835-audio-Drop-useless-running-flag-and-.patch b/target/linux/brcm2708/patches-4.19/950-0379-staging-bcm2835-audio-Drop-useless-running-flag-and-.patch
new file mode 100644 (file)
index 0000000..2a8197c
--- /dev/null
@@ -0,0 +1,106 @@
+From e8a202b4d06a07ba42b91a1dd3c2d9e9cedff32d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:37 +0200
+Subject: [PATCH] staging: bcm2835-audio: Drop useless running flag and
+ check
+
+commit 02f2376321d75e78117f39ff81f215254ee6b4ef upstream.
+
+The running flag of alsa_stream is basically useless.  The running
+state is strictly controlled in ALSA PCM core side, hence the check in
+PCM trigger and close callbacks are superfluous.
+
+Also, the prefill ack at trigger start became superfluous nowadays
+with the ALSA PCM core update.
+
+Let's rip them off.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 46 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  1 -
+ 2 files changed, 8 insertions(+), 39 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -187,19 +187,6 @@ static int snd_bcm2835_playback_close(st
+       audio_info("Alsa close\n");
+-      /*
+-       * Call stop if it's still running. This happens when app
+-       * is force killed and we don't get a stop trigger.
+-       */
+-      if (alsa_stream->running) {
+-              int err;
+-
+-              err = bcm2835_audio_stop(alsa_stream);
+-              alsa_stream->running = 0;
+-              if (err)
+-                      audio_error(" Failed to STOP alsa device\n");
+-      }
+-
+       alsa_stream->period_size = 0;
+       alsa_stream->buffer_size = 0;
+@@ -324,27 +311,13 @@ static int snd_bcm2835_pcm_trigger(struc
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+-              audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n",
+-                      alsa_stream->running);
+-              if (!alsa_stream->running) {
+-                      err = bcm2835_audio_start(alsa_stream);
+-                      if (!err) {
+-                              alsa_stream->pcm_indirect.hw_io =
+-                                      alsa_stream->pcm_indirect.hw_data =
+-                                      bytes_to_frames(runtime,
+-                                      alsa_stream->pos);
+-                              substream->ops->ack(substream);
+-                              alsa_stream->running = 1;
+-                              alsa_stream->draining = 1;
+-                      } else {
+-                              audio_error(" Failed to START alsa device (%d)\n", err);
+-                      }
+-              }
++              err = bcm2835_audio_start(alsa_stream);
++              if (!err)
++                      alsa_stream->draining = 1;
++              else
++                      audio_error(" Failed to START alsa device (%d)\n", err);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+-              audio_debug
+-                      ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n",
+-                      alsa_stream->running, runtime->status->state == SNDRV_PCM_STATE_DRAINING);
+               if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+                       audio_info("DRAINING\n");
+                       alsa_stream->draining = 1;
+@@ -352,12 +325,9 @@ static int snd_bcm2835_pcm_trigger(struc
+                       audio_info("DROPPING\n");
+                       alsa_stream->draining = 0;
+               }
+-              if (alsa_stream->running) {
+-                      err = bcm2835_audio_stop(alsa_stream);
+-                      if (err != 0)
+-                              audio_error(" Failed to STOP alsa device (%d)\n", err);
+-                      alsa_stream->running = 0;
+-              }
++              err = bcm2835_audio_stop(alsa_stream);
++              if (err != 0)
++                      audio_error(" Failed to STOP alsa device (%d)\n", err);
+               break;
+       default:
+               err = -EINVAL;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
+       spinlock_t lock;
+-      int running;
+       int draining;
+       int channels;
diff --git a/target/linux/brcm2708/patches-4.19/950-0379-staging-bcm2835-audio-Remove-redundant-function-call.patch b/target/linux/brcm2708/patches-4.19/950-0379-staging-bcm2835-audio-Remove-redundant-function-call.patch
deleted file mode 100644 (file)
index 482c9ba..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-From 79a3c1a4419b2bf04f6ff5ef84cd74b0456fdd9a Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:35 +0200
-Subject: [PATCH] staging: bcm2835-audio: Remove redundant function
- calls
-
-commit 124950ebe9fa8547c59e8d4acc8d6c59e6278ed6 upstream.
-
-bcm2835_audio_setup(), bcm2835_audio_flush_buffers() and
-bcm2835_audio_flush_playback_buffers() functions do implement
-nothing.
-
-Also, bcm2835_audio_set_ctls() is already called inside
-bcm2835_audio_set_params(), so the later call is superfluous.
-
-This patch removes these superfluous implementations.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  5 -----
- .../bcm2835-audio/bcm2835-vchiq.c             | 21 -------------------
- .../vc04_services/bcm2835-audio/bcm2835.h     |  3 ---
- 3 files changed, 29 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -277,11 +277,6 @@ static int snd_bcm2835_pcm_prepare(struc
-       if (err < 0)
-               audio_error(" error setting hw params\n");
--      bcm2835_audio_setup(alsa_stream);
--
--      /* in preparation of the stream, set the controls (volume level) of the stream */
--      bcm2835_audio_set_ctls(alsa_stream);
--
-       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-       alsa_stream->pcm_indirect.hw_buffer_size =
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -580,12 +580,6 @@ unlock:
-       return ret;
- }
--int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream)
--{
--
--      return 0;
--}
--
- static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
- {
-       struct vc_audio_msg m;
-@@ -774,21 +768,6 @@ unlock:
-       return ret;
- }
--/**
-- * Returns all buffers from arm->vc
-- */
--void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream)
--{
--}
--
--/**
-- * Forces VC to flush(drop) its filled playback buffers and
-- * return them the us. (VC->ARM)
-- */
--void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream)
--{
--}
--
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
- {
-       unsigned int count = atomic_read(&alsa_stream->retrieved);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -158,7 +158,6 @@ int bcm2835_audio_close(struct bcm2835_a
- int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
-                            unsigned int channels, unsigned int samplerate,
-                            unsigned int bps);
--int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
-@@ -167,7 +166,5 @@ int bcm2835_audio_write(struct bcm2835_a
-                       void *src);
- void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
--void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream);
--void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream);
- #endif /* __SOUND_ARM_BCM2835_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0380-staging-bcm2835-audio-Fix-incorrect-draining-handlin.patch b/target/linux/brcm2708/patches-4.19/950-0380-staging-bcm2835-audio-Fix-incorrect-draining-handlin.patch
new file mode 100644 (file)
index 0000000..fe30869
--- /dev/null
@@ -0,0 +1,69 @@
+From e5414b543a330c64b2e0b5e96d604cf580c2b9b7 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:38 +0200
+Subject: [PATCH] staging: bcm2835-audio: Fix incorrect draining
+ handling
+
+commit 7d2a91f5f1bcf08ca257bcf1ed9721fcd341f834 upstream.
+
+The handling of SNDRV_PCM_TRIGGER_STOP at the trigger callback is
+incorrect: when the STOP is issued, the driver is supposed to drop the
+stream immediately.  Meanwhile bcm2835 driver checks the DRAINING
+state and tries to issue some different command.
+
+This patch straightens things a bit, dropping the incorrect state
+checks.  The draining behavior would be still not perfect at this
+point, but will be improved in a later patch.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c  | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -153,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
+       chip->alsa_stream[idx] = alsa_stream;
+       chip->opened |= (1 << idx);
+-      alsa_stream->draining = 1;
+ out:
+       mutex_unlock(&chip->audio_mutex);
+@@ -268,6 +267,7 @@ static int snd_bcm2835_pcm_prepare(struc
+       alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
+       alsa_stream->pos = 0;
++      alsa_stream->draining = false;
+       audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
+               alsa_stream->buffer_size, alsa_stream->period_size,
+@@ -312,21 +312,15 @@ static int snd_bcm2835_pcm_trigger(struc
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               err = bcm2835_audio_start(alsa_stream);
+-              if (!err)
+-                      alsa_stream->draining = 1;
+-              else
++              if (err)
+                       audio_error(" Failed to START alsa device (%d)\n", err);
+               break;
++      case SNDRV_PCM_TRIGGER_DRAIN:
++              alsa_stream->draining = true;
++              break;
+       case SNDRV_PCM_TRIGGER_STOP:
+-              if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+-                      audio_info("DRAINING\n");
+-                      alsa_stream->draining = 1;
+-              } else {
+-                      audio_info("DROPPING\n");
+-                      alsa_stream->draining = 0;
+-              }
+               err = bcm2835_audio_stop(alsa_stream);
+-              if (err != 0)
++              if (err)
+                       audio_error(" Failed to STOP alsa device (%d)\n", err);
+               break;
+       default:
diff --git a/target/linux/brcm2708/patches-4.19/950-0380-staging-bcm2835-audio-Remove-superfluous-open-flag.patch b/target/linux/brcm2708/patches-4.19/950-0380-staging-bcm2835-audio-Remove-superfluous-open-flag.patch
deleted file mode 100644 (file)
index 121846d..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From af2fe52ef43c1aa6a24d1c51ad3ccddc39a12c51 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:36 +0200
-Subject: [PATCH] staging: bcm2835-audio: Remove superfluous open flag
-
-commit ad13924de6b07cb52714ea1809c57b2e72a24504 upstream.
-
-All the alsa_stream->open flag checks in the current code are
-redundant, and they cannot be racy.  For the code simplification,
-let's remove the flag and its check.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../staging/vc04_services/bcm2835-audio/bcm2835-pcm.c    | 9 ++-------
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.h    | 1 -
- 2 files changed, 2 insertions(+), 8 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -57,8 +57,7 @@ void bcm2835_playback_fifo(struct bcm283
-       audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
-               alsa_stream ? alsa_stream->substream : 0);
--      if (alsa_stream->open)
--              consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
-+      consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
-       /* We get called only if playback was triggered, So, the number of buffers we retrieve in
-        * each iteration are the buffers that have been played out already
-@@ -154,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
-       chip->alsa_stream[idx] = alsa_stream;
-       chip->opened |= (1 << idx);
--      alsa_stream->open = 1;
-       alsa_stream->draining = 1;
- out:
-@@ -205,10 +203,7 @@ static int snd_bcm2835_playback_close(st
-       alsa_stream->period_size = 0;
-       alsa_stream->buffer_size = 0;
--      if (alsa_stream->open) {
--              alsa_stream->open = 0;
--              bcm2835_audio_close(alsa_stream);
--      }
-+      bcm2835_audio_close(alsa_stream);
-       if (alsa_stream->chip)
-               alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
-       /*
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
-       spinlock_t lock;
--      int open;
-       int running;
-       int draining;
diff --git a/target/linux/brcm2708/patches-4.19/950-0381-staging-bcm2835-audio-Drop-useless-running-flag-and-.patch b/target/linux/brcm2708/patches-4.19/950-0381-staging-bcm2835-audio-Drop-useless-running-flag-and-.patch
deleted file mode 100644 (file)
index 2a8197c..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-From e8a202b4d06a07ba42b91a1dd3c2d9e9cedff32d Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:37 +0200
-Subject: [PATCH] staging: bcm2835-audio: Drop useless running flag and
- check
-
-commit 02f2376321d75e78117f39ff81f215254ee6b4ef upstream.
-
-The running flag of alsa_stream is basically useless.  The running
-state is strictly controlled in ALSA PCM core side, hence the check in
-PCM trigger and close callbacks are superfluous.
-
-Also, the prefill ack at trigger start became superfluous nowadays
-with the ALSA PCM core update.
-
-Let's rip them off.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 46 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.h     |  1 -
- 2 files changed, 8 insertions(+), 39 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -187,19 +187,6 @@ static int snd_bcm2835_playback_close(st
-       audio_info("Alsa close\n");
--      /*
--       * Call stop if it's still running. This happens when app
--       * is force killed and we don't get a stop trigger.
--       */
--      if (alsa_stream->running) {
--              int err;
--
--              err = bcm2835_audio_stop(alsa_stream);
--              alsa_stream->running = 0;
--              if (err)
--                      audio_error(" Failed to STOP alsa device\n");
--      }
--
-       alsa_stream->period_size = 0;
-       alsa_stream->buffer_size = 0;
-@@ -324,27 +311,13 @@ static int snd_bcm2835_pcm_trigger(struc
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
--              audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n",
--                      alsa_stream->running);
--              if (!alsa_stream->running) {
--                      err = bcm2835_audio_start(alsa_stream);
--                      if (!err) {
--                              alsa_stream->pcm_indirect.hw_io =
--                                      alsa_stream->pcm_indirect.hw_data =
--                                      bytes_to_frames(runtime,
--                                      alsa_stream->pos);
--                              substream->ops->ack(substream);
--                              alsa_stream->running = 1;
--                              alsa_stream->draining = 1;
--                      } else {
--                              audio_error(" Failed to START alsa device (%d)\n", err);
--                      }
--              }
-+              err = bcm2835_audio_start(alsa_stream);
-+              if (!err)
-+                      alsa_stream->draining = 1;
-+              else
-+                      audio_error(" Failed to START alsa device (%d)\n", err);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
--              audio_debug
--                      ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n",
--                      alsa_stream->running, runtime->status->state == SNDRV_PCM_STATE_DRAINING);
-               if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
-                       audio_info("DRAINING\n");
-                       alsa_stream->draining = 1;
-@@ -352,12 +325,9 @@ static int snd_bcm2835_pcm_trigger(struc
-                       audio_info("DROPPING\n");
-                       alsa_stream->draining = 0;
-               }
--              if (alsa_stream->running) {
--                      err = bcm2835_audio_stop(alsa_stream);
--                      if (err != 0)
--                              audio_error(" Failed to STOP alsa device (%d)\n", err);
--                      alsa_stream->running = 0;
--              }
-+              err = bcm2835_audio_stop(alsa_stream);
-+              if (err != 0)
-+                      audio_error(" Failed to STOP alsa device (%d)\n", err);
-               break;
-       default:
-               err = -EINVAL;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
-       spinlock_t lock;
--      int running;
-       int draining;
-       int channels;
diff --git a/target/linux/brcm2708/patches-4.19/950-0381-staging-bcm2835-audio-Kill-unused-spinlock.patch b/target/linux/brcm2708/patches-4.19/950-0381-staging-bcm2835-audio-Kill-unused-spinlock.patch
new file mode 100644 (file)
index 0000000..f337c61
--- /dev/null
@@ -0,0 +1,39 @@
+From d9aef1329c29c20d8e0db9929a3235bfb1d718d3 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:39 +0200
+Subject: [PATCH] staging: bcm2835-audio: Kill unused spinlock
+
+commit 5332f6f012c0bf3a45c77dbc0f79814443a884d4 upstream.
+
+The alsa_stream->lock is never used.  Kill it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 2 --
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.h     | 2 --
+ 2 files changed, 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -128,8 +128,6 @@ static int snd_bcm2835_playback_open_gen
+       alsa_stream->substream = substream;
+       alsa_stream->idx = idx;
+-      spin_lock_init(&alsa_stream->lock);
+-
+       err = bcm2835_audio_open(alsa_stream);
+       if (err) {
+               kfree(alsa_stream);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -119,8 +119,6 @@ struct bcm2835_alsa_stream {
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_indirect pcm_indirect;
+-      spinlock_t lock;
+-
+       int draining;
+       int channels;
diff --git a/target/linux/brcm2708/patches-4.19/950-0382-staging-bcm2835-audio-Fix-incorrect-draining-handlin.patch b/target/linux/brcm2708/patches-4.19/950-0382-staging-bcm2835-audio-Fix-incorrect-draining-handlin.patch
deleted file mode 100644 (file)
index fe30869..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From e5414b543a330c64b2e0b5e96d604cf580c2b9b7 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:38 +0200
-Subject: [PATCH] staging: bcm2835-audio: Fix incorrect draining
- handling
-
-commit 7d2a91f5f1bcf08ca257bcf1ed9721fcd341f834 upstream.
-
-The handling of SNDRV_PCM_TRIGGER_STOP at the trigger callback is
-incorrect: when the STOP is issued, the driver is supposed to drop the
-stream immediately.  Meanwhile bcm2835 driver checks the DRAINING
-state and tries to issue some different command.
-
-This patch straightens things a bit, dropping the incorrect state
-checks.  The draining behavior would be still not perfect at this
-point, but will be improved in a later patch.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c  | 18 ++++++------------
- 1 file changed, 6 insertions(+), 12 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -153,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
-       chip->alsa_stream[idx] = alsa_stream;
-       chip->opened |= (1 << idx);
--      alsa_stream->draining = 1;
- out:
-       mutex_unlock(&chip->audio_mutex);
-@@ -268,6 +267,7 @@ static int snd_bcm2835_pcm_prepare(struc
-       alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
-       alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
-       alsa_stream->pos = 0;
-+      alsa_stream->draining = false;
-       audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
-               alsa_stream->buffer_size, alsa_stream->period_size,
-@@ -312,21 +312,15 @@ static int snd_bcm2835_pcm_trigger(struc
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               err = bcm2835_audio_start(alsa_stream);
--              if (!err)
--                      alsa_stream->draining = 1;
--              else
-+              if (err)
-                       audio_error(" Failed to START alsa device (%d)\n", err);
-               break;
-+      case SNDRV_PCM_TRIGGER_DRAIN:
-+              alsa_stream->draining = true;
-+              break;
-       case SNDRV_PCM_TRIGGER_STOP:
--              if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
--                      audio_info("DRAINING\n");
--                      alsa_stream->draining = 1;
--              } else {
--                      audio_info("DROPPING\n");
--                      alsa_stream->draining = 0;
--              }
-               err = bcm2835_audio_stop(alsa_stream);
--              if (err != 0)
-+              if (err)
-                       audio_error(" Failed to STOP alsa device (%d)\n", err);
-               break;
-       default:
diff --git a/target/linux/brcm2708/patches-4.19/950-0382-staging-bcm2835-audio-Use-PCM-runtime-values-instead.patch b/target/linux/brcm2708/patches-4.19/950-0382-staging-bcm2835-audio-Use-PCM-runtime-values-instead.patch
new file mode 100644 (file)
index 0000000..ffe06fe
--- /dev/null
@@ -0,0 +1,74 @@
+From 4efb059f297f8234bc188b6bc1e4af673ce9f9e3 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:40 +0200
+Subject: [PATCH] staging: bcm2835-audio: Use PCM runtime values
+ instead
+
+commit b8f7fdd50890b848e085c0519469aed4ff4d9b54 upstream.
+
+Some fields in alsa_stream are the values we keep already in PCM
+runtime object, hence they are redundant.  Use the standard PCM
+runtime values instead of the private copies.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 23 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  4 ----
+ 2 files changed, 4 insertions(+), 23 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -206,22 +206,7 @@ static int snd_bcm2835_playback_close(st
+ static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+ {
+-      struct snd_pcm_runtime *runtime = substream->runtime;
+-      struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+-      int err;
+-
+-      err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+-      if (err < 0) {
+-              audio_error
+-                      (" pcm_lib_malloc failed to allocated pages for buffers\n");
+-              return err;
+-      }
+-
+-      alsa_stream->channels = params_channels(params);
+-      alsa_stream->params_rate = params_rate(params);
+-      alsa_stream->pcm_format_width = snd_pcm_format_width(params_format(params));
+-
+-      return err;
++      return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+ }
+ /* hw_free callback */
+@@ -248,11 +233,11 @@ static int snd_bcm2835_pcm_prepare(struc
+       if (chip->spdif_status & IEC958_AES0_NONAUDIO)
+               channels = 0;
+       else
+-              channels = alsa_stream->channels;
++              channels = runtime->channels;
+       err = bcm2835_audio_set_params(alsa_stream, channels,
+-              alsa_stream->params_rate,
+-              alsa_stream->pcm_format_width);
++                                     runtime->rate,
++                                     snd_pcm_format_width(runtime->format));
+       if (err < 0)
+               audio_error(" error setting hw params\n");
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,10 +121,6 @@ struct bcm2835_alsa_stream {
+       int draining;
+-      int channels;
+-      int params_rate;
+-      int pcm_format_width;
+-
+       unsigned int pos;
+       unsigned int buffer_size;
+       unsigned int period_size;
diff --git a/target/linux/brcm2708/patches-4.19/950-0383-staging-bcm2835-audio-Drop-unnecessary-pcm-indirect-.patch b/target/linux/brcm2708/patches-4.19/950-0383-staging-bcm2835-audio-Drop-unnecessary-pcm-indirect-.patch
new file mode 100644 (file)
index 0000000..8012631
--- /dev/null
@@ -0,0 +1,29 @@
+From a08260154f88b0b97e3c8de6b3cdb7187e8c3d8a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:41 +0200
+Subject: [PATCH] staging: bcm2835-audio: Drop unnecessary pcm indirect
+ setup
+
+commit 7318ec896f4856fae2bb013858e422fa078201e1 upstream.
+
+The hw_queue_size of PCM indirect helper doesn't need to be set up if
+you use the whole given buffer size.  Drop the useless
+initialization, which just confuses readers.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -280,7 +280,6 @@ static int snd_bcm2835_pcm_ack(struct sn
+       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+       struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect;
+-      pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max;
+       return snd_pcm_indirect_playback_transfer(substream, pcm_indirect,
+                                                 snd_bcm2835_pcm_transfer);
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0383-staging-bcm2835-audio-Kill-unused-spinlock.patch b/target/linux/brcm2708/patches-4.19/950-0383-staging-bcm2835-audio-Kill-unused-spinlock.patch
deleted file mode 100644 (file)
index f337c61..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From d9aef1329c29c20d8e0db9929a3235bfb1d718d3 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:39 +0200
-Subject: [PATCH] staging: bcm2835-audio: Kill unused spinlock
-
-commit 5332f6f012c0bf3a45c77dbc0f79814443a884d4 upstream.
-
-The alsa_stream->lock is never used.  Kill it.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 2 --
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.h     | 2 --
- 2 files changed, 4 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -128,8 +128,6 @@ static int snd_bcm2835_playback_open_gen
-       alsa_stream->substream = substream;
-       alsa_stream->idx = idx;
--      spin_lock_init(&alsa_stream->lock);
--
-       err = bcm2835_audio_open(alsa_stream);
-       if (err) {
-               kfree(alsa_stream);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -119,8 +119,6 @@ struct bcm2835_alsa_stream {
-       struct snd_pcm_substream *substream;
-       struct snd_pcm_indirect pcm_indirect;
--      spinlock_t lock;
--
-       int draining;
-       int channels;
diff --git a/target/linux/brcm2708/patches-4.19/950-0384-staging-bcm2835-audio-Drop-useless-NULL-check.patch b/target/linux/brcm2708/patches-4.19/950-0384-staging-bcm2835-audio-Drop-useless-NULL-check.patch
new file mode 100644 (file)
index 0000000..ab5a0ed
--- /dev/null
@@ -0,0 +1,28 @@
+From 9f3956e7bbf868894b5aee41110dbe28f117918c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:42 +0200
+Subject: [PATCH] staging: bcm2835-audio: Drop useless NULL check
+
+commit 8bcf9f252c29c2d5bcce3db605c0ebf1ef230f9c upstream.
+
+alsa_stream->chip can be never NULL.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -188,8 +188,7 @@ static int snd_bcm2835_playback_close(st
+       alsa_stream->buffer_size = 0;
+       bcm2835_audio_close(alsa_stream);
+-      if (alsa_stream->chip)
+-              alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
++      alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
+       /*
+        * Do not free up alsa_stream here, it will be freed up by
+        * runtime->private_free callback we registered in *_open above
diff --git a/target/linux/brcm2708/patches-4.19/950-0384-staging-bcm2835-audio-Use-PCM-runtime-values-instead.patch b/target/linux/brcm2708/patches-4.19/950-0384-staging-bcm2835-audio-Use-PCM-runtime-values-instead.patch
deleted file mode 100644 (file)
index ffe06fe..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-From 4efb059f297f8234bc188b6bc1e4af673ce9f9e3 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:40 +0200
-Subject: [PATCH] staging: bcm2835-audio: Use PCM runtime values
- instead
-
-commit b8f7fdd50890b848e085c0519469aed4ff4d9b54 upstream.
-
-Some fields in alsa_stream are the values we keep already in PCM
-runtime object, hence they are redundant.  Use the standard PCM
-runtime values instead of the private copies.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 23 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.h     |  4 ----
- 2 files changed, 4 insertions(+), 23 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -206,22 +206,7 @@ static int snd_bcm2835_playback_close(st
- static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
- {
--      struct snd_pcm_runtime *runtime = substream->runtime;
--      struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
--      int err;
--
--      err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
--      if (err < 0) {
--              audio_error
--                      (" pcm_lib_malloc failed to allocated pages for buffers\n");
--              return err;
--      }
--
--      alsa_stream->channels = params_channels(params);
--      alsa_stream->params_rate = params_rate(params);
--      alsa_stream->pcm_format_width = snd_pcm_format_width(params_format(params));
--
--      return err;
-+      return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
- }
- /* hw_free callback */
-@@ -248,11 +233,11 @@ static int snd_bcm2835_pcm_prepare(struc
-       if (chip->spdif_status & IEC958_AES0_NONAUDIO)
-               channels = 0;
-       else
--              channels = alsa_stream->channels;
-+              channels = runtime->channels;
-       err = bcm2835_audio_set_params(alsa_stream, channels,
--              alsa_stream->params_rate,
--              alsa_stream->pcm_format_width);
-+                                     runtime->rate,
-+                                     snd_pcm_format_width(runtime->format));
-       if (err < 0)
-               audio_error(" error setting hw params\n");
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,10 +121,6 @@ struct bcm2835_alsa_stream {
-       int draining;
--      int channels;
--      int params_rate;
--      int pcm_format_width;
--
-       unsigned int pos;
-       unsigned int buffer_size;
-       unsigned int period_size;
diff --git a/target/linux/brcm2708/patches-4.19/950-0385-staging-bcm2835-audio-Drop-unnecessary-pcm-indirect-.patch b/target/linux/brcm2708/patches-4.19/950-0385-staging-bcm2835-audio-Drop-unnecessary-pcm-indirect-.patch
deleted file mode 100644 (file)
index 8012631..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From a08260154f88b0b97e3c8de6b3cdb7187e8c3d8a Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:41 +0200
-Subject: [PATCH] staging: bcm2835-audio: Drop unnecessary pcm indirect
- setup
-
-commit 7318ec896f4856fae2bb013858e422fa078201e1 upstream.
-
-The hw_queue_size of PCM indirect helper doesn't need to be set up if
-you use the whole given buffer size.  Drop the useless
-initialization, which just confuses readers.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -280,7 +280,6 @@ static int snd_bcm2835_pcm_ack(struct sn
-       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-       struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect;
--      pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max;
-       return snd_pcm_indirect_playback_transfer(substream, pcm_indirect,
-                                                 snd_bcm2835_pcm_transfer);
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0385-staging-bcm2835-audio-Propagate-parameter-setup-erro.patch b/target/linux/brcm2708/patches-4.19/950-0385-staging-bcm2835-audio-Propagate-parameter-setup-erro.patch
new file mode 100644 (file)
index 0000000..dc65250
--- /dev/null
@@ -0,0 +1,40 @@
+From 2ab24bca59da765a12f4617527e671170230bf3a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:43 +0200
+Subject: [PATCH] staging: bcm2835-audio: Propagate parameter setup
+ error
+
+commit fee5638fe552ff8222c3a5bdcc4a34255e248d8c upstream.
+
+When the parameter setup fails, the driver should propagate the error
+code instead of silently ignoring it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -238,7 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
+                                      runtime->rate,
+                                      snd_pcm_format_width(runtime->format));
+       if (err < 0)
+-              audio_error(" error setting hw params\n");
++              goto out;
+       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+@@ -255,8 +255,9 @@ static int snd_bcm2835_pcm_prepare(struc
+               alsa_stream->buffer_size, alsa_stream->period_size,
+               alsa_stream->pos, runtime->frame_bits);
++ out:
+       mutex_unlock(&chip->audio_mutex);
+-      return 0;
++      return err;
+ }
+ static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
diff --git a/target/linux/brcm2708/patches-4.19/950-0386-staging-bcm2835-audio-Drop-debug-messages-in-bcm2835.patch b/target/linux/brcm2708/patches-4.19/950-0386-staging-bcm2835-audio-Drop-debug-messages-in-bcm2835.patch
new file mode 100644 (file)
index 0000000..96a4d73
--- /dev/null
@@ -0,0 +1,150 @@
+From e109804fa00a139a05626c1b8ceebcfe3577fc6d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:44 +0200
+Subject: [PATCH] staging: bcm2835-audio: Drop debug messages in
+ bcm2835-pcm.c
+
+commit 055e1c330d04df87d4730a5db837161c11ddaafc upstream.
+
+These debug messages worsen the code readability a lot while they give
+little debuggability (which we already have via tracing, in anyway).
+
+Let's clean them up.  This allows us to reduce the
+snd_bcm2835_pcm_lib_ioctl() function to be a direct call of the
+snd_pcm_lib_ioctl callback (like most other drivers do), too.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 51 +++----------------
+ 1 file changed, 7 insertions(+), 44 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -44,9 +44,7 @@ static const struct snd_pcm_hardware snd
+ static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
+ {
+-      audio_info("Freeing up alsa stream here ..\n");
+       kfree(runtime->private_data);
+-      runtime->private_data = NULL;
+ }
+ void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
+@@ -99,7 +97,6 @@ static int snd_bcm2835_playback_open_gen
+       int err;
+       mutex_lock(&chip->audio_mutex);
+-      audio_info("Alsa open (%d)\n", substream->number);
+       idx = substream->number;
+       if (spdif && chip->opened) {
+@@ -182,8 +179,6 @@ static int snd_bcm2835_playback_close(st
+       runtime = substream->runtime;
+       alsa_stream = runtime->private_data;
+-      audio_info("Alsa close\n");
+-
+       alsa_stream->period_size = 0;
+       alsa_stream->buffer_size = 0;
+@@ -251,10 +246,6 @@ static int snd_bcm2835_pcm_prepare(struc
+       alsa_stream->pos = 0;
+       alsa_stream->draining = false;
+-      audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
+-              alsa_stream->buffer_size, alsa_stream->period_size,
+-              alsa_stream->pos, runtime->frame_bits);
+-
+  out:
+       mutex_unlock(&chip->audio_mutex);
+       return err;
+@@ -266,12 +257,8 @@ static void snd_bcm2835_pcm_transfer(str
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+       void *src = (void *) (substream->runtime->dma_area + rec->sw_data);
+-      int err;
+-
+-      err = bcm2835_audio_write(alsa_stream, bytes, src);
+-      if (err)
+-              audio_error(" Failed to transfer to alsa device (%d)\n", err);
++      bcm2835_audio_write(alsa_stream, bytes, src);
+ }
+ static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)
+@@ -289,27 +276,18 @@ static int snd_bcm2835_pcm_trigger(struc
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+-      int err = 0;
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+-              err = bcm2835_audio_start(alsa_stream);
+-              if (err)
+-                      audio_error(" Failed to START alsa device (%d)\n", err);
+-              break;
++              return bcm2835_audio_start(alsa_stream);
+       case SNDRV_PCM_TRIGGER_DRAIN:
+               alsa_stream->draining = true;
+-              break;
++              return 0;
+       case SNDRV_PCM_TRIGGER_STOP:
+-              err = bcm2835_audio_stop(alsa_stream);
+-              if (err)
+-                      audio_error(" Failed to STOP alsa device (%d)\n", err);
+-              break;
++              return bcm2835_audio_stop(alsa_stream);
+       default:
+-              err = -EINVAL;
++              return -EINVAL;
+       }
+-
+-      return err;
+ }
+ /* pointer callback */
+@@ -319,31 +297,16 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+-      audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0,
+-              frames_to_bytes(runtime, runtime->status->hw_ptr),
+-              frames_to_bytes(runtime, runtime->control->appl_ptr),
+-              alsa_stream->pos);
+-
+       return snd_pcm_indirect_playback_pointer(substream,
+               &alsa_stream->pcm_indirect,
+               alsa_stream->pos);
+ }
+-static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+-      unsigned int cmd, void *arg)
+-{
+-      int ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+-
+-      audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream,
+-              cmd, arg, arg ? *(unsigned int *)arg : 0, ret);
+-      return ret;
+-}
+-
+ /* operators */
+ static const struct snd_pcm_ops snd_bcm2835_playback_ops = {
+       .open = snd_bcm2835_playback_open,
+       .close = snd_bcm2835_playback_close,
+-      .ioctl = snd_bcm2835_pcm_lib_ioctl,
++      .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_bcm2835_pcm_hw_params,
+       .hw_free = snd_bcm2835_pcm_hw_free,
+       .prepare = snd_bcm2835_pcm_prepare,
+@@ -355,7 +318,7 @@ static const struct snd_pcm_ops snd_bcm2
+ static const struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = {
+       .open = snd_bcm2835_playback_spdif_open,
+       .close = snd_bcm2835_playback_close,
+-      .ioctl = snd_bcm2835_pcm_lib_ioctl,
++      .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_bcm2835_pcm_hw_params,
+       .hw_free = snd_bcm2835_pcm_hw_free,
+       .prepare = snd_bcm2835_pcm_prepare,
diff --git a/target/linux/brcm2708/patches-4.19/950-0386-staging-bcm2835-audio-Drop-useless-NULL-check.patch b/target/linux/brcm2708/patches-4.19/950-0386-staging-bcm2835-audio-Drop-useless-NULL-check.patch
deleted file mode 100644 (file)
index ab5a0ed..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 9f3956e7bbf868894b5aee41110dbe28f117918c Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:42 +0200
-Subject: [PATCH] staging: bcm2835-audio: Drop useless NULL check
-
-commit 8bcf9f252c29c2d5bcce3db605c0ebf1ef230f9c upstream.
-
-alsa_stream->chip can be never NULL.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -188,8 +188,7 @@ static int snd_bcm2835_playback_close(st
-       alsa_stream->buffer_size = 0;
-       bcm2835_audio_close(alsa_stream);
--      if (alsa_stream->chip)
--              alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
-+      alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
-       /*
-        * Do not free up alsa_stream here, it will be freed up by
-        * runtime->private_free callback we registered in *_open above
diff --git a/target/linux/brcm2708/patches-4.19/950-0387-staging-bcm2835-audio-Drop-superfluous-mutex-lock-du.patch b/target/linux/brcm2708/patches-4.19/950-0387-staging-bcm2835-audio-Drop-superfluous-mutex-lock-du.patch
new file mode 100644 (file)
index 0000000..a700811
--- /dev/null
@@ -0,0 +1,49 @@
+From 3c7663a9b1763f64250db4b975a3ce246ef32e0f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:45 +0200
+Subject: [PATCH] staging: bcm2835-audio: Drop superfluous mutex lock
+ during prepare
+
+commit f0eb15d055380ff127e5f12c8fad2b36bdb3c006 upstream.
+
+The chip->audio_mutex is used basically for protecting the opened
+stream assignment, and the prepare callback is irrelevant with it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -218,8 +218,6 @@ static int snd_bcm2835_pcm_prepare(struc
+       int channels;
+       int err;
+-      mutex_lock(&chip->audio_mutex);
+-
+       /* notify the vchiq that it should enter spdif passthrough mode by
+        * setting channels=0 (see
+        * https://github.com/raspberrypi/linux/issues/528)
+@@ -233,7 +231,7 @@ static int snd_bcm2835_pcm_prepare(struc
+                                      runtime->rate,
+                                      snd_pcm_format_width(runtime->format));
+       if (err < 0)
+-              goto out;
++              return err;
+       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+@@ -246,9 +244,7 @@ static int snd_bcm2835_pcm_prepare(struc
+       alsa_stream->pos = 0;
+       alsa_stream->draining = false;
+- out:
+-      mutex_unlock(&chip->audio_mutex);
+-      return err;
++      return 0;
+ }
+ static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
diff --git a/target/linux/brcm2708/patches-4.19/950-0387-staging-bcm2835-audio-Propagate-parameter-setup-erro.patch b/target/linux/brcm2708/patches-4.19/950-0387-staging-bcm2835-audio-Propagate-parameter-setup-erro.patch
deleted file mode 100644 (file)
index dc65250..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From 2ab24bca59da765a12f4617527e671170230bf3a Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:43 +0200
-Subject: [PATCH] staging: bcm2835-audio: Propagate parameter setup
- error
-
-commit fee5638fe552ff8222c3a5bdcc4a34255e248d8c upstream.
-
-When the parameter setup fails, the driver should propagate the error
-code instead of silently ignoring it.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -238,7 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
-                                      runtime->rate,
-                                      snd_pcm_format_width(runtime->format));
-       if (err < 0)
--              audio_error(" error setting hw params\n");
-+              goto out;
-       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-@@ -255,8 +255,9 @@ static int snd_bcm2835_pcm_prepare(struc
-               alsa_stream->buffer_size, alsa_stream->period_size,
-               alsa_stream->pos, runtime->frame_bits);
-+ out:
-       mutex_unlock(&chip->audio_mutex);
--      return 0;
-+      return err;
- }
- static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
diff --git a/target/linux/brcm2708/patches-4.19/950-0388-staging-bcm2835-audio-Add-10ms-period-constraint.patch b/target/linux/brcm2708/patches-4.19/950-0388-staging-bcm2835-audio-Add-10ms-period-constraint.patch
new file mode 100644 (file)
index 0000000..07e96f6
--- /dev/null
@@ -0,0 +1,33 @@
+From daa78c198ece1ec901ee565c869ee1a60a95061d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:46 +0200
+Subject: [PATCH] staging: bcm2835-audio: Add 10ms period constraint
+
+commit 93c66acaf68b5247c3121a46a71ff6a70fc1d492 upstream.
+
+It seems that the resolution of vc04 callback is in 10 msec; i.e. the
+minimal period size is also 10 msec.
+
+This patch adds the corresponding hw constraint.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -145,6 +145,11 @@ static int snd_bcm2835_playback_open_gen
+                                  SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+                                  16);
++      /* position update is in 10ms order */
++      snd_pcm_hw_constraint_minmax(runtime,
++                                   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
++                                   10 * 1000, UINT_MAX);
++
+       chip->alsa_stream[idx] = alsa_stream;
+       chip->opened |= (1 << idx);
diff --git a/target/linux/brcm2708/patches-4.19/950-0388-staging-bcm2835-audio-Drop-debug-messages-in-bcm2835.patch b/target/linux/brcm2708/patches-4.19/950-0388-staging-bcm2835-audio-Drop-debug-messages-in-bcm2835.patch
deleted file mode 100644 (file)
index 96a4d73..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-From e109804fa00a139a05626c1b8ceebcfe3577fc6d Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:44 +0200
-Subject: [PATCH] staging: bcm2835-audio: Drop debug messages in
- bcm2835-pcm.c
-
-commit 055e1c330d04df87d4730a5db837161c11ddaafc upstream.
-
-These debug messages worsen the code readability a lot while they give
-little debuggability (which we already have via tracing, in anyway).
-
-Let's clean them up.  This allows us to reduce the
-snd_bcm2835_pcm_lib_ioctl() function to be a direct call of the
-snd_pcm_lib_ioctl callback (like most other drivers do), too.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 51 +++----------------
- 1 file changed, 7 insertions(+), 44 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -44,9 +44,7 @@ static const struct snd_pcm_hardware snd
- static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
- {
--      audio_info("Freeing up alsa stream here ..\n");
-       kfree(runtime->private_data);
--      runtime->private_data = NULL;
- }
- void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
-@@ -99,7 +97,6 @@ static int snd_bcm2835_playback_open_gen
-       int err;
-       mutex_lock(&chip->audio_mutex);
--      audio_info("Alsa open (%d)\n", substream->number);
-       idx = substream->number;
-       if (spdif && chip->opened) {
-@@ -182,8 +179,6 @@ static int snd_bcm2835_playback_close(st
-       runtime = substream->runtime;
-       alsa_stream = runtime->private_data;
--      audio_info("Alsa close\n");
--
-       alsa_stream->period_size = 0;
-       alsa_stream->buffer_size = 0;
-@@ -251,10 +246,6 @@ static int snd_bcm2835_pcm_prepare(struc
-       alsa_stream->pos = 0;
-       alsa_stream->draining = false;
--      audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
--              alsa_stream->buffer_size, alsa_stream->period_size,
--              alsa_stream->pos, runtime->frame_bits);
--
-  out:
-       mutex_unlock(&chip->audio_mutex);
-       return err;
-@@ -266,12 +257,8 @@ static void snd_bcm2835_pcm_transfer(str
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-       void *src = (void *) (substream->runtime->dma_area + rec->sw_data);
--      int err;
--
--      err = bcm2835_audio_write(alsa_stream, bytes, src);
--      if (err)
--              audio_error(" Failed to transfer to alsa device (%d)\n", err);
-+      bcm2835_audio_write(alsa_stream, bytes, src);
- }
- static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)
-@@ -289,27 +276,18 @@ static int snd_bcm2835_pcm_trigger(struc
- {
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
--      int err = 0;
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
--              err = bcm2835_audio_start(alsa_stream);
--              if (err)
--                      audio_error(" Failed to START alsa device (%d)\n", err);
--              break;
-+              return bcm2835_audio_start(alsa_stream);
-       case SNDRV_PCM_TRIGGER_DRAIN:
-               alsa_stream->draining = true;
--              break;
-+              return 0;
-       case SNDRV_PCM_TRIGGER_STOP:
--              err = bcm2835_audio_stop(alsa_stream);
--              if (err)
--                      audio_error(" Failed to STOP alsa device (%d)\n", err);
--              break;
-+              return bcm2835_audio_stop(alsa_stream);
-       default:
--              err = -EINVAL;
-+              return -EINVAL;
-       }
--
--      return err;
- }
- /* pointer callback */
-@@ -319,31 +297,16 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
--      audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0,
--              frames_to_bytes(runtime, runtime->status->hw_ptr),
--              frames_to_bytes(runtime, runtime->control->appl_ptr),
--              alsa_stream->pos);
--
-       return snd_pcm_indirect_playback_pointer(substream,
-               &alsa_stream->pcm_indirect,
-               alsa_stream->pos);
- }
--static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream,
--      unsigned int cmd, void *arg)
--{
--      int ret = snd_pcm_lib_ioctl(substream, cmd, arg);
--
--      audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream,
--              cmd, arg, arg ? *(unsigned int *)arg : 0, ret);
--      return ret;
--}
--
- /* operators */
- static const struct snd_pcm_ops snd_bcm2835_playback_ops = {
-       .open = snd_bcm2835_playback_open,
-       .close = snd_bcm2835_playback_close,
--      .ioctl = snd_bcm2835_pcm_lib_ioctl,
-+      .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_bcm2835_pcm_hw_params,
-       .hw_free = snd_bcm2835_pcm_hw_free,
-       .prepare = snd_bcm2835_pcm_prepare,
-@@ -355,7 +318,7 @@ static const struct snd_pcm_ops snd_bcm2
- static const struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = {
-       .open = snd_bcm2835_playback_spdif_open,
-       .close = snd_bcm2835_playback_close,
--      .ioctl = snd_bcm2835_pcm_lib_ioctl,
-+      .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_bcm2835_pcm_hw_params,
-       .hw_free = snd_bcm2835_pcm_hw_free,
-       .prepare = snd_bcm2835_pcm_prepare,
diff --git a/target/linux/brcm2708/patches-4.19/950-0389-staging-bcm2835-audio-Drop-superfluous-mutex-lock-du.patch b/target/linux/brcm2708/patches-4.19/950-0389-staging-bcm2835-audio-Drop-superfluous-mutex-lock-du.patch
deleted file mode 100644 (file)
index a700811..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 3c7663a9b1763f64250db4b975a3ce246ef32e0f Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:45 +0200
-Subject: [PATCH] staging: bcm2835-audio: Drop superfluous mutex lock
- during prepare
-
-commit f0eb15d055380ff127e5f12c8fad2b36bdb3c006 upstream.
-
-The chip->audio_mutex is used basically for protecting the opened
-stream assignment, and the prepare callback is irrelevant with it.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 8 ++------
- 1 file changed, 2 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -218,8 +218,6 @@ static int snd_bcm2835_pcm_prepare(struc
-       int channels;
-       int err;
--      mutex_lock(&chip->audio_mutex);
--
-       /* notify the vchiq that it should enter spdif passthrough mode by
-        * setting channels=0 (see
-        * https://github.com/raspberrypi/linux/issues/528)
-@@ -233,7 +231,7 @@ static int snd_bcm2835_pcm_prepare(struc
-                                      runtime->rate,
-                                      snd_pcm_format_width(runtime->format));
-       if (err < 0)
--              goto out;
-+              return err;
-       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-@@ -246,9 +244,7 @@ static int snd_bcm2835_pcm_prepare(struc
-       alsa_stream->pos = 0;
-       alsa_stream->draining = false;
-- out:
--      mutex_unlock(&chip->audio_mutex);
--      return err;
-+      return 0;
- }
- static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
diff --git a/target/linux/brcm2708/patches-4.19/950-0389-staging-bcm2835-audio-Make-single-vchi-handle.patch b/target/linux/brcm2708/patches-4.19/950-0389-staging-bcm2835-audio-Make-single-vchi-handle.patch
new file mode 100644 (file)
index 0000000..eb6538d
--- /dev/null
@@ -0,0 +1,412 @@
+From 98a1612b199cb3060306c05d1a6d7ca18ef08475 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:47 +0200
+Subject: [PATCH] staging: bcm2835-audio: Make single vchi handle
+
+commit 326a6edcb2ada56375bd7d3fc24c83f58e8da7f3 upstream.
+
+The bcm2835_audio_instance object contains the array of
+VCHI_SERVICE_HANDLE_T, while the code assumes and uses only the first
+element explicitly.  Let's reduce to a single vchi handle for
+simplifying the code.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c             | 170 ++++++------------
+ 1 file changed, 58 insertions(+), 112 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -44,8 +44,7 @@
+ #endif
+ struct bcm2835_audio_instance {
+-      unsigned int num_connections;
+-      VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
++      VCHI_SERVICE_HANDLE_T vchi_handle;
+       struct completion msg_avail_comp;
+       struct mutex vchi_mutex;
+       struct bcm2835_alsa_stream *alsa_stream;
+@@ -202,12 +201,12 @@ static void audio_vchi_callback(void *pa
+               BUG();
+               return;
+       }
+-      if (!instance->vchi_handle[0]) {
+-              LOG_ERR(" .. instance->vchi_handle[0] is null\n");
++      if (!instance->vchi_handle) {
++              LOG_ERR(" .. instance->vchi_handle is null\n");
+               BUG();
+               return;
+       }
+-      status = vchi_msg_dequeue(instance->vchi_handle[0],
++      status = vchi_msg_dequeue(instance->vchi_handle,
+                                 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
+       if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
+               LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
+@@ -237,102 +236,61 @@ static void audio_vchi_callback(void *pa
+ static struct bcm2835_audio_instance *
+ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
+-                 VCHI_CONNECTION_T **vchi_connections,
+-                 unsigned int num_connections)
++                 VCHI_CONNECTION_T *vchi_connection)
+ {
+-      unsigned int i;
++      SERVICE_CREATION_T params = {
++              .version                = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
++              .service_id             = VC_AUDIO_SERVER_NAME,
++              .connection             = vchi_connection,
++              .rx_fifo_size           = 0,
++              .tx_fifo_size           = 0,
++              .callback               = audio_vchi_callback,
++              .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
++              .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
++              .want_crc               = 0
++      };
+       struct bcm2835_audio_instance *instance;
+       int status;
+-      int ret;
+-
+-      LOG_DBG("%s: start", __func__);
+-      if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
+-              LOG_ERR("%s: unsupported number of connections %u (max=%u)\n",
+-                      __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
+-
+-              return ERR_PTR(-EINVAL);
+-      }
+       /* Allocate memory for this instance */
+       instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+       if (!instance)
+               return ERR_PTR(-ENOMEM);
+-      instance->num_connections = num_connections;
+-
+       /* Create a lock for exclusive, serialized VCHI connection access */
+       mutex_init(&instance->vchi_mutex);
+       /* Open the VCHI service connections */
+-      for (i = 0; i < num_connections; i++) {
+-              SERVICE_CREATION_T params = {
+-                      .version                = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
+-                      .service_id             = VC_AUDIO_SERVER_NAME,
+-                      .connection             = vchi_connections[i],
+-                      .rx_fifo_size           = 0,
+-                      .tx_fifo_size           = 0,
+-                      .callback               = audio_vchi_callback,
+-                      .callback_param         = instance,
+-                      .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
+-                      .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
+-                      .want_crc               = 0
+-              };
+-
+-              LOG_DBG("%s: about to open %i\n", __func__, i);
+-              status = vchi_service_open(vchi_instance, &params,
+-                                         &instance->vchi_handle[i]);
++      params.callback_param = instance,
+-              LOG_DBG("%s: opened %i: %p=%d\n", __func__, i, instance->vchi_handle[i], status);
+-              if (status) {
+-                      LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
+-                              __func__, status);
+-                      ret = -EPERM;
+-                      goto err_close_services;
+-              }
+-              /* Finished with the service for now */
+-              vchi_service_release(instance->vchi_handle[i]);
+-      }
+-
+-      LOG_DBG("%s: okay\n", __func__);
+-      return instance;
++      status = vchi_service_open(vchi_instance, &params,
++                                 &instance->vchi_handle);
+-err_close_services:
+-      for (i = 0; i < instance->num_connections; i++) {
+-              LOG_ERR("%s: closing %i: %p\n", __func__, i, instance->vchi_handle[i]);
+-              if (instance->vchi_handle[i])
+-                      vchi_service_close(instance->vchi_handle[i]);
++      if (status) {
++              LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
++                      __func__, status);
++              kfree(instance);
++              return ERR_PTR(-EPERM);
+       }
+-      kfree(instance);
+-      LOG_ERR("%s: error\n", __func__);
++      /* Finished with the service for now */
++      vchi_service_release(instance->vchi_handle);
+-      return ERR_PTR(ret);
++      return instance;
+ }
+ static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
+ {
+-      unsigned int i;
+-
+-      if (!instance) {
+-              LOG_ERR("%s: invalid handle %p\n", __func__, instance);
+-
+-              return -1;
+-      }
++      int status;
+-      LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
+       mutex_lock(&instance->vchi_mutex);
+       /* Close all VCHI service connections */
+-      for (i = 0; i < instance->num_connections; i++) {
+-              int status;
+-
+-              LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]);
+-              vchi_service_use(instance->vchi_handle[i]);
++      vchi_service_use(instance->vchi_handle);
+-              status = vchi_service_close(instance->vchi_handle[i]);
+-              if (status) {
+-                      LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
+-                              __func__, status);
+-              }
++      status = vchi_service_close(instance->vchi_handle);
++      if (status) {
++              LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
++                      __func__, status);
+       }
+       mutex_unlock(&instance->vchi_mutex);
+@@ -383,19 +341,9 @@ static int bcm2835_audio_open_connection
+               (struct bcm2835_audio_instance *)alsa_stream->instance;
+       struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
+-      LOG_INFO("%s: start\n", __func__);
+-      BUG_ON(instance);
+-      if (instance) {
+-              LOG_ERR("%s: VCHI instance already open (%p)\n",
+-                      __func__, instance);
+-              instance->alsa_stream = alsa_stream;
+-              alsa_stream->instance = instance;
+-              return 0;
+-      }
+-
+       /* Initialize an instance of the audio service */
+       instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
+-                                    &vhci_ctx->vchi_connection, 1);
++                                    vhci_ctx->vchi_connection);
+       if (IS_ERR(instance)) {
+               LOG_ERR("%s: failed to initialize audio service\n", __func__);
+@@ -407,8 +355,6 @@ static int bcm2835_audio_open_connection
+       instance->alsa_stream = alsa_stream;
+       alsa_stream->instance = instance;
+-      LOG_DBG(" success !\n");
+-
+       return 0;
+ }
+@@ -431,12 +377,12 @@ int bcm2835_audio_open(struct bcm2835_al
+       LOG_DBG(" instance (%p)\n", instance);
+       mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle[0]);
++      vchi_service_use(instance->vchi_handle);
+       m.type = VC_AUDIO_MSG_TYPE_OPEN;
+       /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                       &m, sizeof(m));
+       if (status) {
+@@ -450,7 +396,7 @@ int bcm2835_audio_open(struct bcm2835_al
+       ret = 0;
+ unlock:
+-      vchi_service_release(instance->vchi_handle[0]);
++      vchi_service_release(instance->vchi_handle);
+       mutex_unlock(&instance->vchi_mutex);
+ free_wq:
+@@ -472,7 +418,7 @@ int bcm2835_audio_set_ctls(struct bcm283
+                chip->dest, chip->volume);
+       mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle[0]);
++      vchi_service_use(instance->vchi_handle);
+       instance->result = -1;
+@@ -487,7 +433,7 @@ int bcm2835_audio_set_ctls(struct bcm283
+       init_completion(&instance->msg_avail_comp);
+       /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                       &m, sizeof(m));
+       if (status) {
+@@ -511,7 +457,7 @@ int bcm2835_audio_set_ctls(struct bcm283
+       ret = 0;
+ unlock:
+-      vchi_service_release(instance->vchi_handle[0]);
++      vchi_service_release(instance->vchi_handle);
+       mutex_unlock(&instance->vchi_mutex);
+       return ret;
+@@ -537,7 +483,7 @@ int bcm2835_audio_set_params(struct bcm2
+       }
+       mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle[0]);
++      vchi_service_use(instance->vchi_handle);
+       instance->result = -1;
+@@ -550,7 +496,7 @@ int bcm2835_audio_set_params(struct bcm2
+       init_completion(&instance->msg_avail_comp);
+       /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                       &m, sizeof(m));
+       if (status) {
+@@ -574,7 +520,7 @@ int bcm2835_audio_set_params(struct bcm2
+       ret = 0;
+ unlock:
+-      vchi_service_release(instance->vchi_handle[0]);
++      vchi_service_release(instance->vchi_handle);
+       mutex_unlock(&instance->vchi_mutex);
+       return ret;
+@@ -588,12 +534,12 @@ static int bcm2835_audio_start_worker(st
+       int ret;
+       mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle[0]);
++      vchi_service_use(instance->vchi_handle);
+       m.type = VC_AUDIO_MSG_TYPE_START;
+       /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                       &m, sizeof(m));
+       if (status) {
+@@ -607,7 +553,7 @@ static int bcm2835_audio_start_worker(st
+       ret = 0;
+ unlock:
+-      vchi_service_release(instance->vchi_handle[0]);
++      vchi_service_release(instance->vchi_handle);
+       mutex_unlock(&instance->vchi_mutex);
+       return ret;
+ }
+@@ -620,13 +566,13 @@ static int bcm2835_audio_stop_worker(str
+       int ret;
+       mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle[0]);
++      vchi_service_use(instance->vchi_handle);
+       m.type = VC_AUDIO_MSG_TYPE_STOP;
+       m.u.stop.draining = alsa_stream->draining;
+       /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                       &m, sizeof(m));
+       if (status) {
+@@ -640,7 +586,7 @@ static int bcm2835_audio_stop_worker(str
+       ret = 0;
+ unlock:
+-      vchi_service_release(instance->vchi_handle[0]);
++      vchi_service_release(instance->vchi_handle);
+       mutex_unlock(&instance->vchi_mutex);
+       return ret;
+ }
+@@ -655,7 +601,7 @@ int bcm2835_audio_close(struct bcm2835_a
+       my_workqueue_quit(alsa_stream);
+       mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle[0]);
++      vchi_service_use(instance->vchi_handle);
+       m.type = VC_AUDIO_MSG_TYPE_CLOSE;
+@@ -663,7 +609,7 @@ int bcm2835_audio_close(struct bcm2835_a
+       init_completion(&instance->msg_avail_comp);
+       /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                       &m, sizeof(m));
+       if (status) {
+@@ -687,7 +633,7 @@ int bcm2835_audio_close(struct bcm2835_a
+       ret = 0;
+ unlock:
+-      vchi_service_release(instance->vchi_handle[0]);
++      vchi_service_release(instance->vchi_handle);
+       mutex_unlock(&instance->vchi_mutex);
+       /* Stop the audio service */
+@@ -708,10 +654,10 @@ static int bcm2835_audio_write_worker(st
+       LOG_INFO(" Writing %d bytes from %p\n", count, src);
+       mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle[0]);
++      vchi_service_use(instance->vchi_handle);
+       if (instance->peer_version == 0 &&
+-          vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0)
++          vchi_get_peer_version(instance->vchi_handle, &instance->peer_version) == 0)
+               LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
+       m.type = VC_AUDIO_MSG_TYPE_WRITE;
+@@ -723,7 +669,7 @@ static int bcm2835_audio_write_worker(st
+       m.u.write.silence = src == NULL;
+       /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                       &m, sizeof(m));
+       if (status) {
+@@ -736,7 +682,7 @@ static int bcm2835_audio_write_worker(st
+       if (!m.u.write.silence) {
+               if (!m.u.write.max_packet) {
+                       /* Send the message to the videocore */
+-                      status = vchi_bulk_queue_transmit(instance->vchi_handle[0],
++                      status = vchi_bulk_queue_transmit(instance->vchi_handle,
+                                                         src, count,
+                                                         0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
+                                                         +
+@@ -746,7 +692,7 @@ static int bcm2835_audio_write_worker(st
+                       while (count > 0) {
+                               int bytes = min_t(int, m.u.write.max_packet, count);
+-                              status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++                              status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+                                                               src, bytes);
+                               src = (char *)src + bytes;
+                               count -= bytes;
+@@ -763,7 +709,7 @@ static int bcm2835_audio_write_worker(st
+       ret = 0;
+ unlock:
+-      vchi_service_release(instance->vchi_handle[0]);
++      vchi_service_release(instance->vchi_handle);
+       mutex_unlock(&instance->vchi_mutex);
+       return ret;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0390-staging-bcm2835-audio-Add-10ms-period-constraint.patch b/target/linux/brcm2708/patches-4.19/950-0390-staging-bcm2835-audio-Add-10ms-period-constraint.patch
deleted file mode 100644 (file)
index 07e96f6..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From daa78c198ece1ec901ee565c869ee1a60a95061d Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:46 +0200
-Subject: [PATCH] staging: bcm2835-audio: Add 10ms period constraint
-
-commit 93c66acaf68b5247c3121a46a71ff6a70fc1d492 upstream.
-
-It seems that the resolution of vc04 callback is in 10 msec; i.e. the
-minimal period size is also 10 msec.
-
-This patch adds the corresponding hw constraint.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -145,6 +145,11 @@ static int snd_bcm2835_playback_open_gen
-                                  SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-                                  16);
-+      /* position update is in 10ms order */
-+      snd_pcm_hw_constraint_minmax(runtime,
-+                                   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
-+                                   10 * 1000, UINT_MAX);
-+
-       chip->alsa_stream[idx] = alsa_stream;
-       chip->opened |= (1 << idx);
diff --git a/target/linux/brcm2708/patches-4.19/950-0390-staging-bcm2835-audio-Code-refactoring-of-vchiq-acce.patch b/target/linux/brcm2708/patches-4.19/950-0390-staging-bcm2835-audio-Code-refactoring-of-vchiq-acce.patch
new file mode 100644 (file)
index 0000000..37ebd8b
--- /dev/null
@@ -0,0 +1,575 @@
+From 43f89ac74f3f221e3036a1ec311b24016860d15e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:48 +0200
+Subject: [PATCH] staging: bcm2835-audio: Code refactoring of vchiq
+ accessor codes
+
+commit 769a8e9bf5cf39813f52962fdafdf7e4d52ad585 upstream.
+
+This is a cleanup and code refactoring in bcm2835-vchiq.c.
+
+The major code changes are to provide local helpers for easier use of
+lock / unlock, and message passing with/without response wait.  This
+allows us to reduce lots of open codes.
+
+Also, the max packet is set at opening the stream, not at each time
+when the write gets called.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c             | 440 ++++++------------
+ 1 file changed, 142 insertions(+), 298 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -49,6 +49,7 @@ struct bcm2835_audio_instance {
+       struct mutex vchi_mutex;
+       struct bcm2835_alsa_stream *alsa_stream;
+       int result;
++      unsigned int max_packet;
+       short peer_version;
+ };
+@@ -65,16 +66,68 @@ static int bcm2835_audio_start_worker(st
+ static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+                                     unsigned int count, void *src);
+-// Routine to send a message across a service
++static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
++{
++      mutex_lock(&instance->vchi_mutex);
++      vchi_service_use(instance->vchi_handle);
++}
++
++static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
++{
++      vchi_service_release(instance->vchi_handle);
++      mutex_unlock(&instance->vchi_mutex);
++}
++
++static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance,
++                                       struct vc_audio_msg *m, bool wait)
++{
++      int status;
++
++      if (wait) {
++              instance->result = -1;
++              init_completion(&instance->msg_avail_comp);
++      }
++
++      status = vchi_queue_kernel_message(instance->vchi_handle,
++                                         m, sizeof(*m));
++      if (status) {
++              LOG_ERR("vchi message queue failed: %d, msg=%d\n",
++                      status, m->type);
++              return -EIO;
++      }
++
++      if (wait) {
++              if (!wait_for_completion_timeout(&instance->msg_avail_comp,
++                                               msecs_to_jiffies(10 * 1000))) {
++                      LOG_ERR("vchi message timeout, msg=%d\n", m->type);
++                      return -ETIMEDOUT;
++              } else if (instance->result) {
++                      LOG_ERR("vchi message response error:%d, msg=%d\n",
++                              instance->result, m->type);
++                      return -EIO;
++              }
++      }
++
++      return 0;
++}
+-static int
+-bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
+-                     void *data,
+-                     unsigned int size)
+-{
+-      return vchi_queue_kernel_message(handle,
+-                                       data,
+-                                       size);
++static int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance,
++                                struct vc_audio_msg *m, bool wait)
++{
++      int err;
++
++      bcm2835_audio_lock(instance);
++      err = bcm2835_audio_send_msg_locked(instance, m, wait);
++      bcm2835_audio_unlock(instance);
++      return err;
++}
++
++static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
++                                   int type, bool wait)
++{
++      struct vc_audio_msg m = { .type = type };
++
++      return bcm2835_audio_send_msg(instance, &m, wait);
+ }
+ static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
+@@ -283,10 +336,9 @@ static int vc_vchi_audio_deinit(struct b
+       int status;
+       mutex_lock(&instance->vchi_mutex);
+-
+-      /* Close all VCHI service connections */
+       vchi_service_use(instance->vchi_handle);
++      /* Close all VCHI service connections */
+       status = vchi_service_close(instance->vchi_handle);
+       if (status) {
+               LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
+@@ -345,12 +397,8 @@ static int bcm2835_audio_open_connection
+       instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
+                                     vhci_ctx->vchi_connection);
+-      if (IS_ERR(instance)) {
+-              LOG_ERR("%s: failed to initialize audio service\n", __func__);
+-
+-              /* vchi_instance is retained for use the next time. */
++      if (IS_ERR(instance))
+               return PTR_ERR(instance);
+-      }
+       instance->alsa_stream = alsa_stream;
+       alsa_stream->instance = instance;
+@@ -361,66 +409,44 @@ static int bcm2835_audio_open_connection
+ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       struct bcm2835_audio_instance *instance;
+-      struct vc_audio_msg m;
+-      int status;
+-      int ret;
++      int err;
+       alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
+       if (!alsa_stream->my_wq)
+               return -ENOMEM;
+-      ret = bcm2835_audio_open_connection(alsa_stream);
+-      if (ret)
++      err = bcm2835_audio_open_connection(alsa_stream);
++      if (err < 0)
+               goto free_wq;
+       instance = alsa_stream->instance;
+-      LOG_DBG(" instance (%p)\n", instance);
+-
+-      mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle);
+-
+-      m.type = VC_AUDIO_MSG_TYPE_OPEN;
+-
+-      /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                      &m, sizeof(m));
+-
+-      if (status) {
+-              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+-                      __func__, status);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      ret = 0;
+-unlock:
+-      vchi_service_release(instance->vchi_handle);
+-      mutex_unlock(&instance->vchi_mutex);
++      err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
++                                      false);
++      if (err < 0)
++              goto deinit;
++
++      bcm2835_audio_lock(instance);
++      vchi_get_peer_version(instance->vchi_handle, &instance->peer_version);
++      bcm2835_audio_unlock(instance);
++      if (instance->peer_version < 2 || force_bulk)
++              instance->max_packet = 0; /* bulk transfer */
++      else
++              instance->max_packet = 4000;
+-free_wq:
+-      if (ret)
+-              destroy_workqueue(alsa_stream->my_wq);
++      return 0;
+-      return ret;
++ deinit:
++      vc_vchi_audio_deinit(instance);
++ free_wq:
++      destroy_workqueue(alsa_stream->my_wq);
++      return err;
+ }
+ int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
+ {
+-      struct vc_audio_msg m;
+-      struct bcm2835_audio_instance *instance = alsa_stream->instance;
+       struct bcm2835_chip *chip = alsa_stream->chip;
+-      int status;
+-      int ret;
+-
+-      LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
+-               chip->dest, chip->volume);
+-
+-      mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle);
+-
+-      instance->result = -1;
++      struct vc_audio_msg m = {};
+       m.type = VC_AUDIO_MSG_TYPE_CONTROL;
+       m.u.control.dest = chip->dest;
+@@ -429,289 +455,107 @@ int bcm2835_audio_set_ctls(struct bcm283
+       else
+               m.u.control.volume = alsa2chip(chip->volume);
+-      /* Create the message available completion */
+-      init_completion(&instance->msg_avail_comp);
+-
+-      /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                      &m, sizeof(m));
+-
+-      if (status) {
+-              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+-                      __func__, status);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      /* We are expecting a reply from the videocore */
+-      wait_for_completion(&instance->msg_avail_comp);
+-
+-      if (instance->result) {
+-              LOG_ERR("%s: result=%d\n", __func__, instance->result);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      ret = 0;
+-
+-unlock:
+-      vchi_service_release(instance->vchi_handle);
+-      mutex_unlock(&instance->vchi_mutex);
+-
+-      return ret;
++      return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
+                            unsigned int channels, unsigned int samplerate,
+                            unsigned int bps)
+ {
+-      struct vc_audio_msg m;
+-      struct bcm2835_audio_instance *instance = alsa_stream->instance;
+-      int status;
+-      int ret;
+-
+-      LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
+-               channels, samplerate, bps);
++      struct vc_audio_msg m = {
++               .type = VC_AUDIO_MSG_TYPE_CONFIG,
++               .u.config.channels = channels,
++               .u.config.samplerate = samplerate,
++               .u.config.bps = bps,
++      };
++      int err;
+       /* resend ctls - alsa_stream may not have been open when first send */
+-      ret = bcm2835_audio_set_ctls(alsa_stream);
+-      if (ret) {
+-              LOG_ERR(" Alsa controls not supported\n");
+-              return -EINVAL;
+-      }
++      err = bcm2835_audio_set_ctls(alsa_stream);
++      if (err)
++              return err;
+-      mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle);
+-
+-      instance->result = -1;
+-
+-      m.type = VC_AUDIO_MSG_TYPE_CONFIG;
+-      m.u.config.channels = channels;
+-      m.u.config.samplerate = samplerate;
+-      m.u.config.bps = bps;
+-
+-      /* Create the message available completion */
+-      init_completion(&instance->msg_avail_comp);
+-
+-      /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                      &m, sizeof(m));
+-
+-      if (status) {
+-              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+-                      __func__, status);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      /* We are expecting a reply from the videocore */
+-      wait_for_completion(&instance->msg_avail_comp);
+-
+-      if (instance->result) {
+-              LOG_ERR("%s: result=%d", __func__, instance->result);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      ret = 0;
+-
+-unlock:
+-      vchi_service_release(instance->vchi_handle);
+-      mutex_unlock(&instance->vchi_mutex);
+-
+-      return ret;
++      return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+ static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
+ {
+-      struct vc_audio_msg m;
+-      struct bcm2835_audio_instance *instance = alsa_stream->instance;
+-      int status;
+-      int ret;
+-
+-      mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle);
+-
+-      m.type = VC_AUDIO_MSG_TYPE_START;
+-
+-      /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                      &m, sizeof(m));
+-
+-      if (status) {
+-              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+-                      __func__, status);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      ret = 0;
+-
+-unlock:
+-      vchi_service_release(instance->vchi_handle);
+-      mutex_unlock(&instance->vchi_mutex);
+-      return ret;
++      return bcm2835_audio_send_simple(alsa_stream->instance,
++                                       VC_AUDIO_MSG_TYPE_START, false);
+ }
+ static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
+ {
+-      struct vc_audio_msg m;
+-      struct bcm2835_audio_instance *instance = alsa_stream->instance;
+-      int status;
+-      int ret;
+-
+-      mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle);
+-
+-      m.type = VC_AUDIO_MSG_TYPE_STOP;
+-      m.u.stop.draining = alsa_stream->draining;
+-
+-      /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                      &m, sizeof(m));
+-
+-      if (status) {
+-              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+-                      __func__, status);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      ret = 0;
+-
+-unlock:
+-      vchi_service_release(instance->vchi_handle);
+-      mutex_unlock(&instance->vchi_mutex);
+-      return ret;
++      return bcm2835_audio_send_simple(alsa_stream->instance,
++                                       VC_AUDIO_MSG_TYPE_STOP, false);
+ }
+ int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
+ {
+-      struct vc_audio_msg m;
+       struct bcm2835_audio_instance *instance = alsa_stream->instance;
+-      int status;
+-      int ret;
++      int err;
+       my_workqueue_quit(alsa_stream);
+-      mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle);
+-
+-      m.type = VC_AUDIO_MSG_TYPE_CLOSE;
+-
+-      /* Create the message available completion */
+-      init_completion(&instance->msg_avail_comp);
+-
+-      /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                      &m, sizeof(m));
+-
+-      if (status) {
+-              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+-                      __func__, status);
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      /* We are expecting a reply from the videocore */
+-      wait_for_completion(&instance->msg_avail_comp);
+-
+-      if (instance->result) {
+-              LOG_ERR("%s: failed result (result=%d)\n",
+-                      __func__, instance->result);
+-
+-              ret = -1;
+-              goto unlock;
+-      }
+-
+-      ret = 0;
+-
+-unlock:
+-      vchi_service_release(instance->vchi_handle);
+-      mutex_unlock(&instance->vchi_mutex);
++      err = bcm2835_audio_send_simple(alsa_stream->instance,
++                                      VC_AUDIO_MSG_TYPE_CLOSE, true);
+       /* Stop the audio service */
+       vc_vchi_audio_deinit(instance);
+       alsa_stream->instance = NULL;
+-      return ret;
++      return err;
+ }
+ static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+-                                    unsigned int count, void *src)
++                                    unsigned int size, void *src)
+ {
+-      struct vc_audio_msg m;
+       struct bcm2835_audio_instance *instance = alsa_stream->instance;
+-      int status;
+-      int ret;
+-
+-      LOG_INFO(" Writing %d bytes from %p\n", count, src);
+-
+-      mutex_lock(&instance->vchi_mutex);
+-      vchi_service_use(instance->vchi_handle);
++      struct vc_audio_msg m = {
++              .type = VC_AUDIO_MSG_TYPE_WRITE,
++              .u.write.count = size,
++              .u.write.max_packet = instance->max_packet,
++              .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
++              .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
++      };
++      unsigned int count;
++      int err, status;
+-      if (instance->peer_version == 0 &&
+-          vchi_get_peer_version(instance->vchi_handle, &instance->peer_version) == 0)
+-              LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
+-
+-      m.type = VC_AUDIO_MSG_TYPE_WRITE;
+-      m.u.write.count = count;
+-      // old version uses bulk, new version uses control
+-      m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0 : 4000;
+-      m.u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1;
+-      m.u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2;
+-      m.u.write.silence = src == NULL;
+-
+-      /* Send the message to the videocore */
+-      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                      &m, sizeof(m));
++      if (!size)
++              return 0;
+-      if (status) {
+-              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+-                      __func__, status);
+-
+-              ret = -1;
++      bcm2835_audio_lock(instance);
++      err = bcm2835_audio_send_msg_locked(instance, &m, false);
++      if (err < 0)
+               goto unlock;
+-      }
+-      if (!m.u.write.silence) {
+-              if (!m.u.write.max_packet) {
+-                      /* Send the message to the videocore */
+-                      status = vchi_bulk_queue_transmit(instance->vchi_handle,
+-                                                        src, count,
+-                                                        0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
+-                                                        +
+-                                                        1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
+-                                                        NULL);
+-              } else {
+-                      while (count > 0) {
+-                              int bytes = min_t(int, m.u.write.max_packet, count);
+-                              status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+-                                                              src, bytes);
+-                              src = (char *)src + bytes;
+-                              count -= bytes;
+-                      }
+-              }
+-              if (status) {
+-                      LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
+-                              __func__, status);
++      count = size;
++      if (!instance->max_packet) {
++              /* Send the message to the videocore */
++              status = vchi_bulk_queue_transmit(instance->vchi_handle,
++                                                src, count,
++                                                VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
++                                                NULL);
++      } else {
++              while (count > 0) {
++                      int bytes = min(instance->max_packet, count);
+-                      ret = -1;
+-                      goto unlock;
++                      status = vchi_queue_kernel_message(instance->vchi_handle,
++                                                         src, bytes);
++                      src += bytes;
++                      count -= bytes;
+               }
+       }
+-      ret = 0;
+-unlock:
+-      vchi_service_release(instance->vchi_handle);
+-      mutex_unlock(&instance->vchi_mutex);
+-      return ret;
++      if (status) {
++              LOG_ERR("failed on %d bytes transfer (status=%d)\n",
++                      size, status);
++              err = -EIO;
++      }
++
++ unlock:
++      bcm2835_audio_unlock(instance);
++      return err;
+ }
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
diff --git a/target/linux/brcm2708/patches-4.19/950-0391-staging-bcm2835-audio-Make-single-vchi-handle.patch b/target/linux/brcm2708/patches-4.19/950-0391-staging-bcm2835-audio-Make-single-vchi-handle.patch
deleted file mode 100644 (file)
index eb6538d..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-From 98a1612b199cb3060306c05d1a6d7ca18ef08475 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:47 +0200
-Subject: [PATCH] staging: bcm2835-audio: Make single vchi handle
-
-commit 326a6edcb2ada56375bd7d3fc24c83f58e8da7f3 upstream.
-
-The bcm2835_audio_instance object contains the array of
-VCHI_SERVICE_HANDLE_T, while the code assumes and uses only the first
-element explicitly.  Let's reduce to a single vchi handle for
-simplifying the code.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c             | 170 ++++++------------
- 1 file changed, 58 insertions(+), 112 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -44,8 +44,7 @@
- #endif
- struct bcm2835_audio_instance {
--      unsigned int num_connections;
--      VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
-+      VCHI_SERVICE_HANDLE_T vchi_handle;
-       struct completion msg_avail_comp;
-       struct mutex vchi_mutex;
-       struct bcm2835_alsa_stream *alsa_stream;
-@@ -202,12 +201,12 @@ static void audio_vchi_callback(void *pa
-               BUG();
-               return;
-       }
--      if (!instance->vchi_handle[0]) {
--              LOG_ERR(" .. instance->vchi_handle[0] is null\n");
-+      if (!instance->vchi_handle) {
-+              LOG_ERR(" .. instance->vchi_handle is null\n");
-               BUG();
-               return;
-       }
--      status = vchi_msg_dequeue(instance->vchi_handle[0],
-+      status = vchi_msg_dequeue(instance->vchi_handle,
-                                 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
-       if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
-               LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
-@@ -237,102 +236,61 @@ static void audio_vchi_callback(void *pa
- static struct bcm2835_audio_instance *
- vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
--                 VCHI_CONNECTION_T **vchi_connections,
--                 unsigned int num_connections)
-+                 VCHI_CONNECTION_T *vchi_connection)
- {
--      unsigned int i;
-+      SERVICE_CREATION_T params = {
-+              .version                = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
-+              .service_id             = VC_AUDIO_SERVER_NAME,
-+              .connection             = vchi_connection,
-+              .rx_fifo_size           = 0,
-+              .tx_fifo_size           = 0,
-+              .callback               = audio_vchi_callback,
-+              .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
-+              .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
-+              .want_crc               = 0
-+      };
-       struct bcm2835_audio_instance *instance;
-       int status;
--      int ret;
--
--      LOG_DBG("%s: start", __func__);
--      if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
--              LOG_ERR("%s: unsupported number of connections %u (max=%u)\n",
--                      __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
--
--              return ERR_PTR(-EINVAL);
--      }
-       /* Allocate memory for this instance */
-       instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-       if (!instance)
-               return ERR_PTR(-ENOMEM);
--      instance->num_connections = num_connections;
--
-       /* Create a lock for exclusive, serialized VCHI connection access */
-       mutex_init(&instance->vchi_mutex);
-       /* Open the VCHI service connections */
--      for (i = 0; i < num_connections; i++) {
--              SERVICE_CREATION_T params = {
--                      .version                = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
--                      .service_id             = VC_AUDIO_SERVER_NAME,
--                      .connection             = vchi_connections[i],
--                      .rx_fifo_size           = 0,
--                      .tx_fifo_size           = 0,
--                      .callback               = audio_vchi_callback,
--                      .callback_param         = instance,
--                      .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
--                      .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
--                      .want_crc               = 0
--              };
--
--              LOG_DBG("%s: about to open %i\n", __func__, i);
--              status = vchi_service_open(vchi_instance, &params,
--                                         &instance->vchi_handle[i]);
-+      params.callback_param = instance,
--              LOG_DBG("%s: opened %i: %p=%d\n", __func__, i, instance->vchi_handle[i], status);
--              if (status) {
--                      LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
--                              __func__, status);
--                      ret = -EPERM;
--                      goto err_close_services;
--              }
--              /* Finished with the service for now */
--              vchi_service_release(instance->vchi_handle[i]);
--      }
--
--      LOG_DBG("%s: okay\n", __func__);
--      return instance;
-+      status = vchi_service_open(vchi_instance, &params,
-+                                 &instance->vchi_handle);
--err_close_services:
--      for (i = 0; i < instance->num_connections; i++) {
--              LOG_ERR("%s: closing %i: %p\n", __func__, i, instance->vchi_handle[i]);
--              if (instance->vchi_handle[i])
--                      vchi_service_close(instance->vchi_handle[i]);
-+      if (status) {
-+              LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
-+                      __func__, status);
-+              kfree(instance);
-+              return ERR_PTR(-EPERM);
-       }
--      kfree(instance);
--      LOG_ERR("%s: error\n", __func__);
-+      /* Finished with the service for now */
-+      vchi_service_release(instance->vchi_handle);
--      return ERR_PTR(ret);
-+      return instance;
- }
- static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
- {
--      unsigned int i;
--
--      if (!instance) {
--              LOG_ERR("%s: invalid handle %p\n", __func__, instance);
--
--              return -1;
--      }
-+      int status;
--      LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
-       mutex_lock(&instance->vchi_mutex);
-       /* Close all VCHI service connections */
--      for (i = 0; i < instance->num_connections; i++) {
--              int status;
--
--              LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]);
--              vchi_service_use(instance->vchi_handle[i]);
-+      vchi_service_use(instance->vchi_handle);
--              status = vchi_service_close(instance->vchi_handle[i]);
--              if (status) {
--                      LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
--                              __func__, status);
--              }
-+      status = vchi_service_close(instance->vchi_handle);
-+      if (status) {
-+              LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
-+                      __func__, status);
-       }
-       mutex_unlock(&instance->vchi_mutex);
-@@ -383,19 +341,9 @@ static int bcm2835_audio_open_connection
-               (struct bcm2835_audio_instance *)alsa_stream->instance;
-       struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
--      LOG_INFO("%s: start\n", __func__);
--      BUG_ON(instance);
--      if (instance) {
--              LOG_ERR("%s: VCHI instance already open (%p)\n",
--                      __func__, instance);
--              instance->alsa_stream = alsa_stream;
--              alsa_stream->instance = instance;
--              return 0;
--      }
--
-       /* Initialize an instance of the audio service */
-       instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
--                                    &vhci_ctx->vchi_connection, 1);
-+                                    vhci_ctx->vchi_connection);
-       if (IS_ERR(instance)) {
-               LOG_ERR("%s: failed to initialize audio service\n", __func__);
-@@ -407,8 +355,6 @@ static int bcm2835_audio_open_connection
-       instance->alsa_stream = alsa_stream;
-       alsa_stream->instance = instance;
--      LOG_DBG(" success !\n");
--
-       return 0;
- }
-@@ -431,12 +377,12 @@ int bcm2835_audio_open(struct bcm2835_al
-       LOG_DBG(" instance (%p)\n", instance);
-       mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle[0]);
-+      vchi_service_use(instance->vchi_handle);
-       m.type = VC_AUDIO_MSG_TYPE_OPEN;
-       /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                       &m, sizeof(m));
-       if (status) {
-@@ -450,7 +396,7 @@ int bcm2835_audio_open(struct bcm2835_al
-       ret = 0;
- unlock:
--      vchi_service_release(instance->vchi_handle[0]);
-+      vchi_service_release(instance->vchi_handle);
-       mutex_unlock(&instance->vchi_mutex);
- free_wq:
-@@ -472,7 +418,7 @@ int bcm2835_audio_set_ctls(struct bcm283
-                chip->dest, chip->volume);
-       mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle[0]);
-+      vchi_service_use(instance->vchi_handle);
-       instance->result = -1;
-@@ -487,7 +433,7 @@ int bcm2835_audio_set_ctls(struct bcm283
-       init_completion(&instance->msg_avail_comp);
-       /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                       &m, sizeof(m));
-       if (status) {
-@@ -511,7 +457,7 @@ int bcm2835_audio_set_ctls(struct bcm283
-       ret = 0;
- unlock:
--      vchi_service_release(instance->vchi_handle[0]);
-+      vchi_service_release(instance->vchi_handle);
-       mutex_unlock(&instance->vchi_mutex);
-       return ret;
-@@ -537,7 +483,7 @@ int bcm2835_audio_set_params(struct bcm2
-       }
-       mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle[0]);
-+      vchi_service_use(instance->vchi_handle);
-       instance->result = -1;
-@@ -550,7 +496,7 @@ int bcm2835_audio_set_params(struct bcm2
-       init_completion(&instance->msg_avail_comp);
-       /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                       &m, sizeof(m));
-       if (status) {
-@@ -574,7 +520,7 @@ int bcm2835_audio_set_params(struct bcm2
-       ret = 0;
- unlock:
--      vchi_service_release(instance->vchi_handle[0]);
-+      vchi_service_release(instance->vchi_handle);
-       mutex_unlock(&instance->vchi_mutex);
-       return ret;
-@@ -588,12 +534,12 @@ static int bcm2835_audio_start_worker(st
-       int ret;
-       mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle[0]);
-+      vchi_service_use(instance->vchi_handle);
-       m.type = VC_AUDIO_MSG_TYPE_START;
-       /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                       &m, sizeof(m));
-       if (status) {
-@@ -607,7 +553,7 @@ static int bcm2835_audio_start_worker(st
-       ret = 0;
- unlock:
--      vchi_service_release(instance->vchi_handle[0]);
-+      vchi_service_release(instance->vchi_handle);
-       mutex_unlock(&instance->vchi_mutex);
-       return ret;
- }
-@@ -620,13 +566,13 @@ static int bcm2835_audio_stop_worker(str
-       int ret;
-       mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle[0]);
-+      vchi_service_use(instance->vchi_handle);
-       m.type = VC_AUDIO_MSG_TYPE_STOP;
-       m.u.stop.draining = alsa_stream->draining;
-       /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                       &m, sizeof(m));
-       if (status) {
-@@ -640,7 +586,7 @@ static int bcm2835_audio_stop_worker(str
-       ret = 0;
- unlock:
--      vchi_service_release(instance->vchi_handle[0]);
-+      vchi_service_release(instance->vchi_handle);
-       mutex_unlock(&instance->vchi_mutex);
-       return ret;
- }
-@@ -655,7 +601,7 @@ int bcm2835_audio_close(struct bcm2835_a
-       my_workqueue_quit(alsa_stream);
-       mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle[0]);
-+      vchi_service_use(instance->vchi_handle);
-       m.type = VC_AUDIO_MSG_TYPE_CLOSE;
-@@ -663,7 +609,7 @@ int bcm2835_audio_close(struct bcm2835_a
-       init_completion(&instance->msg_avail_comp);
-       /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                       &m, sizeof(m));
-       if (status) {
-@@ -687,7 +633,7 @@ int bcm2835_audio_close(struct bcm2835_a
-       ret = 0;
- unlock:
--      vchi_service_release(instance->vchi_handle[0]);
-+      vchi_service_release(instance->vchi_handle);
-       mutex_unlock(&instance->vchi_mutex);
-       /* Stop the audio service */
-@@ -708,10 +654,10 @@ static int bcm2835_audio_write_worker(st
-       LOG_INFO(" Writing %d bytes from %p\n", count, src);
-       mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle[0]);
-+      vchi_service_use(instance->vchi_handle);
-       if (instance->peer_version == 0 &&
--          vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0)
-+          vchi_get_peer_version(instance->vchi_handle, &instance->peer_version) == 0)
-               LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
-       m.type = VC_AUDIO_MSG_TYPE_WRITE;
-@@ -723,7 +669,7 @@ static int bcm2835_audio_write_worker(st
-       m.u.write.silence = src == NULL;
-       /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                       &m, sizeof(m));
-       if (status) {
-@@ -736,7 +682,7 @@ static int bcm2835_audio_write_worker(st
-       if (!m.u.write.silence) {
-               if (!m.u.write.max_packet) {
-                       /* Send the message to the videocore */
--                      status = vchi_bulk_queue_transmit(instance->vchi_handle[0],
-+                      status = vchi_bulk_queue_transmit(instance->vchi_handle,
-                                                         src, count,
-                                                         0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
-                                                         +
-@@ -746,7 +692,7 @@ static int bcm2835_audio_write_worker(st
-                       while (count > 0) {
-                               int bytes = min_t(int, m.u.write.max_packet, count);
--                              status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+                              status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-                                                               src, bytes);
-                               src = (char *)src + bytes;
-                               count -= bytes;
-@@ -763,7 +709,7 @@ static int bcm2835_audio_write_worker(st
-       ret = 0;
- unlock:
--      vchi_service_release(instance->vchi_handle[0]);
-+      vchi_service_release(instance->vchi_handle);
-       mutex_unlock(&instance->vchi_mutex);
-       return ret;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0391-staging-bcm2835-audio-Operate-non-atomic-PCM-ops.patch b/target/linux/brcm2708/patches-4.19/950-0391-staging-bcm2835-audio-Operate-non-atomic-PCM-ops.patch
new file mode 100644 (file)
index 0000000..722804f
--- /dev/null
@@ -0,0 +1,593 @@
+From 87ba8310e9f0882e85926ac1ef91333f8906b303 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:49 +0200
+Subject: [PATCH] staging: bcm2835-audio: Operate non-atomic PCM ops
+
+commit 5c7883e5f27e829f3f3a2ba174d4a724bfd5f026 upstream.
+
+This is the most significant part in the patch series.
+
+The bcm2835-audio driver used to queue the commands to vc04 core via
+workqueue, but basically the whole accesses to vc04 core are done in
+the sleepable context, including the callback calls.  In such a case,
+rewriting the code using non-atomic PCM ops will simplify the logic a
+lot.
+
+This patch does it: all workqueue are gone and each former-work
+implementation is now directly called from PCM ops like trigger and
+write transfer.
+
+Along with it, the DMA position updater, bcm2835_playback_fifo(), was
+also rewritten to use a simpler logic.  Now it handles the XRUN and
+draining properly by calling snd_pcm_stop() conditionally.
+
+The current position is kept in atomic_t value so that it can be read
+concurrently from the pointer callback.
+
+Also, the bcm2835_audio_instance object is allocated at the beginning
+of bcm2835_audio_open().  This makes the resource management clearer.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  74 +++---
+ .../bcm2835-audio/bcm2835-vchiq.c             | 244 +++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.h     |   9 +-
+ 3 files changed, 82 insertions(+), 245 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -11,7 +11,8 @@
+ /* hardware definition */
+ static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+-      SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
++               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
++               SNDRV_PCM_INFO_DRAIN_TRIGGER),
+       .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+       .rate_min = 8000,
+@@ -27,7 +28,8 @@ static const struct snd_pcm_hardware snd
+ static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+-      SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
++               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
++               SNDRV_PCM_INFO_DRAIN_TRIGGER),
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
+       SNDRV_PCM_RATE_48000,
+@@ -47,42 +49,34 @@ static void snd_bcm2835_playback_free(st
+       kfree(runtime->private_data);
+ }
+-void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
++void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
++                         unsigned int bytes)
+ {
+-      unsigned int consumed = 0;
+-      int new_period = 0;
++      struct snd_pcm_substream *substream = alsa_stream->substream;
++      unsigned int pos;
+-      audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
+-              alsa_stream ? alsa_stream->substream : 0);
++      if (!alsa_stream->period_size)
++              return;
+-      consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
+-
+-      /* We get called only if playback was triggered, So, the number of buffers we retrieve in
+-       * each iteration are the buffers that have been played out already
+-       */
+-
+-      if (alsa_stream->period_size) {
+-              if ((alsa_stream->pos / alsa_stream->period_size) !=
+-                      ((alsa_stream->pos + consumed) / alsa_stream->period_size))
+-                      new_period = 1;
+-      }
+-      audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n",
+-              alsa_stream->pos,
+-              consumed,
+-              alsa_stream->buffer_size,
+-              (int) (alsa_stream->period_size * alsa_stream->substream->runtime->periods),
+-              frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr),
+-              new_period);
+-      if (alsa_stream->buffer_size) {
+-              alsa_stream->pos += consumed & ~(1 << 30);
+-              alsa_stream->pos %= alsa_stream->buffer_size;
++      if (bytes >= alsa_stream->buffer_size) {
++              snd_pcm_stream_lock(substream);
++              snd_pcm_stop(substream,
++                           alsa_stream->draining ?
++                           SNDRV_PCM_STATE_SETUP :
++                           SNDRV_PCM_STATE_XRUN);
++              snd_pcm_stream_unlock(substream);
++              return;
+       }
+-      if (alsa_stream->substream) {
+-              if (new_period)
+-                      snd_pcm_period_elapsed(alsa_stream->substream);
+-      } else {
+-              audio_warning(" unexpected NULL substream\n");
++      pos = atomic_read(&alsa_stream->pos);
++      pos += bytes;
++      pos %= alsa_stream->buffer_size;
++      atomic_set(&alsa_stream->pos, pos);
++
++      alsa_stream->period_offset += bytes;
++      if (alsa_stream->period_offset >= alsa_stream->period_size) {
++              alsa_stream->period_offset %= alsa_stream->period_size;
++              snd_pcm_period_elapsed(substream);
+       }
+ }
+@@ -246,7 +240,8 @@ static int snd_bcm2835_pcm_prepare(struc
+       alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
+-      alsa_stream->pos = 0;
++      atomic_set(&alsa_stream->pos, 0);
++      alsa_stream->period_offset = 0;
+       alsa_stream->draining = false;
+       return 0;
+@@ -283,7 +278,7 @@ static int snd_bcm2835_pcm_trigger(struc
+               return bcm2835_audio_start(alsa_stream);
+       case SNDRV_PCM_TRIGGER_DRAIN:
+               alsa_stream->draining = true;
+-              return 0;
++              return bcm2835_audio_drain(alsa_stream);
+       case SNDRV_PCM_TRIGGER_STOP:
+               return bcm2835_audio_stop(alsa_stream);
+       default:
+@@ -300,7 +295,7 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
+       return snd_pcm_indirect_playback_pointer(substream,
+               &alsa_stream->pcm_indirect,
+-              alsa_stream->pos);
++              atomic_read(&alsa_stream->pos));
+ }
+ /* operators */
+@@ -338,6 +333,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+       if (err < 0)
+               return err;
+       pcm->private_data = chip;
++      pcm->nonatomic = true;
+       strcpy(pcm->name, "bcm2835 ALSA");
+       chip->pcm = pcm;
+       chip->dest = AUDIO_DEST_AUTO;
+@@ -367,6 +363,7 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+               return err;
+       pcm->private_data = chip;
++      pcm->nonatomic = true;
+       strcpy(pcm->name, "bcm2835 IEC958/HDMI");
+       chip->pcm_spdif = pcm;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+@@ -395,6 +392,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
+               return err;
+       pcm->private_data = chip;
++      pcm->nonatomic = true;
+       strcpy(pcm->name, name);
+       chip->pcm = pcm;
+       chip->dest = route;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -26,10 +26,6 @@
+ /* ---- Private Constants and Types ------------------------------------------ */
+-#define BCM2835_AUDIO_STOP           0
+-#define BCM2835_AUDIO_START          1
+-#define BCM2835_AUDIO_WRITE          2
+-
+ /* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
+ #ifdef AUDIO_DEBUG_ENABLE
+ #define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
+@@ -55,17 +51,6 @@ struct bcm2835_audio_instance {
+ static bool force_bulk;
+-/* ---- Private Variables ---------------------------------------------------- */
+-
+-/* ---- Private Function Prototypes ------------------------------------------ */
+-
+-/* ---- Private Functions ---------------------------------------------------- */
+-
+-static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream);
+-static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream);
+-static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+-                                    unsigned int count, void *src);
+-
+ static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
+ {
+       mutex_lock(&instance->vchi_mutex);
+@@ -135,108 +120,6 @@ static const u32 BCM2835_AUDIO_WRITE_COO
+ static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
+                                               'T' << 8  | 'A');
+-struct bcm2835_audio_work {
+-      struct work_struct my_work;
+-      struct bcm2835_alsa_stream *alsa_stream;
+-      int cmd;
+-      void *src;
+-      unsigned int count;
+-};
+-
+-static void my_wq_function(struct work_struct *work)
+-{
+-      struct bcm2835_audio_work *w =
+-              container_of(work, struct bcm2835_audio_work, my_work);
+-      int ret = -9;
+-
+-      switch (w->cmd) {
+-      case BCM2835_AUDIO_START:
+-              ret = bcm2835_audio_start_worker(w->alsa_stream);
+-              break;
+-      case BCM2835_AUDIO_STOP:
+-              ret = bcm2835_audio_stop_worker(w->alsa_stream);
+-              break;
+-      case BCM2835_AUDIO_WRITE:
+-              ret = bcm2835_audio_write_worker(w->alsa_stream, w->count,
+-                                               w->src);
+-              break;
+-      default:
+-              LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->cmd);
+-              break;
+-      }
+-      kfree((void *)work);
+-}
+-
+-int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-      struct bcm2835_audio_work *work;
+-
+-      work = kmalloc(sizeof(*work), GFP_ATOMIC);
+-      /*--- Queue some work (item 1) ---*/
+-      if (!work) {
+-              LOG_ERR(" .. Error: NULL work kmalloc\n");
+-              return -ENOMEM;
+-      }
+-      INIT_WORK(&work->my_work, my_wq_function);
+-      work->alsa_stream = alsa_stream;
+-      work->cmd = BCM2835_AUDIO_START;
+-      if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
+-              kfree(work);
+-              return -EBUSY;
+-      }
+-      return 0;
+-}
+-
+-int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-      struct bcm2835_audio_work *work;
+-
+-      work = kmalloc(sizeof(*work), GFP_ATOMIC);
+-      /*--- Queue some work (item 1) ---*/
+-      if (!work) {
+-              LOG_ERR(" .. Error: NULL work kmalloc\n");
+-              return -ENOMEM;
+-      }
+-      INIT_WORK(&work->my_work, my_wq_function);
+-      work->alsa_stream = alsa_stream;
+-      work->cmd = BCM2835_AUDIO_STOP;
+-      if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
+-              kfree(work);
+-              return -EBUSY;
+-      }
+-      return 0;
+-}
+-
+-int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
+-                      unsigned int count, void *src)
+-{
+-      struct bcm2835_audio_work *work;
+-
+-      work = kmalloc(sizeof(*work), GFP_ATOMIC);
+-      /*--- Queue some work (item 1) ---*/
+-      if (!work) {
+-              LOG_ERR(" .. Error: NULL work kmalloc\n");
+-              return -ENOMEM;
+-      }
+-      INIT_WORK(&work->my_work, my_wq_function);
+-      work->alsa_stream = alsa_stream;
+-      work->cmd = BCM2835_AUDIO_WRITE;
+-      work->src = src;
+-      work->count = count;
+-      if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
+-              kfree(work);
+-              return -EBUSY;
+-      }
+-      return 0;
+-}
+-
+-static void my_workqueue_quit(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-      flush_workqueue(alsa_stream->my_wq);
+-      destroy_workqueue(alsa_stream->my_wq);
+-      alsa_stream->my_wq = NULL;
+-}
+-
+ static void audio_vchi_callback(void *param,
+                               const VCHI_CALLBACK_REASON_T reason,
+                               void *msg_handle)
+@@ -249,47 +132,27 @@ static void audio_vchi_callback(void *pa
+       if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
+               return;
+-      if (!instance) {
+-              LOG_ERR(" .. instance is null\n");
+-              BUG();
+-              return;
+-      }
+-      if (!instance->vchi_handle) {
+-              LOG_ERR(" .. instance->vchi_handle is null\n");
+-              BUG();
+-              return;
+-      }
+       status = vchi_msg_dequeue(instance->vchi_handle,
+                                 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
+       if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
+-              LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
+-                      instance, m.u.result.success);
+               instance->result = m.u.result.success;
+               complete(&instance->msg_avail_comp);
+       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
+-              struct bcm2835_alsa_stream *alsa_stream = instance->alsa_stream;
+-
+-              LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
+-                      instance, m.u.complete.count);
+               if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
+                   m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
+-                      LOG_ERR(" .. response is corrupt\n");
+-              else if (alsa_stream) {
+-                      atomic_add(m.u.complete.count,
+-                                 &alsa_stream->retrieved);
+-                      bcm2835_playback_fifo(alsa_stream);
+-              } else {
+-                      LOG_ERR(" .. unexpected alsa_stream=%p\n",
+-                              alsa_stream);
+-              }
++                      LOG_ERR("invalid cookie\n");
++              else
++                      bcm2835_playback_fifo(instance->alsa_stream,
++                                            m.u.complete.count);
+       } else {
+-              LOG_ERR(" .. unexpected m.type=%d\n", m.type);
++              LOG_ERR("unexpected callback type=%d\n", m.type);
+       }
+ }
+-static struct bcm2835_audio_instance *
++static int
+ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
+-                 VCHI_CONNECTION_T *vchi_connection)
++                 VCHI_CONNECTION_T *vchi_connection,
++                 struct bcm2835_audio_instance *instance)
+ {
+       SERVICE_CREATION_T params = {
+               .version                = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
+@@ -298,23 +161,14 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+               .rx_fifo_size           = 0,
+               .tx_fifo_size           = 0,
+               .callback               = audio_vchi_callback,
++              .callback_param         = instance,
+               .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
+               .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
+               .want_crc               = 0
+       };
+-      struct bcm2835_audio_instance *instance;
+       int status;
+-      /* Allocate memory for this instance */
+-      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+-      if (!instance)
+-              return ERR_PTR(-ENOMEM);
+-
+-      /* Create a lock for exclusive, serialized VCHI connection access */
+-      mutex_init(&instance->vchi_mutex);
+       /* Open the VCHI service connections */
+-      params.callback_param = instance,
+-
+       status = vchi_service_open(vchi_instance, &params,
+                                  &instance->vchi_handle);
+@@ -322,16 +176,16 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+               LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
+                       __func__, status);
+               kfree(instance);
+-              return ERR_PTR(-EPERM);
++              return -EPERM;
+       }
+       /* Finished with the service for now */
+       vchi_service_release(instance->vchi_handle);
+-      return instance;
++      return 0;
+ }
+-static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
++static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
+ {
+       int status;
+@@ -346,10 +200,6 @@ static int vc_vchi_audio_deinit(struct b
+       }
+       mutex_unlock(&instance->vchi_mutex);
+-
+-      kfree(instance);
+-
+-      return 0;
+ }
+ int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
+@@ -387,39 +237,25 @@ void bcm2835_free_vchi_ctx(struct bcm283
+       vchi_ctx->vchi_instance = NULL;
+ }
+-static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-      struct bcm2835_audio_instance *instance =
+-              (struct bcm2835_audio_instance *)alsa_stream->instance;
+-      struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
+-
+-      /* Initialize an instance of the audio service */
+-      instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
+-                                    vhci_ctx->vchi_connection);
+-
+-      if (IS_ERR(instance))
+-              return PTR_ERR(instance);
+-
+-      instance->alsa_stream = alsa_stream;
+-      alsa_stream->instance = instance;
+-
+-      return 0;
+-}
+-
+ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
+ {
++      struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx;
+       struct bcm2835_audio_instance *instance;
+       int err;
+-      alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
+-      if (!alsa_stream->my_wq)
++      /* Allocate memory for this instance */
++      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++      if (!instance)
+               return -ENOMEM;
++      mutex_init(&instance->vchi_mutex);
++      instance->alsa_stream = alsa_stream;
++      alsa_stream->instance = instance;
+-      err = bcm2835_audio_open_connection(alsa_stream);
++      err = vc_vchi_audio_init(vchi_ctx->vchi_instance,
++                               vchi_ctx->vchi_connection,
++                               instance);
+       if (err < 0)
+-              goto free_wq;
+-
+-      instance = alsa_stream->instance;
++              goto free_instance;
+       err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
+                                       false);
+@@ -438,8 +274,9 @@ int bcm2835_audio_open(struct bcm2835_al
+  deinit:
+       vc_vchi_audio_deinit(instance);
+- free_wq:
+-      destroy_workqueue(alsa_stream->my_wq);
++ free_instance:
++      alsa_stream->instance = NULL;
++      kfree(instance);
+       return err;
+ }
+@@ -478,37 +315,46 @@ int bcm2835_audio_set_params(struct bcm2
+       return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+-static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
++int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       return bcm2835_audio_send_simple(alsa_stream->instance,
+                                        VC_AUDIO_MSG_TYPE_START, false);
+ }
+-static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
++int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       return bcm2835_audio_send_simple(alsa_stream->instance,
+                                        VC_AUDIO_MSG_TYPE_STOP, false);
+ }
++int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
++{
++      struct vc_audio_msg m = {
++              .type = VC_AUDIO_MSG_TYPE_STOP,
++              .u.stop.draining = 1,
++      };
++
++      return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
++}
++
+ int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       struct bcm2835_audio_instance *instance = alsa_stream->instance;
+       int err;
+-      my_workqueue_quit(alsa_stream);
+-
+       err = bcm2835_audio_send_simple(alsa_stream->instance,
+                                       VC_AUDIO_MSG_TYPE_CLOSE, true);
+       /* Stop the audio service */
+       vc_vchi_audio_deinit(instance);
+       alsa_stream->instance = NULL;
++      kfree(instance);
+       return err;
+ }
+-static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+-                                    unsigned int size, void *src)
++int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
++                      unsigned int size, void *src)
+ {
+       struct bcm2835_audio_instance *instance = alsa_stream->instance;
+       struct vc_audio_msg m = {
+@@ -558,13 +404,5 @@ static int bcm2835_audio_write_worker(st
+       return err;
+ }
+-unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-      unsigned int count = atomic_read(&alsa_stream->retrieved);
+-
+-      atomic_sub(count, &alsa_stream->retrieved);
+-      return count;
+-}
+-
+ module_param(force_bulk, bool, 0444);
+ MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,13 +121,12 @@ struct bcm2835_alsa_stream {
+       int draining;
+-      unsigned int pos;
++      atomic_t pos;
++      unsigned int period_offset;
+       unsigned int buffer_size;
+       unsigned int period_size;
+-      atomic_t retrieved;
+       struct bcm2835_audio_instance *instance;
+-      struct workqueue_struct *my_wq;
+       int idx;
+ };
+@@ -152,11 +151,13 @@ int bcm2835_audio_set_params(struct bcm2
+                            unsigned int bps);
+ int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
++int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
+                       unsigned int count,
+                       void *src);
+-void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
++void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
++                         unsigned int size);
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
+ #endif /* __SOUND_ARM_BCM2835_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0392-staging-bcm2835-audio-Code-refactoring-of-vchiq-acce.patch b/target/linux/brcm2708/patches-4.19/950-0392-staging-bcm2835-audio-Code-refactoring-of-vchiq-acce.patch
deleted file mode 100644 (file)
index 37ebd8b..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-From 43f89ac74f3f221e3036a1ec311b24016860d15e Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:48 +0200
-Subject: [PATCH] staging: bcm2835-audio: Code refactoring of vchiq
- accessor codes
-
-commit 769a8e9bf5cf39813f52962fdafdf7e4d52ad585 upstream.
-
-This is a cleanup and code refactoring in bcm2835-vchiq.c.
-
-The major code changes are to provide local helpers for easier use of
-lock / unlock, and message passing with/without response wait.  This
-allows us to reduce lots of open codes.
-
-Also, the max packet is set at opening the stream, not at each time
-when the write gets called.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c             | 440 ++++++------------
- 1 file changed, 142 insertions(+), 298 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -49,6 +49,7 @@ struct bcm2835_audio_instance {
-       struct mutex vchi_mutex;
-       struct bcm2835_alsa_stream *alsa_stream;
-       int result;
-+      unsigned int max_packet;
-       short peer_version;
- };
-@@ -65,16 +66,68 @@ static int bcm2835_audio_start_worker(st
- static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
-                                     unsigned int count, void *src);
--// Routine to send a message across a service
-+static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
-+{
-+      mutex_lock(&instance->vchi_mutex);
-+      vchi_service_use(instance->vchi_handle);
-+}
-+
-+static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
-+{
-+      vchi_service_release(instance->vchi_handle);
-+      mutex_unlock(&instance->vchi_mutex);
-+}
-+
-+static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance,
-+                                       struct vc_audio_msg *m, bool wait)
-+{
-+      int status;
-+
-+      if (wait) {
-+              instance->result = -1;
-+              init_completion(&instance->msg_avail_comp);
-+      }
-+
-+      status = vchi_queue_kernel_message(instance->vchi_handle,
-+                                         m, sizeof(*m));
-+      if (status) {
-+              LOG_ERR("vchi message queue failed: %d, msg=%d\n",
-+                      status, m->type);
-+              return -EIO;
-+      }
-+
-+      if (wait) {
-+              if (!wait_for_completion_timeout(&instance->msg_avail_comp,
-+                                               msecs_to_jiffies(10 * 1000))) {
-+                      LOG_ERR("vchi message timeout, msg=%d\n", m->type);
-+                      return -ETIMEDOUT;
-+              } else if (instance->result) {
-+                      LOG_ERR("vchi message response error:%d, msg=%d\n",
-+                              instance->result, m->type);
-+                      return -EIO;
-+              }
-+      }
-+
-+      return 0;
-+}
--static int
--bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
--                     void *data,
--                     unsigned int size)
--{
--      return vchi_queue_kernel_message(handle,
--                                       data,
--                                       size);
-+static int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance,
-+                                struct vc_audio_msg *m, bool wait)
-+{
-+      int err;
-+
-+      bcm2835_audio_lock(instance);
-+      err = bcm2835_audio_send_msg_locked(instance, m, wait);
-+      bcm2835_audio_unlock(instance);
-+      return err;
-+}
-+
-+static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
-+                                   int type, bool wait)
-+{
-+      struct vc_audio_msg m = { .type = type };
-+
-+      return bcm2835_audio_send_msg(instance, &m, wait);
- }
- static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
-@@ -283,10 +336,9 @@ static int vc_vchi_audio_deinit(struct b
-       int status;
-       mutex_lock(&instance->vchi_mutex);
--
--      /* Close all VCHI service connections */
-       vchi_service_use(instance->vchi_handle);
-+      /* Close all VCHI service connections */
-       status = vchi_service_close(instance->vchi_handle);
-       if (status) {
-               LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
-@@ -345,12 +397,8 @@ static int bcm2835_audio_open_connection
-       instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
-                                     vhci_ctx->vchi_connection);
--      if (IS_ERR(instance)) {
--              LOG_ERR("%s: failed to initialize audio service\n", __func__);
--
--              /* vchi_instance is retained for use the next time. */
-+      if (IS_ERR(instance))
-               return PTR_ERR(instance);
--      }
-       instance->alsa_stream = alsa_stream;
-       alsa_stream->instance = instance;
-@@ -361,66 +409,44 @@ static int bcm2835_audio_open_connection
- int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
- {
-       struct bcm2835_audio_instance *instance;
--      struct vc_audio_msg m;
--      int status;
--      int ret;
-+      int err;
-       alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
-       if (!alsa_stream->my_wq)
-               return -ENOMEM;
--      ret = bcm2835_audio_open_connection(alsa_stream);
--      if (ret)
-+      err = bcm2835_audio_open_connection(alsa_stream);
-+      if (err < 0)
-               goto free_wq;
-       instance = alsa_stream->instance;
--      LOG_DBG(" instance (%p)\n", instance);
--
--      mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle);
--
--      m.type = VC_AUDIO_MSG_TYPE_OPEN;
--
--      /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                      &m, sizeof(m));
--
--      if (status) {
--              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
--                      __func__, status);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      ret = 0;
--unlock:
--      vchi_service_release(instance->vchi_handle);
--      mutex_unlock(&instance->vchi_mutex);
-+      err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
-+                                      false);
-+      if (err < 0)
-+              goto deinit;
-+
-+      bcm2835_audio_lock(instance);
-+      vchi_get_peer_version(instance->vchi_handle, &instance->peer_version);
-+      bcm2835_audio_unlock(instance);
-+      if (instance->peer_version < 2 || force_bulk)
-+              instance->max_packet = 0; /* bulk transfer */
-+      else
-+              instance->max_packet = 4000;
--free_wq:
--      if (ret)
--              destroy_workqueue(alsa_stream->my_wq);
-+      return 0;
--      return ret;
-+ deinit:
-+      vc_vchi_audio_deinit(instance);
-+ free_wq:
-+      destroy_workqueue(alsa_stream->my_wq);
-+      return err;
- }
- int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
- {
--      struct vc_audio_msg m;
--      struct bcm2835_audio_instance *instance = alsa_stream->instance;
-       struct bcm2835_chip *chip = alsa_stream->chip;
--      int status;
--      int ret;
--
--      LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
--               chip->dest, chip->volume);
--
--      mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle);
--
--      instance->result = -1;
-+      struct vc_audio_msg m = {};
-       m.type = VC_AUDIO_MSG_TYPE_CONTROL;
-       m.u.control.dest = chip->dest;
-@@ -429,289 +455,107 @@ int bcm2835_audio_set_ctls(struct bcm283
-       else
-               m.u.control.volume = alsa2chip(chip->volume);
--      /* Create the message available completion */
--      init_completion(&instance->msg_avail_comp);
--
--      /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                      &m, sizeof(m));
--
--      if (status) {
--              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
--                      __func__, status);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      /* We are expecting a reply from the videocore */
--      wait_for_completion(&instance->msg_avail_comp);
--
--      if (instance->result) {
--              LOG_ERR("%s: result=%d\n", __func__, instance->result);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      ret = 0;
--
--unlock:
--      vchi_service_release(instance->vchi_handle);
--      mutex_unlock(&instance->vchi_mutex);
--
--      return ret;
-+      return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
- int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
-                            unsigned int channels, unsigned int samplerate,
-                            unsigned int bps)
- {
--      struct vc_audio_msg m;
--      struct bcm2835_audio_instance *instance = alsa_stream->instance;
--      int status;
--      int ret;
--
--      LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
--               channels, samplerate, bps);
-+      struct vc_audio_msg m = {
-+               .type = VC_AUDIO_MSG_TYPE_CONFIG,
-+               .u.config.channels = channels,
-+               .u.config.samplerate = samplerate,
-+               .u.config.bps = bps,
-+      };
-+      int err;
-       /* resend ctls - alsa_stream may not have been open when first send */
--      ret = bcm2835_audio_set_ctls(alsa_stream);
--      if (ret) {
--              LOG_ERR(" Alsa controls not supported\n");
--              return -EINVAL;
--      }
-+      err = bcm2835_audio_set_ctls(alsa_stream);
-+      if (err)
-+              return err;
--      mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle);
--
--      instance->result = -1;
--
--      m.type = VC_AUDIO_MSG_TYPE_CONFIG;
--      m.u.config.channels = channels;
--      m.u.config.samplerate = samplerate;
--      m.u.config.bps = bps;
--
--      /* Create the message available completion */
--      init_completion(&instance->msg_avail_comp);
--
--      /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                      &m, sizeof(m));
--
--      if (status) {
--              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
--                      __func__, status);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      /* We are expecting a reply from the videocore */
--      wait_for_completion(&instance->msg_avail_comp);
--
--      if (instance->result) {
--              LOG_ERR("%s: result=%d", __func__, instance->result);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      ret = 0;
--
--unlock:
--      vchi_service_release(instance->vchi_handle);
--      mutex_unlock(&instance->vchi_mutex);
--
--      return ret;
-+      return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
- static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
- {
--      struct vc_audio_msg m;
--      struct bcm2835_audio_instance *instance = alsa_stream->instance;
--      int status;
--      int ret;
--
--      mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle);
--
--      m.type = VC_AUDIO_MSG_TYPE_START;
--
--      /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                      &m, sizeof(m));
--
--      if (status) {
--              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
--                      __func__, status);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      ret = 0;
--
--unlock:
--      vchi_service_release(instance->vchi_handle);
--      mutex_unlock(&instance->vchi_mutex);
--      return ret;
-+      return bcm2835_audio_send_simple(alsa_stream->instance,
-+                                       VC_AUDIO_MSG_TYPE_START, false);
- }
- static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
- {
--      struct vc_audio_msg m;
--      struct bcm2835_audio_instance *instance = alsa_stream->instance;
--      int status;
--      int ret;
--
--      mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle);
--
--      m.type = VC_AUDIO_MSG_TYPE_STOP;
--      m.u.stop.draining = alsa_stream->draining;
--
--      /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                      &m, sizeof(m));
--
--      if (status) {
--              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
--                      __func__, status);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      ret = 0;
--
--unlock:
--      vchi_service_release(instance->vchi_handle);
--      mutex_unlock(&instance->vchi_mutex);
--      return ret;
-+      return bcm2835_audio_send_simple(alsa_stream->instance,
-+                                       VC_AUDIO_MSG_TYPE_STOP, false);
- }
- int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
- {
--      struct vc_audio_msg m;
-       struct bcm2835_audio_instance *instance = alsa_stream->instance;
--      int status;
--      int ret;
-+      int err;
-       my_workqueue_quit(alsa_stream);
--      mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle);
--
--      m.type = VC_AUDIO_MSG_TYPE_CLOSE;
--
--      /* Create the message available completion */
--      init_completion(&instance->msg_avail_comp);
--
--      /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                      &m, sizeof(m));
--
--      if (status) {
--              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
--                      __func__, status);
--              ret = -1;
--              goto unlock;
--      }
--
--      /* We are expecting a reply from the videocore */
--      wait_for_completion(&instance->msg_avail_comp);
--
--      if (instance->result) {
--              LOG_ERR("%s: failed result (result=%d)\n",
--                      __func__, instance->result);
--
--              ret = -1;
--              goto unlock;
--      }
--
--      ret = 0;
--
--unlock:
--      vchi_service_release(instance->vchi_handle);
--      mutex_unlock(&instance->vchi_mutex);
-+      err = bcm2835_audio_send_simple(alsa_stream->instance,
-+                                      VC_AUDIO_MSG_TYPE_CLOSE, true);
-       /* Stop the audio service */
-       vc_vchi_audio_deinit(instance);
-       alsa_stream->instance = NULL;
--      return ret;
-+      return err;
- }
- static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
--                                    unsigned int count, void *src)
-+                                    unsigned int size, void *src)
- {
--      struct vc_audio_msg m;
-       struct bcm2835_audio_instance *instance = alsa_stream->instance;
--      int status;
--      int ret;
--
--      LOG_INFO(" Writing %d bytes from %p\n", count, src);
--
--      mutex_lock(&instance->vchi_mutex);
--      vchi_service_use(instance->vchi_handle);
-+      struct vc_audio_msg m = {
-+              .type = VC_AUDIO_MSG_TYPE_WRITE,
-+              .u.write.count = size,
-+              .u.write.max_packet = instance->max_packet,
-+              .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
-+              .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
-+      };
-+      unsigned int count;
-+      int err, status;
--      if (instance->peer_version == 0 &&
--          vchi_get_peer_version(instance->vchi_handle, &instance->peer_version) == 0)
--              LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
--
--      m.type = VC_AUDIO_MSG_TYPE_WRITE;
--      m.u.write.count = count;
--      // old version uses bulk, new version uses control
--      m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0 : 4000;
--      m.u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1;
--      m.u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2;
--      m.u.write.silence = src == NULL;
--
--      /* Send the message to the videocore */
--      status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                      &m, sizeof(m));
-+      if (!size)
-+              return 0;
--      if (status) {
--              LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
--                      __func__, status);
--
--              ret = -1;
-+      bcm2835_audio_lock(instance);
-+      err = bcm2835_audio_send_msg_locked(instance, &m, false);
-+      if (err < 0)
-               goto unlock;
--      }
--      if (!m.u.write.silence) {
--              if (!m.u.write.max_packet) {
--                      /* Send the message to the videocore */
--                      status = vchi_bulk_queue_transmit(instance->vchi_handle,
--                                                        src, count,
--                                                        0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
--                                                        +
--                                                        1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
--                                                        NULL);
--              } else {
--                      while (count > 0) {
--                              int bytes = min_t(int, m.u.write.max_packet, count);
--                              status = bcm2835_vchi_msg_queue(instance->vchi_handle,
--                                                              src, bytes);
--                              src = (char *)src + bytes;
--                              count -= bytes;
--                      }
--              }
--              if (status) {
--                      LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
--                              __func__, status);
-+      count = size;
-+      if (!instance->max_packet) {
-+              /* Send the message to the videocore */
-+              status = vchi_bulk_queue_transmit(instance->vchi_handle,
-+                                                src, count,
-+                                                VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
-+                                                NULL);
-+      } else {
-+              while (count > 0) {
-+                      int bytes = min(instance->max_packet, count);
--                      ret = -1;
--                      goto unlock;
-+                      status = vchi_queue_kernel_message(instance->vchi_handle,
-+                                                         src, bytes);
-+                      src += bytes;
-+                      count -= bytes;
-               }
-       }
--      ret = 0;
--unlock:
--      vchi_service_release(instance->vchi_handle);
--      mutex_unlock(&instance->vchi_mutex);
--      return ret;
-+      if (status) {
-+              LOG_ERR("failed on %d bytes transfer (status=%d)\n",
-+                      size, status);
-+              err = -EIO;
-+      }
-+
-+ unlock:
-+      bcm2835_audio_unlock(instance);
-+      return err;
- }
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
diff --git a/target/linux/brcm2708/patches-4.19/950-0392-staging-bcm2835-audio-Use-card-private_data.patch b/target/linux/brcm2708/patches-4.19/950-0392-staging-bcm2835-audio-Use-card-private_data.patch
new file mode 100644 (file)
index 0000000..d4d61ce
--- /dev/null
@@ -0,0 +1,138 @@
+From af0ded6e9dd38f08a9ee621066e583b5cf972926 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:50 +0200
+Subject: [PATCH] staging: bcm2835-audio: Use card->private_data
+
+commit 898001a0c845cefe5d47d133485712412853f0a8 upstream.
+
+Instead of allocating a separate snd_device object, let snd_card_new()
+allocate the private resource.  This simplifies the code.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c     | 91 +++----------------
+ 1 file changed, 13 insertions(+), 78 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -86,9 +86,6 @@ static int bcm2835_devm_add_vchi_ctx(str
+ static void snd_bcm2835_release(struct device *dev)
+ {
+-      struct bcm2835_chip *chip = dev_get_drvdata(dev);
+-
+-      kfree(chip);
+ }
+ static struct device *
+@@ -117,69 +114,6 @@ snd_create_device(struct device *parent,
+       return device;
+ }
+-/* component-destructor
+- * (see "Management of Cards and Components")
+- */
+-static int snd_bcm2835_dev_free(struct snd_device *device)
+-{
+-      struct bcm2835_chip *chip = device->device_data;
+-      struct snd_card *card = chip->card;
+-
+-      snd_device_free(card, chip);
+-
+-      return 0;
+-}
+-
+-/* chip-specific constructor
+- * (see "Management of Cards and Components")
+- */
+-static int snd_bcm2835_create(struct snd_card *card,
+-                            struct bcm2835_chip **rchip)
+-{
+-      struct bcm2835_chip *chip;
+-      int err;
+-      static struct snd_device_ops ops = {
+-              .dev_free = snd_bcm2835_dev_free,
+-      };
+-
+-      *rchip = NULL;
+-
+-      chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+-      if (!chip)
+-              return -ENOMEM;
+-
+-      chip->card = card;
+-      mutex_init(&chip->audio_mutex);
+-
+-      chip->vchi_ctx = devres_find(card->dev->parent,
+-                                   bcm2835_devm_free_vchi_ctx, NULL, NULL);
+-      if (!chip->vchi_ctx) {
+-              kfree(chip);
+-              return -ENODEV;
+-      }
+-
+-      err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+-      if (err) {
+-              kfree(chip);
+-              return err;
+-      }
+-
+-      *rchip = chip;
+-      return 0;
+-}
+-
+-static struct snd_card *snd_bcm2835_card_new(struct device *dev)
+-{
+-      struct snd_card *card;
+-      int ret;
+-
+-      ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
+-      if (ret)
+-              return ERR_PTR(ret);
+-
+-      return card;
+-}
+-
+ typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
+                                        const char *name,
+                                        enum snd_bcm2835_route route,
+@@ -292,25 +226,26 @@ static int snd_add_child_device(struct d
+               return PTR_ERR(child);
+       }
+-      card = snd_bcm2835_card_new(child);
+-      if (IS_ERR(card)) {
++      err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
++      if (err < 0) {
+               dev_err(child, "Failed to create card");
+-              return PTR_ERR(card);
++              return err;
+       }
+-      snd_card_set_dev(card, child);
++      chip = card->private_data;
++      chip->card = card;
++      chip->dev = child;
++      mutex_init(&chip->audio_mutex);
++
++      chip->vchi_ctx = devres_find(device,
++                                   bcm2835_devm_free_vchi_ctx, NULL, NULL);
++      if (!chip->vchi_ctx)
++              return -ENODEV;
++
+       strcpy(card->driver, audio_driver->driver.name);
+       strcpy(card->shortname, audio_driver->shortname);
+       strcpy(card->longname, audio_driver->longname);
+-      err = snd_bcm2835_create(card, &chip);
+-      if (err) {
+-              dev_err(child, "Failed to create chip, error %d\n", err);
+-              return err;
+-      }
+-
+-      chip->dev = child;
+-
+       err = audio_driver->newpcm(chip, audio_driver->shortname,
+               audio_driver->route,
+               numchans);
diff --git a/target/linux/brcm2708/patches-4.19/950-0393-staging-bcm2835-audio-Operate-non-atomic-PCM-ops.patch b/target/linux/brcm2708/patches-4.19/950-0393-staging-bcm2835-audio-Operate-non-atomic-PCM-ops.patch
deleted file mode 100644 (file)
index 722804f..0000000
+++ /dev/null
@@ -1,593 +0,0 @@
-From 87ba8310e9f0882e85926ac1ef91333f8906b303 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:49 +0200
-Subject: [PATCH] staging: bcm2835-audio: Operate non-atomic PCM ops
-
-commit 5c7883e5f27e829f3f3a2ba174d4a724bfd5f026 upstream.
-
-This is the most significant part in the patch series.
-
-The bcm2835-audio driver used to queue the commands to vc04 core via
-workqueue, but basically the whole accesses to vc04 core are done in
-the sleepable context, including the callback calls.  In such a case,
-rewriting the code using non-atomic PCM ops will simplify the logic a
-lot.
-
-This patch does it: all workqueue are gone and each former-work
-implementation is now directly called from PCM ops like trigger and
-write transfer.
-
-Along with it, the DMA position updater, bcm2835_playback_fifo(), was
-also rewritten to use a simpler logic.  Now it handles the XRUN and
-draining properly by calling snd_pcm_stop() conditionally.
-
-The current position is kept in atomic_t value so that it can be read
-concurrently from the pointer callback.
-
-Also, the bcm2835_audio_instance object is allocated at the beginning
-of bcm2835_audio_open().  This makes the resource management clearer.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  74 +++---
- .../bcm2835-audio/bcm2835-vchiq.c             | 244 +++---------------
- .../vc04_services/bcm2835-audio/bcm2835.h     |   9 +-
- 3 files changed, 82 insertions(+), 245 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -11,7 +11,8 @@
- /* hardware definition */
- static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
--      SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
-+               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-+               SNDRV_PCM_INFO_DRAIN_TRIGGER),
-       .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
-       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-       .rate_min = 8000,
-@@ -27,7 +28,8 @@ static const struct snd_pcm_hardware snd
- static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
--      SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
-+               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-+               SNDRV_PCM_INFO_DRAIN_TRIGGER),
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
-       SNDRV_PCM_RATE_48000,
-@@ -47,42 +49,34 @@ static void snd_bcm2835_playback_free(st
-       kfree(runtime->private_data);
- }
--void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
-+void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
-+                         unsigned int bytes)
- {
--      unsigned int consumed = 0;
--      int new_period = 0;
-+      struct snd_pcm_substream *substream = alsa_stream->substream;
-+      unsigned int pos;
--      audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
--              alsa_stream ? alsa_stream->substream : 0);
-+      if (!alsa_stream->period_size)
-+              return;
--      consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
--
--      /* We get called only if playback was triggered, So, the number of buffers we retrieve in
--       * each iteration are the buffers that have been played out already
--       */
--
--      if (alsa_stream->period_size) {
--              if ((alsa_stream->pos / alsa_stream->period_size) !=
--                      ((alsa_stream->pos + consumed) / alsa_stream->period_size))
--                      new_period = 1;
--      }
--      audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n",
--              alsa_stream->pos,
--              consumed,
--              alsa_stream->buffer_size,
--              (int) (alsa_stream->period_size * alsa_stream->substream->runtime->periods),
--              frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr),
--              new_period);
--      if (alsa_stream->buffer_size) {
--              alsa_stream->pos += consumed & ~(1 << 30);
--              alsa_stream->pos %= alsa_stream->buffer_size;
-+      if (bytes >= alsa_stream->buffer_size) {
-+              snd_pcm_stream_lock(substream);
-+              snd_pcm_stop(substream,
-+                           alsa_stream->draining ?
-+                           SNDRV_PCM_STATE_SETUP :
-+                           SNDRV_PCM_STATE_XRUN);
-+              snd_pcm_stream_unlock(substream);
-+              return;
-       }
--      if (alsa_stream->substream) {
--              if (new_period)
--                      snd_pcm_period_elapsed(alsa_stream->substream);
--      } else {
--              audio_warning(" unexpected NULL substream\n");
-+      pos = atomic_read(&alsa_stream->pos);
-+      pos += bytes;
-+      pos %= alsa_stream->buffer_size;
-+      atomic_set(&alsa_stream->pos, pos);
-+
-+      alsa_stream->period_offset += bytes;
-+      if (alsa_stream->period_offset >= alsa_stream->period_size) {
-+              alsa_stream->period_offset %= alsa_stream->period_size;
-+              snd_pcm_period_elapsed(substream);
-       }
- }
-@@ -246,7 +240,8 @@ static int snd_bcm2835_pcm_prepare(struc
-       alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
-       alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
--      alsa_stream->pos = 0;
-+      atomic_set(&alsa_stream->pos, 0);
-+      alsa_stream->period_offset = 0;
-       alsa_stream->draining = false;
-       return 0;
-@@ -283,7 +278,7 @@ static int snd_bcm2835_pcm_trigger(struc
-               return bcm2835_audio_start(alsa_stream);
-       case SNDRV_PCM_TRIGGER_DRAIN:
-               alsa_stream->draining = true;
--              return 0;
-+              return bcm2835_audio_drain(alsa_stream);
-       case SNDRV_PCM_TRIGGER_STOP:
-               return bcm2835_audio_stop(alsa_stream);
-       default:
-@@ -300,7 +295,7 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
-       return snd_pcm_indirect_playback_pointer(substream,
-               &alsa_stream->pcm_indirect,
--              alsa_stream->pos);
-+              atomic_read(&alsa_stream->pos));
- }
- /* operators */
-@@ -338,6 +333,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
-       if (err < 0)
-               return err;
-       pcm->private_data = chip;
-+      pcm->nonatomic = true;
-       strcpy(pcm->name, "bcm2835 ALSA");
-       chip->pcm = pcm;
-       chip->dest = AUDIO_DEST_AUTO;
-@@ -367,6 +363,7 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
-               return err;
-       pcm->private_data = chip;
-+      pcm->nonatomic = true;
-       strcpy(pcm->name, "bcm2835 IEC958/HDMI");
-       chip->pcm_spdif = pcm;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-@@ -395,6 +392,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
-               return err;
-       pcm->private_data = chip;
-+      pcm->nonatomic = true;
-       strcpy(pcm->name, name);
-       chip->pcm = pcm;
-       chip->dest = route;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -26,10 +26,6 @@
- /* ---- Private Constants and Types ------------------------------------------ */
--#define BCM2835_AUDIO_STOP           0
--#define BCM2835_AUDIO_START          1
--#define BCM2835_AUDIO_WRITE          2
--
- /* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
- #ifdef AUDIO_DEBUG_ENABLE
- #define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
-@@ -55,17 +51,6 @@ struct bcm2835_audio_instance {
- static bool force_bulk;
--/* ---- Private Variables ---------------------------------------------------- */
--
--/* ---- Private Function Prototypes ------------------------------------------ */
--
--/* ---- Private Functions ---------------------------------------------------- */
--
--static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream);
--static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream);
--static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
--                                    unsigned int count, void *src);
--
- static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
- {
-       mutex_lock(&instance->vchi_mutex);
-@@ -135,108 +120,6 @@ static const u32 BCM2835_AUDIO_WRITE_COO
- static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
-                                               'T' << 8  | 'A');
--struct bcm2835_audio_work {
--      struct work_struct my_work;
--      struct bcm2835_alsa_stream *alsa_stream;
--      int cmd;
--      void *src;
--      unsigned int count;
--};
--
--static void my_wq_function(struct work_struct *work)
--{
--      struct bcm2835_audio_work *w =
--              container_of(work, struct bcm2835_audio_work, my_work);
--      int ret = -9;
--
--      switch (w->cmd) {
--      case BCM2835_AUDIO_START:
--              ret = bcm2835_audio_start_worker(w->alsa_stream);
--              break;
--      case BCM2835_AUDIO_STOP:
--              ret = bcm2835_audio_stop_worker(w->alsa_stream);
--              break;
--      case BCM2835_AUDIO_WRITE:
--              ret = bcm2835_audio_write_worker(w->alsa_stream, w->count,
--                                               w->src);
--              break;
--      default:
--              LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->cmd);
--              break;
--      }
--      kfree((void *)work);
--}
--
--int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
--{
--      struct bcm2835_audio_work *work;
--
--      work = kmalloc(sizeof(*work), GFP_ATOMIC);
--      /*--- Queue some work (item 1) ---*/
--      if (!work) {
--              LOG_ERR(" .. Error: NULL work kmalloc\n");
--              return -ENOMEM;
--      }
--      INIT_WORK(&work->my_work, my_wq_function);
--      work->alsa_stream = alsa_stream;
--      work->cmd = BCM2835_AUDIO_START;
--      if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
--              kfree(work);
--              return -EBUSY;
--      }
--      return 0;
--}
--
--int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
--{
--      struct bcm2835_audio_work *work;
--
--      work = kmalloc(sizeof(*work), GFP_ATOMIC);
--      /*--- Queue some work (item 1) ---*/
--      if (!work) {
--              LOG_ERR(" .. Error: NULL work kmalloc\n");
--              return -ENOMEM;
--      }
--      INIT_WORK(&work->my_work, my_wq_function);
--      work->alsa_stream = alsa_stream;
--      work->cmd = BCM2835_AUDIO_STOP;
--      if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
--              kfree(work);
--              return -EBUSY;
--      }
--      return 0;
--}
--
--int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
--                      unsigned int count, void *src)
--{
--      struct bcm2835_audio_work *work;
--
--      work = kmalloc(sizeof(*work), GFP_ATOMIC);
--      /*--- Queue some work (item 1) ---*/
--      if (!work) {
--              LOG_ERR(" .. Error: NULL work kmalloc\n");
--              return -ENOMEM;
--      }
--      INIT_WORK(&work->my_work, my_wq_function);
--      work->alsa_stream = alsa_stream;
--      work->cmd = BCM2835_AUDIO_WRITE;
--      work->src = src;
--      work->count = count;
--      if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
--              kfree(work);
--              return -EBUSY;
--      }
--      return 0;
--}
--
--static void my_workqueue_quit(struct bcm2835_alsa_stream *alsa_stream)
--{
--      flush_workqueue(alsa_stream->my_wq);
--      destroy_workqueue(alsa_stream->my_wq);
--      alsa_stream->my_wq = NULL;
--}
--
- static void audio_vchi_callback(void *param,
-                               const VCHI_CALLBACK_REASON_T reason,
-                               void *msg_handle)
-@@ -249,47 +132,27 @@ static void audio_vchi_callback(void *pa
-       if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
-               return;
--      if (!instance) {
--              LOG_ERR(" .. instance is null\n");
--              BUG();
--              return;
--      }
--      if (!instance->vchi_handle) {
--              LOG_ERR(" .. instance->vchi_handle is null\n");
--              BUG();
--              return;
--      }
-       status = vchi_msg_dequeue(instance->vchi_handle,
-                                 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
-       if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
--              LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
--                      instance, m.u.result.success);
-               instance->result = m.u.result.success;
-               complete(&instance->msg_avail_comp);
-       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
--              struct bcm2835_alsa_stream *alsa_stream = instance->alsa_stream;
--
--              LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
--                      instance, m.u.complete.count);
-               if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
-                   m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
--                      LOG_ERR(" .. response is corrupt\n");
--              else if (alsa_stream) {
--                      atomic_add(m.u.complete.count,
--                                 &alsa_stream->retrieved);
--                      bcm2835_playback_fifo(alsa_stream);
--              } else {
--                      LOG_ERR(" .. unexpected alsa_stream=%p\n",
--                              alsa_stream);
--              }
-+                      LOG_ERR("invalid cookie\n");
-+              else
-+                      bcm2835_playback_fifo(instance->alsa_stream,
-+                                            m.u.complete.count);
-       } else {
--              LOG_ERR(" .. unexpected m.type=%d\n", m.type);
-+              LOG_ERR("unexpected callback type=%d\n", m.type);
-       }
- }
--static struct bcm2835_audio_instance *
-+static int
- vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
--                 VCHI_CONNECTION_T *vchi_connection)
-+                 VCHI_CONNECTION_T *vchi_connection,
-+                 struct bcm2835_audio_instance *instance)
- {
-       SERVICE_CREATION_T params = {
-               .version                = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
-@@ -298,23 +161,14 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
-               .rx_fifo_size           = 0,
-               .tx_fifo_size           = 0,
-               .callback               = audio_vchi_callback,
-+              .callback_param         = instance,
-               .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
-               .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
-               .want_crc               = 0
-       };
--      struct bcm2835_audio_instance *instance;
-       int status;
--      /* Allocate memory for this instance */
--      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
--      if (!instance)
--              return ERR_PTR(-ENOMEM);
--
--      /* Create a lock for exclusive, serialized VCHI connection access */
--      mutex_init(&instance->vchi_mutex);
-       /* Open the VCHI service connections */
--      params.callback_param = instance,
--
-       status = vchi_service_open(vchi_instance, &params,
-                                  &instance->vchi_handle);
-@@ -322,16 +176,16 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
-               LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
-                       __func__, status);
-               kfree(instance);
--              return ERR_PTR(-EPERM);
-+              return -EPERM;
-       }
-       /* Finished with the service for now */
-       vchi_service_release(instance->vchi_handle);
--      return instance;
-+      return 0;
- }
--static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
-+static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
- {
-       int status;
-@@ -346,10 +200,6 @@ static int vc_vchi_audio_deinit(struct b
-       }
-       mutex_unlock(&instance->vchi_mutex);
--
--      kfree(instance);
--
--      return 0;
- }
- int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
-@@ -387,39 +237,25 @@ void bcm2835_free_vchi_ctx(struct bcm283
-       vchi_ctx->vchi_instance = NULL;
- }
--static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream)
--{
--      struct bcm2835_audio_instance *instance =
--              (struct bcm2835_audio_instance *)alsa_stream->instance;
--      struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
--
--      /* Initialize an instance of the audio service */
--      instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
--                                    vhci_ctx->vchi_connection);
--
--      if (IS_ERR(instance))
--              return PTR_ERR(instance);
--
--      instance->alsa_stream = alsa_stream;
--      alsa_stream->instance = instance;
--
--      return 0;
--}
--
- int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
- {
-+      struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx;
-       struct bcm2835_audio_instance *instance;
-       int err;
--      alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
--      if (!alsa_stream->my_wq)
-+      /* Allocate memory for this instance */
-+      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-+      if (!instance)
-               return -ENOMEM;
-+      mutex_init(&instance->vchi_mutex);
-+      instance->alsa_stream = alsa_stream;
-+      alsa_stream->instance = instance;
--      err = bcm2835_audio_open_connection(alsa_stream);
-+      err = vc_vchi_audio_init(vchi_ctx->vchi_instance,
-+                               vchi_ctx->vchi_connection,
-+                               instance);
-       if (err < 0)
--              goto free_wq;
--
--      instance = alsa_stream->instance;
-+              goto free_instance;
-       err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
-                                       false);
-@@ -438,8 +274,9 @@ int bcm2835_audio_open(struct bcm2835_al
-  deinit:
-       vc_vchi_audio_deinit(instance);
-- free_wq:
--      destroy_workqueue(alsa_stream->my_wq);
-+ free_instance:
-+      alsa_stream->instance = NULL;
-+      kfree(instance);
-       return err;
- }
-@@ -478,37 +315,46 @@ int bcm2835_audio_set_params(struct bcm2
-       return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
--static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
-+int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
- {
-       return bcm2835_audio_send_simple(alsa_stream->instance,
-                                        VC_AUDIO_MSG_TYPE_START, false);
- }
--static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
-+int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
- {
-       return bcm2835_audio_send_simple(alsa_stream->instance,
-                                        VC_AUDIO_MSG_TYPE_STOP, false);
- }
-+int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
-+{
-+      struct vc_audio_msg m = {
-+              .type = VC_AUDIO_MSG_TYPE_STOP,
-+              .u.stop.draining = 1,
-+      };
-+
-+      return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
-+}
-+
- int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
- {
-       struct bcm2835_audio_instance *instance = alsa_stream->instance;
-       int err;
--      my_workqueue_quit(alsa_stream);
--
-       err = bcm2835_audio_send_simple(alsa_stream->instance,
-                                       VC_AUDIO_MSG_TYPE_CLOSE, true);
-       /* Stop the audio service */
-       vc_vchi_audio_deinit(instance);
-       alsa_stream->instance = NULL;
-+      kfree(instance);
-       return err;
- }
--static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
--                                    unsigned int size, void *src)
-+int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
-+                      unsigned int size, void *src)
- {
-       struct bcm2835_audio_instance *instance = alsa_stream->instance;
-       struct vc_audio_msg m = {
-@@ -558,13 +404,5 @@ static int bcm2835_audio_write_worker(st
-       return err;
- }
--unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
--{
--      unsigned int count = atomic_read(&alsa_stream->retrieved);
--
--      atomic_sub(count, &alsa_stream->retrieved);
--      return count;
--}
--
- module_param(force_bulk, bool, 0444);
- MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,13 +121,12 @@ struct bcm2835_alsa_stream {
-       int draining;
--      unsigned int pos;
-+      atomic_t pos;
-+      unsigned int period_offset;
-       unsigned int buffer_size;
-       unsigned int period_size;
--      atomic_t retrieved;
-       struct bcm2835_audio_instance *instance;
--      struct workqueue_struct *my_wq;
-       int idx;
- };
-@@ -152,11 +151,13 @@ int bcm2835_audio_set_params(struct bcm2
-                            unsigned int bps);
- int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
-+int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
-                       unsigned int count,
-                       void *src);
--void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
-+void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
-+                         unsigned int size);
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
- #endif /* __SOUND_ARM_BCM2835_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0393-staging-bcm2835-audio-Use-standard-error-print-helpe.patch b/target/linux/brcm2708/patches-4.19/950-0393-staging-bcm2835-audio-Use-standard-error-print-helpe.patch
new file mode 100644 (file)
index 0000000..63cd0b0
--- /dev/null
@@ -0,0 +1,237 @@
+From ec788d7c115d3ec59b39b6aac17d57ad86b7fbfe Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:51 +0200
+Subject: [PATCH] staging: bcm2835-audio: Use standard error print
+ helpers
+
+commit b7584b64168208ebc14160770c0966b8b12fc16b upstream.
+
+For making the whole code more consistent, replace the home-made debug
+print macros with the standard dev_err() & co.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  4 +-
+ .../bcm2835-audio/bcm2835-vchiq.c             | 52 ++++++++-----------
+ .../vc04_services/bcm2835-audio/bcm2835.c     |  2 +-
+ .../vc04_services/bcm2835-audio/bcm2835.h     | 43 +--------------
+ 4 files changed, 27 insertions(+), 74 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -101,8 +101,8 @@ static int snd_bcm2835_playback_open_gen
+               goto out;
+       }
+       if (idx >= MAX_SUBSTREAMS) {
+-              audio_error
+-                      ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
++              dev_err(chip->dev,
++                      "substream(%d) device doesn't exist max(%d) substreams allowed\n",
+                       idx, MAX_SUBSTREAMS);
+               err = -ENODEV;
+               goto out;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -26,20 +26,8 @@
+ /* ---- Private Constants and Types ------------------------------------------ */
+-/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
+-#ifdef AUDIO_DEBUG_ENABLE
+-#define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
+-#define LOG_WARN(fmt, arg...)  pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
+-#define LOG_INFO(fmt, arg...)  pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
+-#define LOG_DBG(fmt, arg...)   pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
+-#else
+-#define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
+-#define LOG_WARN(fmt, arg...)  no_printk(fmt, ##arg)
+-#define LOG_INFO(fmt, arg...)  no_printk(fmt, ##arg)
+-#define LOG_DBG(fmt, arg...)   no_printk(fmt, ##arg)
+-#endif
+-
+ struct bcm2835_audio_instance {
++      struct device *dev;
+       VCHI_SERVICE_HANDLE_T vchi_handle;
+       struct completion msg_avail_comp;
+       struct mutex vchi_mutex;
+@@ -76,7 +64,8 @@ static int bcm2835_audio_send_msg_locked
+       status = vchi_queue_kernel_message(instance->vchi_handle,
+                                          m, sizeof(*m));
+       if (status) {
+-              LOG_ERR("vchi message queue failed: %d, msg=%d\n",
++              dev_err(instance->dev,
++                      "vchi message queue failed: %d, msg=%d\n",
+                       status, m->type);
+               return -EIO;
+       }
+@@ -84,10 +73,12 @@ static int bcm2835_audio_send_msg_locked
+       if (wait) {
+               if (!wait_for_completion_timeout(&instance->msg_avail_comp,
+                                                msecs_to_jiffies(10 * 1000))) {
+-                      LOG_ERR("vchi message timeout, msg=%d\n", m->type);
++                      dev_err(instance->dev,
++                              "vchi message timeout, msg=%d\n", m->type);
+                       return -ETIMEDOUT;
+               } else if (instance->result) {
+-                      LOG_ERR("vchi message response error:%d, msg=%d\n",
++                      dev_err(instance->dev,
++                              "vchi message response error:%d, msg=%d\n",
+                               instance->result, m->type);
+                       return -EIO;
+               }
+@@ -140,12 +131,12 @@ static void audio_vchi_callback(void *pa
+       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
+               if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
+                   m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
+-                      LOG_ERR("invalid cookie\n");
++                      dev_err(instance->dev, "invalid cookie\n");
+               else
+                       bcm2835_playback_fifo(instance->alsa_stream,
+                                             m.u.complete.count);
+       } else {
+-              LOG_ERR("unexpected callback type=%d\n", m.type);
++              dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
+       }
+ }
+@@ -173,8 +164,9 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+                                  &instance->vchi_handle);
+       if (status) {
+-              LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
+-                      __func__, status);
++              dev_err(instance->dev,
++                      "failed to open VCHI service connection (status=%d)\n",
++                      status);
+               kfree(instance);
+               return -EPERM;
+       }
+@@ -195,30 +187,30 @@ static void vc_vchi_audio_deinit(struct
+       /* Close all VCHI service connections */
+       status = vchi_service_close(instance->vchi_handle);
+       if (status) {
+-              LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
+-                      __func__, status);
++              dev_err(instance->dev,
++                      "failed to close VCHI service connection (status=%d)\n",
++                      status);
+       }
+       mutex_unlock(&instance->vchi_mutex);
+ }
+-int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
++int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx)
+ {
+       int ret;
+       /* Initialize and create a VCHI connection */
+       ret = vchi_initialise(&vchi_ctx->vchi_instance);
+       if (ret) {
+-              LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
+-                      __func__, ret);
+-
++              dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
++                      ret);
+               return -EIO;
+       }
+       ret = vchi_connect(NULL, 0, vchi_ctx->vchi_instance);
+       if (ret) {
+-              LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
+-                      __func__, ret);
++              dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n",
++                      ret);
+               kfree(vchi_ctx->vchi_instance);
+               vchi_ctx->vchi_instance = NULL;
+@@ -248,6 +240,7 @@ int bcm2835_audio_open(struct bcm2835_al
+       if (!instance)
+               return -ENOMEM;
+       mutex_init(&instance->vchi_mutex);
++      instance->dev = alsa_stream->chip->dev;
+       instance->alsa_stream = alsa_stream;
+       alsa_stream->instance = instance;
+@@ -394,7 +387,8 @@ int bcm2835_audio_write(struct bcm2835_a
+       }
+       if (status) {
+-              LOG_ERR("failed on %d bytes transfer (status=%d)\n",
++              dev_err(instance->dev,
++                      "failed on %d bytes transfer (status=%d)\n",
+                       size, status);
+               err = -EIO;
+       }
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -73,7 +73,7 @@ static int bcm2835_devm_add_vchi_ctx(str
+       memset(vchi_ctx, 0, sizeof(*vchi_ctx));
+-      ret = bcm2835_new_vchi_ctx(vchi_ctx);
++      ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
+       if (ret) {
+               devres_free(vchi_ctx);
+               return ret;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -17,47 +17,6 @@
+ #include "interface/vchi/vchi.h"
+-/*
+- * #define AUDIO_DEBUG_ENABLE
+- * #define AUDIO_VERBOSE_DEBUG_ENABLE
+- */
+-
+-/* Debug macros */
+-
+-#ifdef AUDIO_DEBUG_ENABLE
+-#ifdef AUDIO_VERBOSE_DEBUG_ENABLE
+-
+-#define audio_debug(fmt, arg...) \
+-      pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+-#define audio_info(fmt, arg...) \
+-      pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+-#else
+-
+-#define audio_debug(fmt, arg...)
+-
+-#define audio_info(fmt, arg...)
+-
+-#endif /* AUDIO_VERBOSE_DEBUG_ENABLE */
+-
+-#else
+-
+-#define audio_debug(fmt, arg...)
+-
+-#define audio_info(fmt, arg...)
+-
+-#endif /* AUDIO_DEBUG_ENABLE */
+-
+-#define audio_error(fmt, arg...) \
+-      pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+-#define audio_warning(fmt, arg...) \
+-      pr_warn("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+-#define audio_alert(fmt, arg...) \
+-      pr_alert("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+ #define MAX_SUBSTREAMS   (8)
+ #define AVAIL_SUBSTREAMS_MASK  (0xff)
+@@ -141,7 +100,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
+ int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
+ int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
+-int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
++int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx);
+ void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
+ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream);
diff --git a/target/linux/brcm2708/patches-4.19/950-0394-staging-bcm2835-audio-Remove-unnecessary-header-file.patch b/target/linux/brcm2708/patches-4.19/950-0394-staging-bcm2835-audio-Remove-unnecessary-header-file.patch
new file mode 100644 (file)
index 0000000..989e0e4
--- /dev/null
@@ -0,0 +1,73 @@
+From 8deead340379eeb09571476e0412ce50036c08d1 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:52 +0200
+Subject: [PATCH] staging: bcm2835-audio: Remove unnecessary header
+ file includes
+
+commit 7e46fff5f19ce2b8a9891e4c08631c64d06e9e17 upstream.
+
+Yet a few header files are included unnecessarily.  Drop them.
+
+Also remove trivial comments.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c             | 19 -------------------
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  6 ------
+ 2 files changed, 25 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -1,31 +1,12 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
+-#include <linux/device.h>
+-#include <sound/core.h>
+-#include <sound/initval.h>
+-#include <sound/pcm.h>
+-#include <linux/io.h>
+-#include <linux/interrupt.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/mm.h>
+-#include <linux/syscalls.h>
+-#include <linux/uaccess.h>
+ #include <linux/slab.h>
+-#include <linux/delay.h>
+-#include <linux/atomic.h>
+ #include <linux/module.h>
+ #include <linux/completion.h>
+-
+ #include "bcm2835.h"
+-
+-/* ---- Include Files -------------------------------------------------------- */
+-
+ #include "vc_vchi_audioserv_defs.h"
+-/* ---- Private Constants and Types ------------------------------------------ */
+-
+ struct bcm2835_audio_instance {
+       struct device *dev;
+       VCHI_SERVICE_HANDLE_T vchi_handle;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -5,16 +5,10 @@
+ #define __SOUND_ARM_BCM2835_H
+ #include <linux/device.h>
+-#include <linux/list.h>
+-#include <linux/interrupt.h>
+ #include <linux/wait.h>
+ #include <sound/core.h>
+-#include <sound/initval.h>
+ #include <sound/pcm.h>
+-#include <sound/pcm_params.h>
+ #include <sound/pcm-indirect.h>
+-#include <linux/workqueue.h>
+-
+ #include "interface/vchi/vchi.h"
+ #define MAX_SUBSTREAMS   (8)
diff --git a/target/linux/brcm2708/patches-4.19/950-0394-staging-bcm2835-audio-Use-card-private_data.patch b/target/linux/brcm2708/patches-4.19/950-0394-staging-bcm2835-audio-Use-card-private_data.patch
deleted file mode 100644 (file)
index d4d61ce..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-From af0ded6e9dd38f08a9ee621066e583b5cf972926 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:50 +0200
-Subject: [PATCH] staging: bcm2835-audio: Use card->private_data
-
-commit 898001a0c845cefe5d47d133485712412853f0a8 upstream.
-
-Instead of allocating a separate snd_device object, let snd_card_new()
-allocate the private resource.  This simplifies the code.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835.c     | 91 +++----------------
- 1 file changed, 13 insertions(+), 78 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -86,9 +86,6 @@ static int bcm2835_devm_add_vchi_ctx(str
- static void snd_bcm2835_release(struct device *dev)
- {
--      struct bcm2835_chip *chip = dev_get_drvdata(dev);
--
--      kfree(chip);
- }
- static struct device *
-@@ -117,69 +114,6 @@ snd_create_device(struct device *parent,
-       return device;
- }
--/* component-destructor
-- * (see "Management of Cards and Components")
-- */
--static int snd_bcm2835_dev_free(struct snd_device *device)
--{
--      struct bcm2835_chip *chip = device->device_data;
--      struct snd_card *card = chip->card;
--
--      snd_device_free(card, chip);
--
--      return 0;
--}
--
--/* chip-specific constructor
-- * (see "Management of Cards and Components")
-- */
--static int snd_bcm2835_create(struct snd_card *card,
--                            struct bcm2835_chip **rchip)
--{
--      struct bcm2835_chip *chip;
--      int err;
--      static struct snd_device_ops ops = {
--              .dev_free = snd_bcm2835_dev_free,
--      };
--
--      *rchip = NULL;
--
--      chip = kzalloc(sizeof(*chip), GFP_KERNEL);
--      if (!chip)
--              return -ENOMEM;
--
--      chip->card = card;
--      mutex_init(&chip->audio_mutex);
--
--      chip->vchi_ctx = devres_find(card->dev->parent,
--                                   bcm2835_devm_free_vchi_ctx, NULL, NULL);
--      if (!chip->vchi_ctx) {
--              kfree(chip);
--              return -ENODEV;
--      }
--
--      err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
--      if (err) {
--              kfree(chip);
--              return err;
--      }
--
--      *rchip = chip;
--      return 0;
--}
--
--static struct snd_card *snd_bcm2835_card_new(struct device *dev)
--{
--      struct snd_card *card;
--      int ret;
--
--      ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
--      if (ret)
--              return ERR_PTR(ret);
--
--      return card;
--}
--
- typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
-                                        const char *name,
-                                        enum snd_bcm2835_route route,
-@@ -292,25 +226,26 @@ static int snd_add_child_device(struct d
-               return PTR_ERR(child);
-       }
--      card = snd_bcm2835_card_new(child);
--      if (IS_ERR(card)) {
-+      err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
-+      if (err < 0) {
-               dev_err(child, "Failed to create card");
--              return PTR_ERR(card);
-+              return err;
-       }
--      snd_card_set_dev(card, child);
-+      chip = card->private_data;
-+      chip->card = card;
-+      chip->dev = child;
-+      mutex_init(&chip->audio_mutex);
-+
-+      chip->vchi_ctx = devres_find(device,
-+                                   bcm2835_devm_free_vchi_ctx, NULL, NULL);
-+      if (!chip->vchi_ctx)
-+              return -ENODEV;
-+
-       strcpy(card->driver, audio_driver->driver.name);
-       strcpy(card->shortname, audio_driver->shortname);
-       strcpy(card->longname, audio_driver->longname);
--      err = snd_bcm2835_create(card, &chip);
--      if (err) {
--              dev_err(child, "Failed to create chip, error %d\n", err);
--              return err;
--      }
--
--      chip->dev = child;
--
-       err = audio_driver->newpcm(chip, audio_driver->shortname,
-               audio_driver->route,
-               numchans);
diff --git a/target/linux/brcm2708/patches-4.19/950-0395-staging-bcm2835-audio-Move-module-parameter-descript.patch b/target/linux/brcm2708/patches-4.19/950-0395-staging-bcm2835-audio-Move-module-parameter-descript.patch
new file mode 100644 (file)
index 0000000..5db4daa
--- /dev/null
@@ -0,0 +1,36 @@
+From fb05aeb91f3e94e89ad2d9aa68104e6e4cc97239 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:53 +0200
+Subject: [PATCH] staging: bcm2835-audio: Move module parameter
+ description
+
+commit b876f2075808e95e244053caa53fa7e86e929a99 upstream.
+
+For more consistency, move the module parameter description right
+after its variable definition.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -19,6 +19,8 @@ struct bcm2835_audio_instance {
+ };
+ static bool force_bulk;
++module_param(force_bulk, bool, 0444);
++MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
+ static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
+ {
+@@ -378,6 +380,3 @@ int bcm2835_audio_write(struct bcm2835_a
+       bcm2835_audio_unlock(instance);
+       return err;
+ }
+-
+-module_param(force_bulk, bool, 0444);
+-MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
diff --git a/target/linux/brcm2708/patches-4.19/950-0395-staging-bcm2835-audio-Use-standard-error-print-helpe.patch b/target/linux/brcm2708/patches-4.19/950-0395-staging-bcm2835-audio-Use-standard-error-print-helpe.patch
deleted file mode 100644 (file)
index 63cd0b0..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-From ec788d7c115d3ec59b39b6aac17d57ad86b7fbfe Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:51 +0200
-Subject: [PATCH] staging: bcm2835-audio: Use standard error print
- helpers
-
-commit b7584b64168208ebc14160770c0966b8b12fc16b upstream.
-
-For making the whole code more consistent, replace the home-made debug
-print macros with the standard dev_err() & co.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c |  4 +-
- .../bcm2835-audio/bcm2835-vchiq.c             | 52 ++++++++-----------
- .../vc04_services/bcm2835-audio/bcm2835.c     |  2 +-
- .../vc04_services/bcm2835-audio/bcm2835.h     | 43 +--------------
- 4 files changed, 27 insertions(+), 74 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -101,8 +101,8 @@ static int snd_bcm2835_playback_open_gen
-               goto out;
-       }
-       if (idx >= MAX_SUBSTREAMS) {
--              audio_error
--                      ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
-+              dev_err(chip->dev,
-+                      "substream(%d) device doesn't exist max(%d) substreams allowed\n",
-                       idx, MAX_SUBSTREAMS);
-               err = -ENODEV;
-               goto out;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -26,20 +26,8 @@
- /* ---- Private Constants and Types ------------------------------------------ */
--/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
--#ifdef AUDIO_DEBUG_ENABLE
--#define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
--#define LOG_WARN(fmt, arg...)  pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
--#define LOG_INFO(fmt, arg...)  pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
--#define LOG_DBG(fmt, arg...)   pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
--#else
--#define LOG_ERR(fmt, arg...)   pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
--#define LOG_WARN(fmt, arg...)  no_printk(fmt, ##arg)
--#define LOG_INFO(fmt, arg...)  no_printk(fmt, ##arg)
--#define LOG_DBG(fmt, arg...)   no_printk(fmt, ##arg)
--#endif
--
- struct bcm2835_audio_instance {
-+      struct device *dev;
-       VCHI_SERVICE_HANDLE_T vchi_handle;
-       struct completion msg_avail_comp;
-       struct mutex vchi_mutex;
-@@ -76,7 +64,8 @@ static int bcm2835_audio_send_msg_locked
-       status = vchi_queue_kernel_message(instance->vchi_handle,
-                                          m, sizeof(*m));
-       if (status) {
--              LOG_ERR("vchi message queue failed: %d, msg=%d\n",
-+              dev_err(instance->dev,
-+                      "vchi message queue failed: %d, msg=%d\n",
-                       status, m->type);
-               return -EIO;
-       }
-@@ -84,10 +73,12 @@ static int bcm2835_audio_send_msg_locked
-       if (wait) {
-               if (!wait_for_completion_timeout(&instance->msg_avail_comp,
-                                                msecs_to_jiffies(10 * 1000))) {
--                      LOG_ERR("vchi message timeout, msg=%d\n", m->type);
-+                      dev_err(instance->dev,
-+                              "vchi message timeout, msg=%d\n", m->type);
-                       return -ETIMEDOUT;
-               } else if (instance->result) {
--                      LOG_ERR("vchi message response error:%d, msg=%d\n",
-+                      dev_err(instance->dev,
-+                              "vchi message response error:%d, msg=%d\n",
-                               instance->result, m->type);
-                       return -EIO;
-               }
-@@ -140,12 +131,12 @@ static void audio_vchi_callback(void *pa
-       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
-               if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
-                   m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
--                      LOG_ERR("invalid cookie\n");
-+                      dev_err(instance->dev, "invalid cookie\n");
-               else
-                       bcm2835_playback_fifo(instance->alsa_stream,
-                                             m.u.complete.count);
-       } else {
--              LOG_ERR("unexpected callback type=%d\n", m.type);
-+              dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
-       }
- }
-@@ -173,8 +164,9 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
-                                  &instance->vchi_handle);
-       if (status) {
--              LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
--                      __func__, status);
-+              dev_err(instance->dev,
-+                      "failed to open VCHI service connection (status=%d)\n",
-+                      status);
-               kfree(instance);
-               return -EPERM;
-       }
-@@ -195,30 +187,30 @@ static void vc_vchi_audio_deinit(struct
-       /* Close all VCHI service connections */
-       status = vchi_service_close(instance->vchi_handle);
-       if (status) {
--              LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
--                      __func__, status);
-+              dev_err(instance->dev,
-+                      "failed to close VCHI service connection (status=%d)\n",
-+                      status);
-       }
-       mutex_unlock(&instance->vchi_mutex);
- }
--int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
-+int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx)
- {
-       int ret;
-       /* Initialize and create a VCHI connection */
-       ret = vchi_initialise(&vchi_ctx->vchi_instance);
-       if (ret) {
--              LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
--                      __func__, ret);
--
-+              dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
-+                      ret);
-               return -EIO;
-       }
-       ret = vchi_connect(NULL, 0, vchi_ctx->vchi_instance);
-       if (ret) {
--              LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
--                      __func__, ret);
-+              dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n",
-+                      ret);
-               kfree(vchi_ctx->vchi_instance);
-               vchi_ctx->vchi_instance = NULL;
-@@ -248,6 +240,7 @@ int bcm2835_audio_open(struct bcm2835_al
-       if (!instance)
-               return -ENOMEM;
-       mutex_init(&instance->vchi_mutex);
-+      instance->dev = alsa_stream->chip->dev;
-       instance->alsa_stream = alsa_stream;
-       alsa_stream->instance = instance;
-@@ -394,7 +387,8 @@ int bcm2835_audio_write(struct bcm2835_a
-       }
-       if (status) {
--              LOG_ERR("failed on %d bytes transfer (status=%d)\n",
-+              dev_err(instance->dev,
-+                      "failed on %d bytes transfer (status=%d)\n",
-                       size, status);
-               err = -EIO;
-       }
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -73,7 +73,7 @@ static int bcm2835_devm_add_vchi_ctx(str
-       memset(vchi_ctx, 0, sizeof(*vchi_ctx));
--      ret = bcm2835_new_vchi_ctx(vchi_ctx);
-+      ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
-       if (ret) {
-               devres_free(vchi_ctx);
-               return ret;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -17,47 +17,6 @@
- #include "interface/vchi/vchi.h"
--/*
-- * #define AUDIO_DEBUG_ENABLE
-- * #define AUDIO_VERBOSE_DEBUG_ENABLE
-- */
--
--/* Debug macros */
--
--#ifdef AUDIO_DEBUG_ENABLE
--#ifdef AUDIO_VERBOSE_DEBUG_ENABLE
--
--#define audio_debug(fmt, arg...) \
--      pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
--
--#define audio_info(fmt, arg...) \
--      pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
--
--#else
--
--#define audio_debug(fmt, arg...)
--
--#define audio_info(fmt, arg...)
--
--#endif /* AUDIO_VERBOSE_DEBUG_ENABLE */
--
--#else
--
--#define audio_debug(fmt, arg...)
--
--#define audio_info(fmt, arg...)
--
--#endif /* AUDIO_DEBUG_ENABLE */
--
--#define audio_error(fmt, arg...) \
--      pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
--
--#define audio_warning(fmt, arg...) \
--      pr_warn("%s:%d " fmt, __func__, __LINE__, ##arg)
--
--#define audio_alert(fmt, arg...) \
--      pr_alert("%s:%d " fmt, __func__, __LINE__, ##arg)
--
- #define MAX_SUBSTREAMS   (8)
- #define AVAIL_SUBSTREAMS_MASK  (0xff)
-@@ -141,7 +100,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
- int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
- int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
--int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
-+int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx);
- void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
- int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream);
diff --git a/target/linux/brcm2708/patches-4.19/950-0396-staging-bcm2835-audio-Remove-unnecessary-header-file.patch b/target/linux/brcm2708/patches-4.19/950-0396-staging-bcm2835-audio-Remove-unnecessary-header-file.patch
deleted file mode 100644 (file)
index 989e0e4..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From 8deead340379eeb09571476e0412ce50036c08d1 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:52 +0200
-Subject: [PATCH] staging: bcm2835-audio: Remove unnecessary header
- file includes
-
-commit 7e46fff5f19ce2b8a9891e4c08631c64d06e9e17 upstream.
-
-Yet a few header files are included unnecessarily.  Drop them.
-
-Also remove trivial comments.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c             | 19 -------------------
- .../vc04_services/bcm2835-audio/bcm2835.h     |  6 ------
- 2 files changed, 25 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -1,31 +1,12 @@
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
--#include <linux/device.h>
--#include <sound/core.h>
--#include <sound/initval.h>
--#include <sound/pcm.h>
--#include <linux/io.h>
--#include <linux/interrupt.h>
--#include <linux/fs.h>
--#include <linux/file.h>
--#include <linux/mm.h>
--#include <linux/syscalls.h>
--#include <linux/uaccess.h>
- #include <linux/slab.h>
--#include <linux/delay.h>
--#include <linux/atomic.h>
- #include <linux/module.h>
- #include <linux/completion.h>
--
- #include "bcm2835.h"
--
--/* ---- Include Files -------------------------------------------------------- */
--
- #include "vc_vchi_audioserv_defs.h"
--/* ---- Private Constants and Types ------------------------------------------ */
--
- struct bcm2835_audio_instance {
-       struct device *dev;
-       VCHI_SERVICE_HANDLE_T vchi_handle;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -5,16 +5,10 @@
- #define __SOUND_ARM_BCM2835_H
- #include <linux/device.h>
--#include <linux/list.h>
--#include <linux/interrupt.h>
- #include <linux/wait.h>
- #include <sound/core.h>
--#include <sound/initval.h>
- #include <sound/pcm.h>
--#include <sound/pcm_params.h>
- #include <sound/pcm-indirect.h>
--#include <linux/workqueue.h>
--
- #include "interface/vchi/vchi.h"
- #define MAX_SUBSTREAMS   (8)
diff --git a/target/linux/brcm2708/patches-4.19/950-0396-staging-bcm2835-audio-Use-coherent-device-buffers.patch b/target/linux/brcm2708/patches-4.19/950-0396-staging-bcm2835-audio-Use-coherent-device-buffers.patch
new file mode 100644 (file)
index 0000000..dfd4b97
--- /dev/null
@@ -0,0 +1,61 @@
+From 8a01a25d0ad7e9d06f64fddae871deb91c3988ac Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:54 +0200
+Subject: [PATCH] staging: bcm2835-audio: Use coherent device buffers
+
+commit ad29c6e6cbf6f2af7362b043adad51a3be3d39c7 upstream.
+
+The memory access to the pages allocated with
+SNDRV_DMA_TYPE_CONTINUOUS are basically non-coherent, and it becomes a
+problem when a process accesses via mmap.
+
+For the more consistent access, use the device coherent memory, just
+by replacing the call pattern in the allocator helpers.
+
+The only point we need to be careful for is the device object passed
+there; since bcm2835-audio driver creates fake devices and each card
+is created on top of that, we need to pass its parent device as the
+real device object.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c        | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -345,8 +345,8 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+       /* pre-allocation of buffers */
+       /* NOTE: this may fail */
+-      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+-                                            snd_dma_continuous_data(GFP_KERNEL),
++      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++                                            chip->card->dev->parent,
+                                             snd_bcm2835_playback_hw.buffer_bytes_max,
+                                             snd_bcm2835_playback_hw.buffer_bytes_max);
+@@ -371,8 +371,8 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+       /* pre-allocation of buffers */
+       /* NOTE: this may fail */
+-      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+-              snd_dma_continuous_data(GFP_KERNEL),
++      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++              chip->card->dev->parent,
+               snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
+       return 0;
+@@ -404,8 +404,8 @@ int snd_bcm2835_new_simple_pcm(struct bc
+       snd_pcm_lib_preallocate_pages_for_all(
+               pcm,
+-              SNDRV_DMA_TYPE_CONTINUOUS,
+-              snd_dma_continuous_data(GFP_KERNEL),
++              SNDRV_DMA_TYPE_DEV,
++              chip->card->dev->parent,
+               snd_bcm2835_playback_hw.buffer_bytes_max,
+               snd_bcm2835_playback_hw.buffer_bytes_max);
diff --git a/target/linux/brcm2708/patches-4.19/950-0397-staging-bcm2835-audio-Move-module-parameter-descript.patch b/target/linux/brcm2708/patches-4.19/950-0397-staging-bcm2835-audio-Move-module-parameter-descript.patch
deleted file mode 100644 (file)
index 5db4daa..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From fb05aeb91f3e94e89ad2d9aa68104e6e4cc97239 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:53 +0200
-Subject: [PATCH] staging: bcm2835-audio: Move module parameter
- description
-
-commit b876f2075808e95e244053caa53fa7e86e929a99 upstream.
-
-For more consistency, move the module parameter description right
-after its variable definition.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -19,6 +19,8 @@ struct bcm2835_audio_instance {
- };
- static bool force_bulk;
-+module_param(force_bulk, bool, 0444);
-+MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
- static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
- {
-@@ -378,6 +380,3 @@ int bcm2835_audio_write(struct bcm2835_a
-       bcm2835_audio_unlock(instance);
-       return err;
- }
--
--module_param(force_bulk, bool, 0444);
--MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
diff --git a/target/linux/brcm2708/patches-4.19/950-0397-staging-bcm2835-audio-Set-SNDRV_PCM_INFO_SYNC_APPLPT.patch b/target/linux/brcm2708/patches-4.19/950-0397-staging-bcm2835-audio-Set-SNDRV_PCM_INFO_SYNC_APPLPT.patch
new file mode 100644 (file)
index 0000000..5b38ca5
--- /dev/null
@@ -0,0 +1,40 @@
+From 27417ac1fa4894dc46d71cc34af17fe6a5186f2f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:55 +0200
+Subject: [PATCH] staging: bcm2835-audio: Set
+ SNDRV_PCM_INFO_SYNC_APPLPTR
+
+commit b59d6a5f73501f74848d6700101e7736afe3d54a upstream.
+
+The recent ALSA PCM core supports the SNDRV_PCM_INFO_SYNC_APPLPTR flag
+indicating that the driver needs the ack call at each appl_ptr
+update.  This is requirement for the indirect PCM implementations like
+bcm2835-audio driver, too.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -12,7 +12,7 @@
+ static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+-               SNDRV_PCM_INFO_DRAIN_TRIGGER),
++               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+       .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+       .rate_min = 8000,
+@@ -29,7 +29,7 @@ static const struct snd_pcm_hardware snd
+ static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+-               SNDRV_PCM_INFO_DRAIN_TRIGGER),
++               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
+       SNDRV_PCM_RATE_48000,
diff --git a/target/linux/brcm2708/patches-4.19/950-0398-staging-bcm2835-audio-Simplify-PCM-creation-helpers.patch b/target/linux/brcm2708/patches-4.19/950-0398-staging-bcm2835-audio-Simplify-PCM-creation-helpers.patch
new file mode 100644 (file)
index 0000000..6ead1b4
--- /dev/null
@@ -0,0 +1,196 @@
+From 706f9b2b95a2fff44f92deada99545036c249658 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:56 +0200
+Subject: [PATCH] staging: bcm2835-audio: Simplify PCM creation helpers
+
+commit 74470ffeb9aed5548654cfca881bf1d7469fe9c4 upstream.
+
+All three functions to create PCM objects are fairly resemble, and can
+be unified to a single common helper.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 87 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.c     | 17 +++-
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  9 +-
+ 3 files changed, 32 insertions(+), 81 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -324,91 +324,36 @@ static const struct snd_pcm_ops snd_bcm2
+ };
+ /* create a pcm device */
+-int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels)
++int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
++                      int idx, enum snd_bcm2835_route route,
++                      u32 numchannels, bool spdif)
+ {
+       struct snd_pcm *pcm;
+       int err;
+-      err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
+-      if (err < 0)
+-              return err;
+-      pcm->private_data = chip;
+-      pcm->nonatomic = true;
+-      strcpy(pcm->name, "bcm2835 ALSA");
+-      chip->pcm = pcm;
+-      chip->dest = AUDIO_DEST_AUTO;
+-      chip->volume = 0;
+-      chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
+-      /* set operators */
+-      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+-                      &snd_bcm2835_playback_ops);
+-
+-      /* pre-allocation of buffers */
+-      /* NOTE: this may fail */
+-      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+-                                            chip->card->dev->parent,
+-                                            snd_bcm2835_playback_hw.buffer_bytes_max,
+-                                            snd_bcm2835_playback_hw.buffer_bytes_max);
+-
+-      return 0;
+-}
+-
+-int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip)
+-{
+-      struct snd_pcm *pcm;
+-      int err;
+-
+-      err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
+-      if (err < 0)
+-              return err;
+-
+-      pcm->private_data = chip;
+-      pcm->nonatomic = true;
+-      strcpy(pcm->name, "bcm2835 IEC958/HDMI");
+-      chip->pcm_spdif = pcm;
+-      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+-                      &snd_bcm2835_playback_spdif_ops);
+-
+-      /* pre-allocation of buffers */
+-      /* NOTE: this may fail */
+-      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+-              chip->card->dev->parent,
+-              snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
+-
+-      return 0;
+-}
+-
+-int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
+-                             const char *name,
+-                             enum snd_bcm2835_route route,
+-                             u32 numchannels)
+-{
+-      struct snd_pcm *pcm;
+-      int err;
+-
+-      err = snd_pcm_new(chip->card, name, 0, numchannels,
+-                        0, &pcm);
++      err = snd_pcm_new(chip->card, name, idx, numchannels, 0, &pcm);
+       if (err)
+               return err;
+       pcm->private_data = chip;
+       pcm->nonatomic = true;
+       strcpy(pcm->name, name);
+-      chip->pcm = pcm;
+-      chip->dest = route;
+-      chip->volume = 0;
+-      chip->mute = CTRL_VOL_UNMUTE;
++      if (!spdif) {
++              chip->dest = route;
++              chip->volume = 0;
++              chip->mute = CTRL_VOL_UNMUTE;
++      }
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++                      spdif ? &snd_bcm2835_playback_spdif_ops :
+                       &snd_bcm2835_playback_ops);
+-      snd_pcm_lib_preallocate_pages_for_all(
+-              pcm,
+-              SNDRV_DMA_TYPE_DEV,
+-              chip->card->dev->parent,
+-              snd_bcm2835_playback_hw.buffer_bytes_max,
+-              snd_bcm2835_playback_hw.buffer_bytes_max);
++      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++              chip->card->dev->parent, 128 * 1024, 128 * 1024);
++      if (spdif)
++              chip->pcm_spdif = pcm;
++      else
++              chip->pcm = pcm;
+       return 0;
+ }
+-
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -138,17 +138,26 @@ static int bcm2835_audio_alsa_newpcm(str
+ {
+       int err;
+-      err = snd_bcm2835_new_pcm(chip, numchannels - 1);
++      err = snd_bcm2835_new_pcm(chip, "bcm2835 ALSA", 0, AUDIO_DEST_AUTO,
++                                numchannels - 1, false);
+       if (err)
+               return err;
+-      err = snd_bcm2835_new_spdif_pcm(chip);
++      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
+       if (err)
+               return err;
+       return 0;
+ }
++static int bcm2835_audio_simple_newpcm(struct bcm2835_chip *chip,
++                                     const char *name,
++                                     enum snd_bcm2835_route route,
++                                     u32 numchannels)
++{
++      return snd_bcm2835_new_pcm(chip, name, 0, route, numchannels, false);
++}
++
+ static struct bcm2835_audio_driver bcm2835_audio_alsa = {
+       .driver = {
+               .name = "bcm2835_alsa",
+@@ -169,7 +178,7 @@ static struct bcm2835_audio_driver bcm28
+       .shortname = "bcm2835 HDMI",
+       .longname  = "bcm2835 HDMI",
+       .minchannels = 1,
+-      .newpcm = snd_bcm2835_new_simple_pcm,
++      .newpcm = bcm2835_audio_simple_newpcm,
+       .newctl = snd_bcm2835_new_hdmi_ctl,
+       .route = AUDIO_DEST_HDMI
+ };
+@@ -182,7 +191,7 @@ static struct bcm2835_audio_driver bcm28
+       .shortname = "bcm2835 Headphones",
+       .longname  = "bcm2835 Headphones",
+       .minchannels = 1,
+-      .newpcm = snd_bcm2835_new_simple_pcm,
++      .newpcm = bcm2835_audio_simple_newpcm,
+       .newctl = snd_bcm2835_new_headphones_ctl,
+       .route = AUDIO_DEST_HEADPHONES
+ };
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -84,12 +84,9 @@ struct bcm2835_alsa_stream {
+ };
+ int snd_bcm2835_new_ctl(struct bcm2835_chip *chip);
+-int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels);
+-int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip);
+-int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
+-                             const char *name,
+-                             enum snd_bcm2835_route route,
+-                             u32 numchannels);
++int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
++                      int idx, enum snd_bcm2835_route route,
++                      u32 numchannels, bool spdif);
+ int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
+ int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
diff --git a/target/linux/brcm2708/patches-4.19/950-0398-staging-bcm2835-audio-Use-coherent-device-buffers.patch b/target/linux/brcm2708/patches-4.19/950-0398-staging-bcm2835-audio-Use-coherent-device-buffers.patch
deleted file mode 100644 (file)
index dfd4b97..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From 8a01a25d0ad7e9d06f64fddae871deb91c3988ac Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:54 +0200
-Subject: [PATCH] staging: bcm2835-audio: Use coherent device buffers
-
-commit ad29c6e6cbf6f2af7362b043adad51a3be3d39c7 upstream.
-
-The memory access to the pages allocated with
-SNDRV_DMA_TYPE_CONTINUOUS are basically non-coherent, and it becomes a
-problem when a process accesses via mmap.
-
-For the more consistent access, use the device coherent memory, just
-by replacing the call pattern in the allocator helpers.
-
-The only point we need to be careful for is the device object passed
-there; since bcm2835-audio driver creates fake devices and each card
-is created on top of that, we need to pass its parent device as the
-real device object.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c        | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -345,8 +345,8 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
-       /* pre-allocation of buffers */
-       /* NOTE: this may fail */
--      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
--                                            snd_dma_continuous_data(GFP_KERNEL),
-+      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+                                            chip->card->dev->parent,
-                                             snd_bcm2835_playback_hw.buffer_bytes_max,
-                                             snd_bcm2835_playback_hw.buffer_bytes_max);
-@@ -371,8 +371,8 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
-       /* pre-allocation of buffers */
-       /* NOTE: this may fail */
--      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
--              snd_dma_continuous_data(GFP_KERNEL),
-+      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+              chip->card->dev->parent,
-               snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
-       return 0;
-@@ -404,8 +404,8 @@ int snd_bcm2835_new_simple_pcm(struct bc
-       snd_pcm_lib_preallocate_pages_for_all(
-               pcm,
--              SNDRV_DMA_TYPE_CONTINUOUS,
--              snd_dma_continuous_data(GFP_KERNEL),
-+              SNDRV_DMA_TYPE_DEV,
-+              chip->card->dev->parent,
-               snd_bcm2835_playback_hw.buffer_bytes_max,
-               snd_bcm2835_playback_hw.buffer_bytes_max);
diff --git a/target/linux/brcm2708/patches-4.19/950-0399-staging-bcm2835-audio-Set-SNDRV_PCM_INFO_SYNC_APPLPT.patch b/target/linux/brcm2708/patches-4.19/950-0399-staging-bcm2835-audio-Set-SNDRV_PCM_INFO_SYNC_APPLPT.patch
deleted file mode 100644 (file)
index 5b38ca5..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From 27417ac1fa4894dc46d71cc34af17fe6a5186f2f Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:55 +0200
-Subject: [PATCH] staging: bcm2835-audio: Set
- SNDRV_PCM_INFO_SYNC_APPLPTR
-
-commit b59d6a5f73501f74848d6700101e7736afe3d54a upstream.
-
-The recent ALSA PCM core supports the SNDRV_PCM_INFO_SYNC_APPLPTR flag
-indicating that the driver needs the ack call at each appl_ptr
-update.  This is requirement for the indirect PCM implementations like
-bcm2835-audio driver, too.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -12,7 +12,7 @@
- static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
--               SNDRV_PCM_INFO_DRAIN_TRIGGER),
-+               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
-       .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
-       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-       .rate_min = 8000,
-@@ -29,7 +29,7 @@ static const struct snd_pcm_hardware snd
- static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
--               SNDRV_PCM_INFO_DRAIN_TRIGGER),
-+               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
-       SNDRV_PCM_RATE_48000,
diff --git a/target/linux/brcm2708/patches-4.19/950-0399-staging-bcm2835-audio-Simplify-kctl-creation-helpers.patch b/target/linux/brcm2708/patches-4.19/950-0399-staging-bcm2835-audio-Simplify-kctl-creation-helpers.patch
new file mode 100644 (file)
index 0000000..ec0530b
--- /dev/null
@@ -0,0 +1,161 @@
+From c4766c1589a25608ffe6848722632be2f65d0951 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:57 +0200
+Subject: [PATCH] staging: bcm2835-audio: Simplify kctl creation
+ helpers
+
+commit dc5c0eb1e8601206dffbfc302cbd190f89dcd040 upstream.
+
+Just a minor code refactoring and adding some const prefix.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 69 +++++++------------
+ 1 file changed, 25 insertions(+), 44 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -97,40 +97,34 @@ static int snd_bcm2835_ctl_put(struct sn
+ static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
+-static struct snd_kcontrol_new snd_bcm2835_ctl[] = {
++static const struct snd_kcontrol_new snd_bcm2835_ctl[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "PCM Playback Volume",
+-              .index = 0,
+               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+               .private_value = PCM_PLAYBACK_VOLUME,
+               .info = snd_bcm2835_ctl_info,
+               .get = snd_bcm2835_ctl_get,
+               .put = snd_bcm2835_ctl_put,
+-              .count = 1,
+               .tlv = {.p = snd_bcm2835_db_scale}
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "PCM Playback Switch",
+-              .index = 0,
+               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+               .private_value = PCM_PLAYBACK_MUTE,
+               .info = snd_bcm2835_ctl_info,
+               .get = snd_bcm2835_ctl_get,
+               .put = snd_bcm2835_ctl_put,
+-              .count = 1,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "PCM Playback Route",
+-              .index = 0,
+               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+               .private_value = PCM_PLAYBACK_DEVICE,
+               .info = snd_bcm2835_ctl_info,
+               .get = snd_bcm2835_ctl_get,
+               .put = snd_bcm2835_ctl_put,
+-              .count = 1,
+       },
+ };
+@@ -196,7 +190,7 @@ static int snd_bcm2835_spdif_mask_get(st
+       return 0;
+ }
+-static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
++static const struct snd_kcontrol_new snd_bcm2835_spdif[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+@@ -213,28 +207,32 @@ static struct snd_kcontrol_new snd_bcm28
+       },
+ };
+-int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
++static int create_ctls(struct bcm2835_chip *chip, size_t size,
++                     const struct snd_kcontrol_new *kctls)
+ {
+-      int err;
+-      unsigned int idx;
++      int i, err;
+-      strcpy(chip->card->mixername, "Broadcom Mixer");
+-      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) {
+-              err = snd_ctl_add(chip->card,
+-                                snd_ctl_new1(&snd_bcm2835_ctl[idx], chip));
+-              if (err < 0)
+-                      return err;
+-      }
+-      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) {
+-              err = snd_ctl_add(chip->card,
+-                                snd_ctl_new1(&snd_bcm2835_spdif[idx], chip));
++      for (i = 0; i < size; i++) {
++              err = snd_ctl_add(chip->card, snd_ctl_new1(&kctls[i], chip));
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+ }
+-static struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
++int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
++{
++      int err;
++
++      strcpy(chip->card->mixername, "Broadcom Mixer");
++      err = create_ctls(chip, ARRAY_SIZE(snd_bcm2835_ctl), snd_bcm2835_ctl);
++      if (err < 0)
++              return err;
++      return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_spdif),
++                         snd_bcm2835_spdif);
++}
++
++static const struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Headphone Playback Volume",
+@@ -263,21 +261,12 @@ static struct snd_kcontrol_new snd_bcm28
+ int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip)
+ {
+-      int err;
+-      unsigned int idx;
+-
+       strcpy(chip->card->mixername, "Broadcom Mixer");
+-      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_headphones_ctl); idx++) {
+-              err = snd_ctl_add(chip->card,
+-                                snd_ctl_new1(&snd_bcm2835_headphones_ctl[idx],
+-                                             chip));
+-              if (err)
+-                      return err;
+-      }
+-      return 0;
++      return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_headphones_ctl),
++                         snd_bcm2835_headphones_ctl);
+ }
+-static struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
++static const struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "HDMI Playback Volume",
+@@ -306,16 +295,8 @@ static struct snd_kcontrol_new snd_bcm28
+ int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip)
+ {
+-      int err;
+-      unsigned int idx;
+-
+       strcpy(chip->card->mixername, "Broadcom Mixer");
+-      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_hdmi); idx++) {
+-              err = snd_ctl_add(chip->card,
+-                                snd_ctl_new1(&snd_bcm2835_hdmi[idx], chip));
+-              if (err)
+-                      return err;
+-      }
+-      return 0;
++      return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_hdmi),
++                         snd_bcm2835_hdmi);
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0400-staging-bcm2835-audio-Simplify-PCM-creation-helpers.patch b/target/linux/brcm2708/patches-4.19/950-0400-staging-bcm2835-audio-Simplify-PCM-creation-helpers.patch
deleted file mode 100644 (file)
index 6ead1b4..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-From 706f9b2b95a2fff44f92deada99545036c249658 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:56 +0200
-Subject: [PATCH] staging: bcm2835-audio: Simplify PCM creation helpers
-
-commit 74470ffeb9aed5548654cfca881bf1d7469fe9c4 upstream.
-
-All three functions to create PCM objects are fairly resemble, and can
-be unified to a single common helper.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 87 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.c     | 17 +++-
- .../vc04_services/bcm2835-audio/bcm2835.h     |  9 +-
- 3 files changed, 32 insertions(+), 81 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -324,91 +324,36 @@ static const struct snd_pcm_ops snd_bcm2
- };
- /* create a pcm device */
--int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels)
-+int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
-+                      int idx, enum snd_bcm2835_route route,
-+                      u32 numchannels, bool spdif)
- {
-       struct snd_pcm *pcm;
-       int err;
--      err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
--      if (err < 0)
--              return err;
--      pcm->private_data = chip;
--      pcm->nonatomic = true;
--      strcpy(pcm->name, "bcm2835 ALSA");
--      chip->pcm = pcm;
--      chip->dest = AUDIO_DEST_AUTO;
--      chip->volume = 0;
--      chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
--      /* set operators */
--      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
--                      &snd_bcm2835_playback_ops);
--
--      /* pre-allocation of buffers */
--      /* NOTE: this may fail */
--      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
--                                            chip->card->dev->parent,
--                                            snd_bcm2835_playback_hw.buffer_bytes_max,
--                                            snd_bcm2835_playback_hw.buffer_bytes_max);
--
--      return 0;
--}
--
--int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip)
--{
--      struct snd_pcm *pcm;
--      int err;
--
--      err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
--      if (err < 0)
--              return err;
--
--      pcm->private_data = chip;
--      pcm->nonatomic = true;
--      strcpy(pcm->name, "bcm2835 IEC958/HDMI");
--      chip->pcm_spdif = pcm;
--      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
--                      &snd_bcm2835_playback_spdif_ops);
--
--      /* pre-allocation of buffers */
--      /* NOTE: this may fail */
--      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
--              chip->card->dev->parent,
--              snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
--
--      return 0;
--}
--
--int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
--                             const char *name,
--                             enum snd_bcm2835_route route,
--                             u32 numchannels)
--{
--      struct snd_pcm *pcm;
--      int err;
--
--      err = snd_pcm_new(chip->card, name, 0, numchannels,
--                        0, &pcm);
-+      err = snd_pcm_new(chip->card, name, idx, numchannels, 0, &pcm);
-       if (err)
-               return err;
-       pcm->private_data = chip;
-       pcm->nonatomic = true;
-       strcpy(pcm->name, name);
--      chip->pcm = pcm;
--      chip->dest = route;
--      chip->volume = 0;
--      chip->mute = CTRL_VOL_UNMUTE;
-+      if (!spdif) {
-+              chip->dest = route;
-+              chip->volume = 0;
-+              chip->mute = CTRL_VOL_UNMUTE;
-+      }
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+                      spdif ? &snd_bcm2835_playback_spdif_ops :
-                       &snd_bcm2835_playback_ops);
--      snd_pcm_lib_preallocate_pages_for_all(
--              pcm,
--              SNDRV_DMA_TYPE_DEV,
--              chip->card->dev->parent,
--              snd_bcm2835_playback_hw.buffer_bytes_max,
--              snd_bcm2835_playback_hw.buffer_bytes_max);
-+      snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+              chip->card->dev->parent, 128 * 1024, 128 * 1024);
-+      if (spdif)
-+              chip->pcm_spdif = pcm;
-+      else
-+              chip->pcm = pcm;
-       return 0;
- }
--
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -138,17 +138,26 @@ static int bcm2835_audio_alsa_newpcm(str
- {
-       int err;
--      err = snd_bcm2835_new_pcm(chip, numchannels - 1);
-+      err = snd_bcm2835_new_pcm(chip, "bcm2835 ALSA", 0, AUDIO_DEST_AUTO,
-+                                numchannels - 1, false);
-       if (err)
-               return err;
--      err = snd_bcm2835_new_spdif_pcm(chip);
-+      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
-       if (err)
-               return err;
-       return 0;
- }
-+static int bcm2835_audio_simple_newpcm(struct bcm2835_chip *chip,
-+                                     const char *name,
-+                                     enum snd_bcm2835_route route,
-+                                     u32 numchannels)
-+{
-+      return snd_bcm2835_new_pcm(chip, name, 0, route, numchannels, false);
-+}
-+
- static struct bcm2835_audio_driver bcm2835_audio_alsa = {
-       .driver = {
-               .name = "bcm2835_alsa",
-@@ -169,7 +178,7 @@ static struct bcm2835_audio_driver bcm28
-       .shortname = "bcm2835 HDMI",
-       .longname  = "bcm2835 HDMI",
-       .minchannels = 1,
--      .newpcm = snd_bcm2835_new_simple_pcm,
-+      .newpcm = bcm2835_audio_simple_newpcm,
-       .newctl = snd_bcm2835_new_hdmi_ctl,
-       .route = AUDIO_DEST_HDMI
- };
-@@ -182,7 +191,7 @@ static struct bcm2835_audio_driver bcm28
-       .shortname = "bcm2835 Headphones",
-       .longname  = "bcm2835 Headphones",
-       .minchannels = 1,
--      .newpcm = snd_bcm2835_new_simple_pcm,
-+      .newpcm = bcm2835_audio_simple_newpcm,
-       .newctl = snd_bcm2835_new_headphones_ctl,
-       .route = AUDIO_DEST_HEADPHONES
- };
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -84,12 +84,9 @@ struct bcm2835_alsa_stream {
- };
- int snd_bcm2835_new_ctl(struct bcm2835_chip *chip);
--int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels);
--int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip);
--int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
--                             const char *name,
--                             enum snd_bcm2835_route route,
--                             u32 numchannels);
-+int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
-+                      int idx, enum snd_bcm2835_route route,
-+                      u32 numchannels, bool spdif);
- int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
- int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
diff --git a/target/linux/brcm2708/patches-4.19/950-0400-staging-bcm2835-audio-Simplify-card-object-managemen.patch b/target/linux/brcm2708/patches-4.19/950-0400-staging-bcm2835-audio-Simplify-card-object-managemen.patch
new file mode 100644 (file)
index 0000000..523e543
--- /dev/null
@@ -0,0 +1,212 @@
+From b19ed31a1ced7b6d4c4c04967a509d91a134e5bb Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:58 +0200
+Subject: [PATCH] staging: bcm2835-audio: Simplify card object
+ management
+
+commit 872ae2d63d516a2a3b9c833d8685afcfa7814542 upstream.
+
+Instead of creating a dummy child device to manage the card object,
+just use devm stuff directly for releasing with snd_card_free().
+This results in a lot of code reduction.
+
+Since the dummy child devices are gone, the device object to be passed
+to the memory allocator needs to be adjusted as well.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c |   2 +-
+ .../vc04_services/bcm2835-audio/bcm2835.c     | 120 +++++-------------
+ 2 files changed, 33 insertions(+), 89 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -349,7 +349,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+                       &snd_bcm2835_playback_ops);
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+-              chip->card->dev->parent, 128 * 1024, 128 * 1024);
++              chip->card->dev, 128 * 1024, 128 * 1024);
+       if (spdif)
+               chip->pcm_spdif = pcm;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -22,38 +22,6 @@ module_param(enable_compat_alsa, bool, 0
+ MODULE_PARM_DESC(enable_compat_alsa,
+                "Enables ALSA compatibility virtual audio device");
+-static void snd_devm_unregister_child(struct device *dev, void *res)
+-{
+-      struct device *childdev = *(struct device **)res;
+-      struct bcm2835_chip *chip = dev_get_drvdata(childdev);
+-      struct snd_card *card = chip->card;
+-
+-      snd_card_free(card);
+-
+-      device_unregister(childdev);
+-}
+-
+-static int snd_devm_add_child(struct device *dev, struct device *child)
+-{
+-      struct device **dr;
+-      int ret;
+-
+-      dr = devres_alloc(snd_devm_unregister_child, sizeof(*dr), GFP_KERNEL);
+-      if (!dr)
+-              return -ENOMEM;
+-
+-      ret = device_add(child);
+-      if (ret) {
+-              devres_free(dr);
+-              return ret;
+-      }
+-
+-      *dr = child;
+-      devres_add(dev, dr);
+-
+-      return 0;
+-}
+-
+ static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
+ {
+       struct bcm2835_vchi_ctx *vchi_ctx = res;
+@@ -84,36 +52,6 @@ static int bcm2835_devm_add_vchi_ctx(str
+       return 0;
+ }
+-static void snd_bcm2835_release(struct device *dev)
+-{
+-}
+-
+-static struct device *
+-snd_create_device(struct device *parent,
+-                struct device_driver *driver,
+-                const char *name)
+-{
+-      struct device *device;
+-      int ret;
+-
+-      device = devm_kzalloc(parent, sizeof(*device), GFP_KERNEL);
+-      if (!device)
+-              return ERR_PTR(-ENOMEM);
+-
+-      device_initialize(device);
+-      device->parent = parent;
+-      device->driver = driver;
+-      device->release = snd_bcm2835_release;
+-
+-      dev_set_name(device, "%s", name);
+-
+-      ret = snd_devm_add_child(parent, device);
+-      if (ret)
+-              return ERR_PTR(ret);
+-
+-      return device;
+-}
+-
+ typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
+                                        const char *name,
+                                        enum snd_bcm2835_route route,
+@@ -216,40 +154,36 @@ static struct bcm2835_audio_drivers chil
+       },
+ };
+-static int snd_add_child_device(struct device *device,
++static void bcm2835_card_free(void *data)
++{
++      snd_card_free(data);
++}
++
++static int snd_add_child_device(struct device *dev,
+                               struct bcm2835_audio_driver *audio_driver,
+                               u32 numchans)
+ {
+       struct snd_card *card;
+-      struct device *child;
+       struct bcm2835_chip *chip;
+       int err;
+-      child = snd_create_device(device, &audio_driver->driver,
+-                                audio_driver->driver.name);
+-      if (IS_ERR(child)) {
+-              dev_err(device,
+-                      "Unable to create child device %p, error %ld",
+-                      audio_driver->driver.name,
+-                      PTR_ERR(child));
+-              return PTR_ERR(child);
+-      }
+-
+-      err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
++      err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
+       if (err < 0) {
+-              dev_err(child, "Failed to create card");
++              dev_err(dev, "Failed to create card");
+               return err;
+       }
+       chip = card->private_data;
+       chip->card = card;
+-      chip->dev = child;
++      chip->dev = dev;
+       mutex_init(&chip->audio_mutex);
+-      chip->vchi_ctx = devres_find(device,
++      chip->vchi_ctx = devres_find(dev,
+                                    bcm2835_devm_free_vchi_ctx, NULL, NULL);
+-      if (!chip->vchi_ctx)
+-              return -ENODEV;
++      if (!chip->vchi_ctx) {
++              err = -ENODEV;
++              goto error;
++      }
+       strcpy(card->driver, audio_driver->driver.name);
+       strcpy(card->shortname, audio_driver->shortname);
+@@ -259,26 +193,36 @@ static int snd_add_child_device(struct d
+               audio_driver->route,
+               numchans);
+       if (err) {
+-              dev_err(child, "Failed to create pcm, error %d\n", err);
+-              return err;
++              dev_err(dev, "Failed to create pcm, error %d\n", err);
++              goto error;
+       }
+       err = audio_driver->newctl(chip);
+       if (err) {
+-              dev_err(child, "Failed to create controls, error %d\n", err);
+-              return err;
++              dev_err(dev, "Failed to create controls, error %d\n", err);
++              goto error;
+       }
+       err = snd_card_register(card);
+       if (err) {
+-              dev_err(child, "Failed to register card, error %d\n", err);
+-              return err;
++              dev_err(dev, "Failed to register card, error %d\n", err);
++              goto error;
+       }
+-      dev_set_drvdata(child, chip);
+-      dev_info(child, "card created with %d channels\n", numchans);
++      dev_set_drvdata(dev, chip);
++      err = devm_add_action(dev, bcm2835_card_free, card);
++      if (err < 0) {
++              dev_err(dev, "Failed to add devm action, err %d\n", err);
++              goto error;
++      }
++
++      dev_info(dev, "card created with %d channels\n", numchans);
+       return 0;
++
++ error:
++      snd_card_free(card);
++      return err;
+ }
+ static int snd_add_child_devices(struct device *device, u32 numchans)
diff --git a/target/linux/brcm2708/patches-4.19/950-0401-staging-bcm2835-audio-Simplify-kctl-creation-helpers.patch b/target/linux/brcm2708/patches-4.19/950-0401-staging-bcm2835-audio-Simplify-kctl-creation-helpers.patch
deleted file mode 100644 (file)
index ec0530b..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-From c4766c1589a25608ffe6848722632be2f65d0951 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:57 +0200
-Subject: [PATCH] staging: bcm2835-audio: Simplify kctl creation
- helpers
-
-commit dc5c0eb1e8601206dffbfc302cbd190f89dcd040 upstream.
-
-Just a minor code refactoring and adding some const prefix.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 69 +++++++------------
- 1 file changed, 25 insertions(+), 44 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -97,40 +97,34 @@ static int snd_bcm2835_ctl_put(struct sn
- static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
--static struct snd_kcontrol_new snd_bcm2835_ctl[] = {
-+static const struct snd_kcontrol_new snd_bcm2835_ctl[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "PCM Playback Volume",
--              .index = 0,
-               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-               .private_value = PCM_PLAYBACK_VOLUME,
-               .info = snd_bcm2835_ctl_info,
-               .get = snd_bcm2835_ctl_get,
-               .put = snd_bcm2835_ctl_put,
--              .count = 1,
-               .tlv = {.p = snd_bcm2835_db_scale}
-       },
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "PCM Playback Switch",
--              .index = 0,
-               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-               .private_value = PCM_PLAYBACK_MUTE,
-               .info = snd_bcm2835_ctl_info,
-               .get = snd_bcm2835_ctl_get,
-               .put = snd_bcm2835_ctl_put,
--              .count = 1,
-       },
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "PCM Playback Route",
--              .index = 0,
-               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-               .private_value = PCM_PLAYBACK_DEVICE,
-               .info = snd_bcm2835_ctl_info,
-               .get = snd_bcm2835_ctl_get,
-               .put = snd_bcm2835_ctl_put,
--              .count = 1,
-       },
- };
-@@ -196,7 +190,7 @@ static int snd_bcm2835_spdif_mask_get(st
-       return 0;
- }
--static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
-+static const struct snd_kcontrol_new snd_bcm2835_spdif[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
-               .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
-@@ -213,28 +207,32 @@ static struct snd_kcontrol_new snd_bcm28
-       },
- };
--int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
-+static int create_ctls(struct bcm2835_chip *chip, size_t size,
-+                     const struct snd_kcontrol_new *kctls)
- {
--      int err;
--      unsigned int idx;
-+      int i, err;
--      strcpy(chip->card->mixername, "Broadcom Mixer");
--      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) {
--              err = snd_ctl_add(chip->card,
--                                snd_ctl_new1(&snd_bcm2835_ctl[idx], chip));
--              if (err < 0)
--                      return err;
--      }
--      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) {
--              err = snd_ctl_add(chip->card,
--                                snd_ctl_new1(&snd_bcm2835_spdif[idx], chip));
-+      for (i = 0; i < size; i++) {
-+              err = snd_ctl_add(chip->card, snd_ctl_new1(&kctls[i], chip));
-               if (err < 0)
-                       return err;
-       }
-       return 0;
- }
--static struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
-+int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
-+{
-+      int err;
-+
-+      strcpy(chip->card->mixername, "Broadcom Mixer");
-+      err = create_ctls(chip, ARRAY_SIZE(snd_bcm2835_ctl), snd_bcm2835_ctl);
-+      if (err < 0)
-+              return err;
-+      return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_spdif),
-+                         snd_bcm2835_spdif);
-+}
-+
-+static const struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Headphone Playback Volume",
-@@ -263,21 +261,12 @@ static struct snd_kcontrol_new snd_bcm28
- int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip)
- {
--      int err;
--      unsigned int idx;
--
-       strcpy(chip->card->mixername, "Broadcom Mixer");
--      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_headphones_ctl); idx++) {
--              err = snd_ctl_add(chip->card,
--                                snd_ctl_new1(&snd_bcm2835_headphones_ctl[idx],
--                                             chip));
--              if (err)
--                      return err;
--      }
--      return 0;
-+      return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_headphones_ctl),
-+                         snd_bcm2835_headphones_ctl);
- }
--static struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
-+static const struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "HDMI Playback Volume",
-@@ -306,16 +295,8 @@ static struct snd_kcontrol_new snd_bcm28
- int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip)
- {
--      int err;
--      unsigned int idx;
--
-       strcpy(chip->card->mixername, "Broadcom Mixer");
--      for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_hdmi); idx++) {
--              err = snd_ctl_add(chip->card,
--                                snd_ctl_new1(&snd_bcm2835_hdmi[idx], chip));
--              if (err)
--                      return err;
--      }
--      return 0;
-+      return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_hdmi),
-+                         snd_bcm2835_hdmi);
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0401-staging-bcm2835-audio-unify-FOURCC-command-definitio.patch b/target/linux/brcm2708/patches-4.19/950-0401-staging-bcm2835-audio-unify-FOURCC-command-definitio.patch
new file mode 100644 (file)
index 0000000..fa24932
--- /dev/null
@@ -0,0 +1,71 @@
+From 26693d4d1239b8239644ce6da50b8ce06ff18ae5 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:50 +0200
+Subject: [PATCH] staging: bcm2835-audio: unify FOURCC command
+ definitions
+
+commit a90d8f49cc7fd7220aa24b85fc74ef3cfd62b96f upstream.
+
+The device communicates with the audio core using FOURCC codes. The
+driver was generating them using different macros/expressions. We now
+use the same macro to create them and centralize all the definitions.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-vchiq.c     | 13 ++++---------
+ .../bcm2835-audio/vc_vchi_audioserv_defs.h          |  4 +++-
+ 2 files changed, 7 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -89,11 +89,6 @@ static int bcm2835_audio_send_simple(str
+       return bcm2835_audio_send_msg(instance, &m, wait);
+ }
+-static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
+-                                              'M' << 8  | 'A');
+-static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
+-                                              'T' << 8  | 'A');
+-
+ static void audio_vchi_callback(void *param,
+                               const VCHI_CALLBACK_REASON_T reason,
+                               void *msg_handle)
+@@ -112,8 +107,8 @@ static void audio_vchi_callback(void *pa
+               instance->result = m.u.result.success;
+               complete(&instance->msg_avail_comp);
+       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
+-              if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
+-                  m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
++              if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
++                  m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
+                       dev_err(instance->dev, "invalid cookie\n");
+               else
+                       bcm2835_playback_fifo(instance->alsa_stream,
+@@ -337,8 +332,8 @@ int bcm2835_audio_write(struct bcm2835_a
+               .type = VC_AUDIO_MSG_TYPE_WRITE,
+               .u.write.count = size,
+               .u.write.max_packet = instance->max_packet,
+-              .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
+-              .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
++              .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
++              .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
+       };
+       unsigned int count;
+       int err, status;
+--- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
+@@ -7,8 +7,10 @@
+ #define VC_AUDIOSERV_MIN_VER 1
+ #define VC_AUDIOSERV_VER 2
+-/* FourCC code used for VCHI connection */
++/* FourCC codes used for VCHI communication */
+ #define VC_AUDIO_SERVER_NAME  MAKE_FOURCC("AUDS")
++#define VC_AUDIO_WRITE_COOKIE1 MAKE_FOURCC("BCMA")
++#define VC_AUDIO_WRITE_COOKIE2 MAKE_FOURCC("DATA")
+ /*
+  *  List of screens that are currently supported
diff --git a/target/linux/brcm2708/patches-4.19/950-0402-staging-bcm2835-audio-Simplify-card-object-managemen.patch b/target/linux/brcm2708/patches-4.19/950-0402-staging-bcm2835-audio-Simplify-card-object-managemen.patch
deleted file mode 100644 (file)
index 523e543..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-From b19ed31a1ced7b6d4c4c04967a509d91a134e5bb Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:58 +0200
-Subject: [PATCH] staging: bcm2835-audio: Simplify card object
- management
-
-commit 872ae2d63d516a2a3b9c833d8685afcfa7814542 upstream.
-
-Instead of creating a dummy child device to manage the card object,
-just use devm stuff directly for releasing with snd_card_free().
-This results in a lot of code reduction.
-
-Since the dummy child devices are gone, the device object to be passed
-to the memory allocator needs to be adjusted as well.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c |   2 +-
- .../vc04_services/bcm2835-audio/bcm2835.c     | 120 +++++-------------
- 2 files changed, 33 insertions(+), 89 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -349,7 +349,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
-                       &snd_bcm2835_playback_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
--              chip->card->dev->parent, 128 * 1024, 128 * 1024);
-+              chip->card->dev, 128 * 1024, 128 * 1024);
-       if (spdif)
-               chip->pcm_spdif = pcm;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -22,38 +22,6 @@ module_param(enable_compat_alsa, bool, 0
- MODULE_PARM_DESC(enable_compat_alsa,
-                "Enables ALSA compatibility virtual audio device");
--static void snd_devm_unregister_child(struct device *dev, void *res)
--{
--      struct device *childdev = *(struct device **)res;
--      struct bcm2835_chip *chip = dev_get_drvdata(childdev);
--      struct snd_card *card = chip->card;
--
--      snd_card_free(card);
--
--      device_unregister(childdev);
--}
--
--static int snd_devm_add_child(struct device *dev, struct device *child)
--{
--      struct device **dr;
--      int ret;
--
--      dr = devres_alloc(snd_devm_unregister_child, sizeof(*dr), GFP_KERNEL);
--      if (!dr)
--              return -ENOMEM;
--
--      ret = device_add(child);
--      if (ret) {
--              devres_free(dr);
--              return ret;
--      }
--
--      *dr = child;
--      devres_add(dev, dr);
--
--      return 0;
--}
--
- static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
- {
-       struct bcm2835_vchi_ctx *vchi_ctx = res;
-@@ -84,36 +52,6 @@ static int bcm2835_devm_add_vchi_ctx(str
-       return 0;
- }
--static void snd_bcm2835_release(struct device *dev)
--{
--}
--
--static struct device *
--snd_create_device(struct device *parent,
--                struct device_driver *driver,
--                const char *name)
--{
--      struct device *device;
--      int ret;
--
--      device = devm_kzalloc(parent, sizeof(*device), GFP_KERNEL);
--      if (!device)
--              return ERR_PTR(-ENOMEM);
--
--      device_initialize(device);
--      device->parent = parent;
--      device->driver = driver;
--      device->release = snd_bcm2835_release;
--
--      dev_set_name(device, "%s", name);
--
--      ret = snd_devm_add_child(parent, device);
--      if (ret)
--              return ERR_PTR(ret);
--
--      return device;
--}
--
- typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
-                                        const char *name,
-                                        enum snd_bcm2835_route route,
-@@ -216,40 +154,36 @@ static struct bcm2835_audio_drivers chil
-       },
- };
--static int snd_add_child_device(struct device *device,
-+static void bcm2835_card_free(void *data)
-+{
-+      snd_card_free(data);
-+}
-+
-+static int snd_add_child_device(struct device *dev,
-                               struct bcm2835_audio_driver *audio_driver,
-                               u32 numchans)
- {
-       struct snd_card *card;
--      struct device *child;
-       struct bcm2835_chip *chip;
-       int err;
--      child = snd_create_device(device, &audio_driver->driver,
--                                audio_driver->driver.name);
--      if (IS_ERR(child)) {
--              dev_err(device,
--                      "Unable to create child device %p, error %ld",
--                      audio_driver->driver.name,
--                      PTR_ERR(child));
--              return PTR_ERR(child);
--      }
--
--      err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
-+      err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
-       if (err < 0) {
--              dev_err(child, "Failed to create card");
-+              dev_err(dev, "Failed to create card");
-               return err;
-       }
-       chip = card->private_data;
-       chip->card = card;
--      chip->dev = child;
-+      chip->dev = dev;
-       mutex_init(&chip->audio_mutex);
--      chip->vchi_ctx = devres_find(device,
-+      chip->vchi_ctx = devres_find(dev,
-                                    bcm2835_devm_free_vchi_ctx, NULL, NULL);
--      if (!chip->vchi_ctx)
--              return -ENODEV;
-+      if (!chip->vchi_ctx) {
-+              err = -ENODEV;
-+              goto error;
-+      }
-       strcpy(card->driver, audio_driver->driver.name);
-       strcpy(card->shortname, audio_driver->shortname);
-@@ -259,26 +193,36 @@ static int snd_add_child_device(struct d
-               audio_driver->route,
-               numchans);
-       if (err) {
--              dev_err(child, "Failed to create pcm, error %d\n", err);
--              return err;
-+              dev_err(dev, "Failed to create pcm, error %d\n", err);
-+              goto error;
-       }
-       err = audio_driver->newctl(chip);
-       if (err) {
--              dev_err(child, "Failed to create controls, error %d\n", err);
--              return err;
-+              dev_err(dev, "Failed to create controls, error %d\n", err);
-+              goto error;
-       }
-       err = snd_card_register(card);
-       if (err) {
--              dev_err(child, "Failed to register card, error %d\n", err);
--              return err;
-+              dev_err(dev, "Failed to register card, error %d\n", err);
-+              goto error;
-       }
--      dev_set_drvdata(child, chip);
--      dev_info(child, "card created with %d channels\n", numchans);
-+      dev_set_drvdata(dev, chip);
-+      err = devm_add_action(dev, bcm2835_card_free, card);
-+      if (err < 0) {
-+              dev_err(dev, "Failed to add devm action, err %d\n", err);
-+              goto error;
-+      }
-+
-+      dev_info(dev, "card created with %d channels\n", numchans);
-       return 0;
-+
-+ error:
-+      snd_card_free(card);
-+      return err;
- }
- static int snd_add_child_devices(struct device *device, u32 numchans)
diff --git a/target/linux/brcm2708/patches-4.19/950-0402-staging-bcm2835-audio-don-t-initialize-memory-twice.patch b/target/linux/brcm2708/patches-4.19/950-0402-staging-bcm2835-audio-don-t-initialize-memory-twice.patch
new file mode 100644 (file)
index 0000000..f5c7781
--- /dev/null
@@ -0,0 +1,30 @@
+From 7250c9d3d3f1b861d8f0c6220a81a465e45d70eb Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:51 +0200
+Subject: [PATCH] staging: bcm2835-audio: don't initialize memory twice
+
+commit 2e5f59fb77397cab3bc3d156e8be4164a67d32ef upstream.
+
+The memory is being allocated with devres_alloc(), wich ultimately uses
+__GFP_ZERO to call kmalloc. We don't need to zero the memory area again
+in bcm2835-audio.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -39,8 +39,6 @@ static int bcm2835_devm_add_vchi_ctx(str
+       if (!vchi_ctx)
+               return -ENOMEM;
+-      memset(vchi_ctx, 0, sizeof(*vchi_ctx));
+-
+       ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
+       if (ret) {
+               devres_free(vchi_ctx);
diff --git a/target/linux/brcm2708/patches-4.19/950-0403-staging-bcm2835-audio-reorder-variable-declarations-.patch b/target/linux/brcm2708/patches-4.19/950-0403-staging-bcm2835-audio-reorder-variable-declarations-.patch
new file mode 100644 (file)
index 0000000..6b9ac81
--- /dev/null
@@ -0,0 +1,118 @@
+From 604f0019cc1eaed6a316d7875fe697e53f5f105c Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:52 +0200
+Subject: [PATCH] staging: bcm2835-audio: reorder variable declarations
+ & remove trivial comments
+
+commit d048385a070552ae819f99f05bd03ec41072783d upstream.
+
+When it comes to declaring variables it's preferred, when possible, to
+use an inverted tree organization scheme.
+
+Also, removes some comments that were useless.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c      | 10 ++--------
+ .../vc04_services/bcm2835-audio/bcm2835-vchiq.c    |  4 ++--
+ .../staging/vc04_services/bcm2835-audio/bcm2835.c  | 14 +++++++-------
+ 3 files changed, 11 insertions(+), 17 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -164,14 +164,11 @@ static int snd_bcm2835_playback_spdif_op
+       return snd_bcm2835_playback_open_generic(substream, 1);
+ }
+-/* close callback */
+ static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
+ {
+-      /* the hardware-specific codes will be here */
+-
+-      struct bcm2835_chip *chip;
+-      struct snd_pcm_runtime *runtime;
+       struct bcm2835_alsa_stream *alsa_stream;
++      struct snd_pcm_runtime *runtime;
++      struct bcm2835_chip *chip;
+       chip = snd_pcm_substream_chip(substream);
+       mutex_lock(&chip->audio_mutex);
+@@ -195,20 +192,17 @@ static int snd_bcm2835_playback_close(st
+       return 0;
+ }
+-/* hw_params callback */
+ static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+ {
+       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+ }
+-/* hw_free callback */
+ static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)
+ {
+       return snd_pcm_lib_free_pages(substream);
+ }
+-/* prepare callback */
+ static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+       struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -94,9 +94,9 @@ static void audio_vchi_callback(void *pa
+                               void *msg_handle)
+ {
+       struct bcm2835_audio_instance *instance = param;
+-      int status;
+-      int msg_len;
+       struct vc_audio_msg m;
++      int msg_len;
++      int status;
+       if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
+               return;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -161,8 +161,8 @@ static int snd_add_child_device(struct d
+                               struct bcm2835_audio_driver *audio_driver,
+                               u32 numchans)
+ {
+-      struct snd_card *card;
+       struct bcm2835_chip *chip;
++      struct snd_card *card;
+       int err;
+       err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
+@@ -225,12 +225,12 @@ static int snd_add_child_device(struct d
+ static int snd_add_child_devices(struct device *device, u32 numchans)
+ {
+-      int i;
+-      int count_devices = 0;
+-      int minchannels = 0;
+-      int extrachannels = 0;
+       int extrachannels_per_driver = 0;
+       int extrachannels_remainder = 0;
++      int count_devices = 0;
++      int extrachannels = 0;
++      int minchannels = 0;
++      int i;
+       for (i = 0; i < ARRAY_SIZE(children_devices); i++)
+               if (*children_devices[i].is_enabled)
+@@ -258,9 +258,9 @@ static int snd_add_child_devices(struct
+               extrachannels_remainder);
+       for (i = 0; i < ARRAY_SIZE(children_devices); i++) {
+-              int err;
+-              int numchannels_this_device;
+               struct bcm2835_audio_driver *audio_driver;
++              int numchannels_this_device;
++              int err;
+               if (!*children_devices[i].is_enabled)
+                       continue;
diff --git a/target/linux/brcm2708/patches-4.19/950-0403-staging-bcm2835-audio-unify-FOURCC-command-definitio.patch b/target/linux/brcm2708/patches-4.19/950-0403-staging-bcm2835-audio-unify-FOURCC-command-definitio.patch
deleted file mode 100644 (file)
index fa24932..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-From 26693d4d1239b8239644ce6da50b8ce06ff18ae5 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:50 +0200
-Subject: [PATCH] staging: bcm2835-audio: unify FOURCC command
- definitions
-
-commit a90d8f49cc7fd7220aa24b85fc74ef3cfd62b96f upstream.
-
-The device communicates with the audio core using FOURCC codes. The
-driver was generating them using different macros/expressions. We now
-use the same macro to create them and centralize all the definitions.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-vchiq.c     | 13 ++++---------
- .../bcm2835-audio/vc_vchi_audioserv_defs.h          |  4 +++-
- 2 files changed, 7 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -89,11 +89,6 @@ static int bcm2835_audio_send_simple(str
-       return bcm2835_audio_send_msg(instance, &m, wait);
- }
--static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
--                                              'M' << 8  | 'A');
--static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
--                                              'T' << 8  | 'A');
--
- static void audio_vchi_callback(void *param,
-                               const VCHI_CALLBACK_REASON_T reason,
-                               void *msg_handle)
-@@ -112,8 +107,8 @@ static void audio_vchi_callback(void *pa
-               instance->result = m.u.result.success;
-               complete(&instance->msg_avail_comp);
-       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
--              if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
--                  m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
-+              if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
-+                  m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
-                       dev_err(instance->dev, "invalid cookie\n");
-               else
-                       bcm2835_playback_fifo(instance->alsa_stream,
-@@ -337,8 +332,8 @@ int bcm2835_audio_write(struct bcm2835_a
-               .type = VC_AUDIO_MSG_TYPE_WRITE,
-               .u.write.count = size,
-               .u.write.max_packet = instance->max_packet,
--              .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
--              .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
-+              .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
-+              .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
-       };
-       unsigned int count;
-       int err, status;
---- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-@@ -7,8 +7,10 @@
- #define VC_AUDIOSERV_MIN_VER 1
- #define VC_AUDIOSERV_VER 2
--/* FourCC code used for VCHI connection */
-+/* FourCC codes used for VCHI communication */
- #define VC_AUDIO_SERVER_NAME  MAKE_FOURCC("AUDS")
-+#define VC_AUDIO_WRITE_COOKIE1 MAKE_FOURCC("BCMA")
-+#define VC_AUDIO_WRITE_COOKIE2 MAKE_FOURCC("DATA")
- /*
-  *  List of screens that are currently supported
diff --git a/target/linux/brcm2708/patches-4.19/950-0404-staging-bcm2835-audio-don-t-initialize-memory-twice.patch b/target/linux/brcm2708/patches-4.19/950-0404-staging-bcm2835-audio-don-t-initialize-memory-twice.patch
deleted file mode 100644 (file)
index f5c7781..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 7250c9d3d3f1b861d8f0c6220a81a465e45d70eb Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:51 +0200
-Subject: [PATCH] staging: bcm2835-audio: don't initialize memory twice
-
-commit 2e5f59fb77397cab3bc3d156e8be4164a67d32ef upstream.
-
-The memory is being allocated with devres_alloc(), wich ultimately uses
-__GFP_ZERO to call kmalloc. We don't need to zero the memory area again
-in bcm2835-audio.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -39,8 +39,6 @@ static int bcm2835_devm_add_vchi_ctx(str
-       if (!vchi_ctx)
-               return -ENOMEM;
--      memset(vchi_ctx, 0, sizeof(*vchi_ctx));
--
-       ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
-       if (ret) {
-               devres_free(vchi_ctx);
diff --git a/target/linux/brcm2708/patches-4.19/950-0404-staging-bcm2835-audio-use-anonymous-union-in-struct-.patch b/target/linux/brcm2708/patches-4.19/950-0404-staging-bcm2835-audio-use-anonymous-union-in-struct-.patch
new file mode 100644 (file)
index 0000000..e212a94
--- /dev/null
@@ -0,0 +1,105 @@
+From 23b89436030e64196a1bc317901d08edd54fb772 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:53 +0200
+Subject: [PATCH] staging: bcm2835-audio: use anonymous union in struct
+ vc_audio_msg
+
+commit 9c2eaf7da855d314a369d48b9cbf8ac80717a1d0 upstream.
+
+In this case explicitly naming the union doesn't help overall code
+comprehension and clutters it.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c             | 30 +++++++++----------
+ .../bcm2835-audio/vc_vchi_audioserv_defs.h    |  2 +-
+ 2 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -104,15 +104,15 @@ static void audio_vchi_callback(void *pa
+       status = vchi_msg_dequeue(instance->vchi_handle,
+                                 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
+       if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
+-              instance->result = m.u.result.success;
++              instance->result = m.result.success;
+               complete(&instance->msg_avail_comp);
+       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
+-              if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
+-                  m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
++              if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
++                  m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
+                       dev_err(instance->dev, "invalid cookie\n");
+               else
+                       bcm2835_playback_fifo(instance->alsa_stream,
+-                                            m.u.complete.count);
++                                            m.complete.count);
+       } else {
+               dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
+       }
+@@ -257,11 +257,11 @@ int bcm2835_audio_set_ctls(struct bcm283
+       struct vc_audio_msg m = {};
+       m.type = VC_AUDIO_MSG_TYPE_CONTROL;
+-      m.u.control.dest = chip->dest;
++      m.control.dest = chip->dest;
+       if (!chip->mute)
+-              m.u.control.volume = CHIP_MIN_VOLUME;
++              m.control.volume = CHIP_MIN_VOLUME;
+       else
+-              m.u.control.volume = alsa2chip(chip->volume);
++              m.control.volume = alsa2chip(chip->volume);
+       return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+@@ -272,9 +272,9 @@ int bcm2835_audio_set_params(struct bcm2
+ {
+       struct vc_audio_msg m = {
+                .type = VC_AUDIO_MSG_TYPE_CONFIG,
+-               .u.config.channels = channels,
+-               .u.config.samplerate = samplerate,
+-               .u.config.bps = bps,
++               .config.channels = channels,
++               .config.samplerate = samplerate,
++               .config.bps = bps,
+       };
+       int err;
+@@ -302,7 +302,7 @@ int bcm2835_audio_drain(struct bcm2835_a
+ {
+       struct vc_audio_msg m = {
+               .type = VC_AUDIO_MSG_TYPE_STOP,
+-              .u.stop.draining = 1,
++              .stop.draining = 1,
+       };
+       return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
+@@ -330,10 +330,10 @@ int bcm2835_audio_write(struct bcm2835_a
+       struct bcm2835_audio_instance *instance = alsa_stream->instance;
+       struct vc_audio_msg m = {
+               .type = VC_AUDIO_MSG_TYPE_WRITE,
+-              .u.write.count = size,
+-              .u.write.max_packet = instance->max_packet,
+-              .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
+-              .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
++              .write.count = size,
++              .write.max_packet = instance->max_packet,
++              .write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
++              .write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
+       };
+       unsigned int count;
+       int err, status;
+--- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
+@@ -93,7 +93,7 @@ struct vc_audio_msg {
+               struct vc_audio_write write;
+               struct vc_audio_result result;
+               struct vc_audio_complete complete;
+-      } u;
++      };
+ };
+ #endif /* _VC_AUDIO_DEFS_H_ */
diff --git a/target/linux/brcm2708/patches-4.19/950-0405-staging-bcm2835-audio-more-generic-probe-function-na.patch b/target/linux/brcm2708/patches-4.19/950-0405-staging-bcm2835-audio-more-generic-probe-function-na.patch
new file mode 100644 (file)
index 0000000..6b03e1e
--- /dev/null
@@ -0,0 +1,39 @@
+From 0b7d959b0d0c18959c66696844a1c9956370ab99 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:54 +0200
+Subject: [PATCH] staging: bcm2835-audio: more generic probe function
+ name
+
+commit 96f3bd8ae6516898c7b411ecb87064bb0dd25415 upstream.
+
+There will only be one probe function, there is no use for appendig
+"_dt" the end of the name.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -291,7 +291,7 @@ static int snd_add_child_devices(struct
+       return 0;
+ }
+-static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
++static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+       u32 numchans;
+@@ -344,7 +344,7 @@ static const struct of_device_id snd_bcm
+ MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
+ static struct platform_driver bcm2835_alsa0_driver = {
+-      .probe = snd_bcm2835_alsa_probe_dt,
++      .probe = snd_bcm2835_alsa_probe,
+ #ifdef CONFIG_PM
+       .suspend = snd_bcm2835_alsa_suspend,
+       .resume = snd_bcm2835_alsa_resume,
diff --git a/target/linux/brcm2708/patches-4.19/950-0405-staging-bcm2835-audio-reorder-variable-declarations-.patch b/target/linux/brcm2708/patches-4.19/950-0405-staging-bcm2835-audio-reorder-variable-declarations-.patch
deleted file mode 100644 (file)
index 6b9ac81..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-From 604f0019cc1eaed6a316d7875fe697e53f5f105c Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:52 +0200
-Subject: [PATCH] staging: bcm2835-audio: reorder variable declarations
- & remove trivial comments
-
-commit d048385a070552ae819f99f05bd03ec41072783d upstream.
-
-When it comes to declaring variables it's preferred, when possible, to
-use an inverted tree organization scheme.
-
-Also, removes some comments that were useless.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c      | 10 ++--------
- .../vc04_services/bcm2835-audio/bcm2835-vchiq.c    |  4 ++--
- .../staging/vc04_services/bcm2835-audio/bcm2835.c  | 14 +++++++-------
- 3 files changed, 11 insertions(+), 17 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -164,14 +164,11 @@ static int snd_bcm2835_playback_spdif_op
-       return snd_bcm2835_playback_open_generic(substream, 1);
- }
--/* close callback */
- static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
- {
--      /* the hardware-specific codes will be here */
--
--      struct bcm2835_chip *chip;
--      struct snd_pcm_runtime *runtime;
-       struct bcm2835_alsa_stream *alsa_stream;
-+      struct snd_pcm_runtime *runtime;
-+      struct bcm2835_chip *chip;
-       chip = snd_pcm_substream_chip(substream);
-       mutex_lock(&chip->audio_mutex);
-@@ -195,20 +192,17 @@ static int snd_bcm2835_playback_close(st
-       return 0;
- }
--/* hw_params callback */
- static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
- {
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
- }
--/* hw_free callback */
- static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)
- {
-       return snd_pcm_lib_free_pages(substream);
- }
--/* prepare callback */
- static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
- {
-       struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -94,9 +94,9 @@ static void audio_vchi_callback(void *pa
-                               void *msg_handle)
- {
-       struct bcm2835_audio_instance *instance = param;
--      int status;
--      int msg_len;
-       struct vc_audio_msg m;
-+      int msg_len;
-+      int status;
-       if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
-               return;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -161,8 +161,8 @@ static int snd_add_child_device(struct d
-                               struct bcm2835_audio_driver *audio_driver,
-                               u32 numchans)
- {
--      struct snd_card *card;
-       struct bcm2835_chip *chip;
-+      struct snd_card *card;
-       int err;
-       err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
-@@ -225,12 +225,12 @@ static int snd_add_child_device(struct d
- static int snd_add_child_devices(struct device *device, u32 numchans)
- {
--      int i;
--      int count_devices = 0;
--      int minchannels = 0;
--      int extrachannels = 0;
-       int extrachannels_per_driver = 0;
-       int extrachannels_remainder = 0;
-+      int count_devices = 0;
-+      int extrachannels = 0;
-+      int minchannels = 0;
-+      int i;
-       for (i = 0; i < ARRAY_SIZE(children_devices); i++)
-               if (*children_devices[i].is_enabled)
-@@ -258,9 +258,9 @@ static int snd_add_child_devices(struct
-               extrachannels_remainder);
-       for (i = 0; i < ARRAY_SIZE(children_devices); i++) {
--              int err;
--              int numchannels_this_device;
-               struct bcm2835_audio_driver *audio_driver;
-+              int numchannels_this_device;
-+              int err;
-               if (!*children_devices[i].is_enabled)
-                       continue;
diff --git a/target/linux/brcm2708/patches-4.19/950-0406-staging-bcm2835-audio-rename-platform_driver-structu.patch b/target/linux/brcm2708/patches-4.19/950-0406-staging-bcm2835-audio-rename-platform_driver-structu.patch
new file mode 100644 (file)
index 0000000..0512802
--- /dev/null
@@ -0,0 +1,47 @@
+From b06f01038711efc5182267cfc68e358a89ee2502 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:55 +0200
+Subject: [PATCH] staging: bcm2835-audio: rename platform_driver
+ structure
+
+commit 82cdc0c6b6faf877e2aecb957cffa9cb578cc572 upstream.
+
+It was called bcm2835_alsa0_driver, that "0" didn't mean much.
+
+Suggested-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -343,7 +343,7 @@ static const struct of_device_id snd_bcm
+ };
+ MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
+-static struct platform_driver bcm2835_alsa0_driver = {
++static struct platform_driver bcm2835_alsa_driver = {
+       .probe = snd_bcm2835_alsa_probe,
+ #ifdef CONFIG_PM
+       .suspend = snd_bcm2835_alsa_suspend,
+@@ -359,7 +359,7 @@ static int bcm2835_alsa_device_init(void
+ {
+       int retval;
+-      retval = platform_driver_register(&bcm2835_alsa0_driver);
++      retval = platform_driver_register(&bcm2835_alsa_driver);
+       if (retval)
+               pr_err("Error registering bcm2835_audio driver %d .\n", retval);
+@@ -368,7 +368,7 @@ static int bcm2835_alsa_device_init(void
+ static void bcm2835_alsa_device_exit(void)
+ {
+-      platform_driver_unregister(&bcm2835_alsa0_driver);
++      platform_driver_unregister(&bcm2835_alsa_driver);
+ }
+ late_initcall(bcm2835_alsa_device_init);
diff --git a/target/linux/brcm2708/patches-4.19/950-0406-staging-bcm2835-audio-use-anonymous-union-in-struct-.patch b/target/linux/brcm2708/patches-4.19/950-0406-staging-bcm2835-audio-use-anonymous-union-in-struct-.patch
deleted file mode 100644 (file)
index e212a94..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-From 23b89436030e64196a1bc317901d08edd54fb772 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:53 +0200
-Subject: [PATCH] staging: bcm2835-audio: use anonymous union in struct
- vc_audio_msg
-
-commit 9c2eaf7da855d314a369d48b9cbf8ac80717a1d0 upstream.
-
-In this case explicitly naming the union doesn't help overall code
-comprehension and clutters it.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c             | 30 +++++++++----------
- .../bcm2835-audio/vc_vchi_audioserv_defs.h    |  2 +-
- 2 files changed, 16 insertions(+), 16 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -104,15 +104,15 @@ static void audio_vchi_callback(void *pa
-       status = vchi_msg_dequeue(instance->vchi_handle,
-                                 &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
-       if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
--              instance->result = m.u.result.success;
-+              instance->result = m.result.success;
-               complete(&instance->msg_avail_comp);
-       } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
--              if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
--                  m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
-+              if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
-+                  m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
-                       dev_err(instance->dev, "invalid cookie\n");
-               else
-                       bcm2835_playback_fifo(instance->alsa_stream,
--                                            m.u.complete.count);
-+                                            m.complete.count);
-       } else {
-               dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
-       }
-@@ -257,11 +257,11 @@ int bcm2835_audio_set_ctls(struct bcm283
-       struct vc_audio_msg m = {};
-       m.type = VC_AUDIO_MSG_TYPE_CONTROL;
--      m.u.control.dest = chip->dest;
-+      m.control.dest = chip->dest;
-       if (!chip->mute)
--              m.u.control.volume = CHIP_MIN_VOLUME;
-+              m.control.volume = CHIP_MIN_VOLUME;
-       else
--              m.u.control.volume = alsa2chip(chip->volume);
-+              m.control.volume = alsa2chip(chip->volume);
-       return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
-@@ -272,9 +272,9 @@ int bcm2835_audio_set_params(struct bcm2
- {
-       struct vc_audio_msg m = {
-                .type = VC_AUDIO_MSG_TYPE_CONFIG,
--               .u.config.channels = channels,
--               .u.config.samplerate = samplerate,
--               .u.config.bps = bps,
-+               .config.channels = channels,
-+               .config.samplerate = samplerate,
-+               .config.bps = bps,
-       };
-       int err;
-@@ -302,7 +302,7 @@ int bcm2835_audio_drain(struct bcm2835_a
- {
-       struct vc_audio_msg m = {
-               .type = VC_AUDIO_MSG_TYPE_STOP,
--              .u.stop.draining = 1,
-+              .stop.draining = 1,
-       };
-       return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
-@@ -330,10 +330,10 @@ int bcm2835_audio_write(struct bcm2835_a
-       struct bcm2835_audio_instance *instance = alsa_stream->instance;
-       struct vc_audio_msg m = {
-               .type = VC_AUDIO_MSG_TYPE_WRITE,
--              .u.write.count = size,
--              .u.write.max_packet = instance->max_packet,
--              .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
--              .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
-+              .write.count = size,
-+              .write.max_packet = instance->max_packet,
-+              .write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
-+              .write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
-       };
-       unsigned int count;
-       int err, status;
---- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-@@ -93,7 +93,7 @@ struct vc_audio_msg {
-               struct vc_audio_write write;
-               struct vc_audio_result result;
-               struct vc_audio_complete complete;
--      } u;
-+      };
- };
- #endif /* _VC_AUDIO_DEFS_H_ */
diff --git a/target/linux/brcm2708/patches-4.19/950-0407-staging-bcm2835-audio-more-generic-probe-function-na.patch b/target/linux/brcm2708/patches-4.19/950-0407-staging-bcm2835-audio-more-generic-probe-function-na.patch
deleted file mode 100644 (file)
index 6b03e1e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From 0b7d959b0d0c18959c66696844a1c9956370ab99 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:54 +0200
-Subject: [PATCH] staging: bcm2835-audio: more generic probe function
- name
-
-commit 96f3bd8ae6516898c7b411ecb87064bb0dd25415 upstream.
-
-There will only be one probe function, there is no use for appendig
-"_dt" the end of the name.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -291,7 +291,7 @@ static int snd_add_child_devices(struct
-       return 0;
- }
--static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
-+static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
- {
-       struct device *dev = &pdev->dev;
-       u32 numchans;
-@@ -344,7 +344,7 @@ static const struct of_device_id snd_bcm
- MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
- static struct platform_driver bcm2835_alsa0_driver = {
--      .probe = snd_bcm2835_alsa_probe_dt,
-+      .probe = snd_bcm2835_alsa_probe,
- #ifdef CONFIG_PM
-       .suspend = snd_bcm2835_alsa_suspend,
-       .resume = snd_bcm2835_alsa_resume,
diff --git a/target/linux/brcm2708/patches-4.19/950-0407-staging-bcm2835-audio-update-TODO.patch b/target/linux/brcm2708/patches-4.19/950-0407-staging-bcm2835-audio-update-TODO.patch
new file mode 100644 (file)
index 0000000..8f24d15
--- /dev/null
@@ -0,0 +1,56 @@
+From 56b704581afbd8d9ccd73cfa7935b6178749a3e9 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:56 +0200
+Subject: [PATCH] staging: bcm2835-audio: update TODO
+
+commit 01ec7398c56e8f1b903ecb3c5c75400e263eef43 upstream.
+
+The following tasks were completed or not the right solution:
+
+1/2- Not the proper solution, we should register a platform device in
+vchiq the same way it's done with bcm2835-camera as commented here:
+https://lkml.org/lkml/2018/10/16/1131
+
+2/3- Fixed by Takashi Iwai here: https://lkml.org/lkml/2018/9/4/587
+
+Also, adds a new task as per mailing list conversation.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../staging/vc04_services/bcm2835-audio/TODO  | 25 +++----------------
+ 1 file changed, 3 insertions(+), 22 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/TODO
++++ b/drivers/staging/vc04_services/bcm2835-audio/TODO
+@@ -4,26 +4,7 @@
+ *                                                                           *
+ *****************************************************************************
++1) Revisit multi-cards options and PCM route mixer control (as per comment
++https://lkml.org/lkml/2018/9/8/200)
+-1) Document the device tree node
+-
+-The downstream tree(the tree that the driver was imported from) at
+-http://www.github.com/raspberrypi/linux uses this node:
+-
+-audio: audio {
+-      compatible = "brcm,bcm2835-audio";
+-      brcm,pwm-channels = <8>;
+-};
+-
+-Since the driver requires the use of VCHIQ, it may be useful to have a link
+-in the device tree to the VCHIQ driver.
+-
+-2) Gracefully handle the case where VCHIQ is missing from the device tree or
+-it has not been initialized yet.
+-
+-3) Review error handling and remove duplicate code.
+-
+-4) Cleanup the logging mechanism.  The driver should probably be using the
+-standard kernel logging mechanisms such as dev_info, dev_dbg, and friends.
+-
+-5) Fix the remaining checkpatch.pl errors and warnings.
++2) Fix the remaining checkpatch.pl errors and warnings.
diff --git a/target/linux/brcm2708/patches-4.19/950-0408-staging-bcm2835-audio-interpolate-audio-delay.patch b/target/linux/brcm2708/patches-4.19/950-0408-staging-bcm2835-audio-interpolate-audio-delay.patch
new file mode 100644 (file)
index 0000000..cf5f11c
--- /dev/null
@@ -0,0 +1,82 @@
+From 2ba82d9516203ce41f33e98adb667bedee3622bc Mon Sep 17 00:00:00 2001
+From: Mike Brady <mikebrady@eircom.net>
+Date: Mon, 22 Oct 2018 20:17:08 +0100
+Subject: [PATCH] staging: bcm2835-audio: interpolate audio delay
+
+commit a105a3a72824e0ac685a0711a67e4dbe29de62d0 upstream.
+
+When the BCM2835 audio output is used, userspace sees a jitter up to 10ms
+in the audio position, aka "delay" -- the number of frames that must
+be output before a new frame would be played.
+Make this a bit nicer for userspace by interpolating the position
+using the CPU clock.
+The overhead is small -- an extra ktime_get() every time a GPU message
+is sent -- and another call and a few calculations whenever the delay
+is sought from userland.
+At 48,000 frames per second, i.e. approximately 20 microseconds per
+frame, it would take a clock inaccuracy of
+20 microseconds in 10 milliseconds -- 2,000 parts per million --
+to result in an inaccurate estimate, whereas
+crystal- or resonator-based clocks typically have an
+inaccuracy of 10s to 100s of parts per million.
+
+Signed-off-by: Mike Brady <mikebrady@eircom.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 20 +++++++++++++++++++
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  1 +
+ 2 files changed, 21 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -74,6 +74,7 @@ void bcm2835_playback_fifo(struct bcm283
+       atomic_set(&alsa_stream->pos, pos);
+       alsa_stream->period_offset += bytes;
++      alsa_stream->interpolate_start = ktime_get();
+       if (alsa_stream->period_offset >= alsa_stream->period_size) {
+               alsa_stream->period_offset %= alsa_stream->period_size;
+               snd_pcm_period_elapsed(substream);
+@@ -237,6 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
+       atomic_set(&alsa_stream->pos, 0);
+       alsa_stream->period_offset = 0;
+       alsa_stream->draining = false;
++      alsa_stream->interpolate_start = ktime_get();
+       return 0;
+ }
+@@ -286,6 +288,24 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
++      ktime_t now = ktime_get();
++
++      /* Give userspace better delay reporting by interpolating between GPU
++       * notifications, assuming audio speed is close enough to the clock
++       * used for ktime
++       */
++
++      if ((ktime_to_ns(alsa_stream->interpolate_start)) &&
++          (ktime_compare(alsa_stream->interpolate_start, now) < 0)) {
++              u64 interval =
++                      (ktime_to_ns(ktime_sub(now,
++                              alsa_stream->interpolate_start)));
++              u64 frames_output_in_interval =
++                      div_u64((interval * runtime->rate), 1000000000);
++              snd_pcm_sframes_t frames_output_in_interval_sized =
++                      -frames_output_in_interval;
++              runtime->delay = frames_output_in_interval_sized;
++      }
+       return snd_pcm_indirect_playback_pointer(substream,
+               &alsa_stream->pcm_indirect,
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -78,6 +78,7 @@ struct bcm2835_alsa_stream {
+       unsigned int period_offset;
+       unsigned int buffer_size;
+       unsigned int period_size;
++      ktime_t interpolate_start;
+       struct bcm2835_audio_instance *instance;
+       int idx;
diff --git a/target/linux/brcm2708/patches-4.19/950-0408-staging-bcm2835-audio-rename-platform_driver-structu.patch b/target/linux/brcm2708/patches-4.19/950-0408-staging-bcm2835-audio-rename-platform_driver-structu.patch
deleted file mode 100644 (file)
index 0512802..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From b06f01038711efc5182267cfc68e358a89ee2502 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:55 +0200
-Subject: [PATCH] staging: bcm2835-audio: rename platform_driver
- structure
-
-commit 82cdc0c6b6faf877e2aecb957cffa9cb578cc572 upstream.
-
-It was called bcm2835_alsa0_driver, that "0" didn't mean much.
-
-Suggested-by: Takashi Iwai <tiwai@suse.de>
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -343,7 +343,7 @@ static const struct of_device_id snd_bcm
- };
- MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
--static struct platform_driver bcm2835_alsa0_driver = {
-+static struct platform_driver bcm2835_alsa_driver = {
-       .probe = snd_bcm2835_alsa_probe,
- #ifdef CONFIG_PM
-       .suspend = snd_bcm2835_alsa_suspend,
-@@ -359,7 +359,7 @@ static int bcm2835_alsa_device_init(void
- {
-       int retval;
--      retval = platform_driver_register(&bcm2835_alsa0_driver);
-+      retval = platform_driver_register(&bcm2835_alsa_driver);
-       if (retval)
-               pr_err("Error registering bcm2835_audio driver %d .\n", retval);
-@@ -368,7 +368,7 @@ static int bcm2835_alsa_device_init(void
- static void bcm2835_alsa_device_exit(void)
- {
--      platform_driver_unregister(&bcm2835_alsa0_driver);
-+      platform_driver_unregister(&bcm2835_alsa_driver);
- }
- late_initcall(bcm2835_alsa_device_init);
diff --git a/target/linux/brcm2708/patches-4.19/950-0409-staging-bcm2835-audio-Enable-compile-test.patch b/target/linux/brcm2708/patches-4.19/950-0409-staging-bcm2835-audio-Enable-compile-test.patch
new file mode 100644 (file)
index 0000000..3605c41
--- /dev/null
@@ -0,0 +1,27 @@
+From b338fbb56955b74b5f41a623aceab4d74ba7c173 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Thu, 6 Dec 2018 19:28:56 +0100
+Subject: [PATCH] staging: bcm2835-audio: Enable compile test
+
+commit 458d4866a34d0c129ffc3bd56345b2166ba46d77 upstream.
+
+Enable the compilation test for bcm2835-audio to gain more build coverage.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/Kconfig
++++ b/drivers/staging/vc04_services/bcm2835-audio/Kconfig
+@@ -1,6 +1,6 @@
+ config SND_BCM2835
+         tristate "BCM2835 Audio"
+-        depends on ARCH_BCM2835 && SND
++        depends on (ARCH_BCM2835 || COMPILE_TEST) && SND
+         select SND_PCM
+         select BCM2835_VCHIQ
+         help
diff --git a/target/linux/brcm2708/patches-4.19/950-0409-staging-bcm2835-audio-update-TODO.patch b/target/linux/brcm2708/patches-4.19/950-0409-staging-bcm2835-audio-update-TODO.patch
deleted file mode 100644 (file)
index 8f24d15..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 56b704581afbd8d9ccd73cfa7935b6178749a3e9 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:56 +0200
-Subject: [PATCH] staging: bcm2835-audio: update TODO
-
-commit 01ec7398c56e8f1b903ecb3c5c75400e263eef43 upstream.
-
-The following tasks were completed or not the right solution:
-
-1/2- Not the proper solution, we should register a platform device in
-vchiq the same way it's done with bcm2835-camera as commented here:
-https://lkml.org/lkml/2018/10/16/1131
-
-2/3- Fixed by Takashi Iwai here: https://lkml.org/lkml/2018/9/4/587
-
-Also, adds a new task as per mailing list conversation.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../staging/vc04_services/bcm2835-audio/TODO  | 25 +++----------------
- 1 file changed, 3 insertions(+), 22 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/TODO
-+++ b/drivers/staging/vc04_services/bcm2835-audio/TODO
-@@ -4,26 +4,7 @@
- *                                                                           *
- *****************************************************************************
-+1) Revisit multi-cards options and PCM route mixer control (as per comment
-+https://lkml.org/lkml/2018/9/8/200)
--1) Document the device tree node
--
--The downstream tree(the tree that the driver was imported from) at
--http://www.github.com/raspberrypi/linux uses this node:
--
--audio: audio {
--      compatible = "brcm,bcm2835-audio";
--      brcm,pwm-channels = <8>;
--};
--
--Since the driver requires the use of VCHIQ, it may be useful to have a link
--in the device tree to the VCHIQ driver.
--
--2) Gracefully handle the case where VCHIQ is missing from the device tree or
--it has not been initialized yet.
--
--3) Review error handling and remove duplicate code.
--
--4) Cleanup the logging mechanism.  The driver should probably be using the
--standard kernel logging mechanisms such as dev_info, dev_dbg, and friends.
--
--5) Fix the remaining checkpatch.pl errors and warnings.
-+2) Fix the remaining checkpatch.pl errors and warnings.
diff --git a/target/linux/brcm2708/patches-4.19/950-0410-staging-bcm2835-audio-interpolate-audio-delay.patch b/target/linux/brcm2708/patches-4.19/950-0410-staging-bcm2835-audio-interpolate-audio-delay.patch
deleted file mode 100644 (file)
index cf5f11c..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-From 2ba82d9516203ce41f33e98adb667bedee3622bc Mon Sep 17 00:00:00 2001
-From: Mike Brady <mikebrady@eircom.net>
-Date: Mon, 22 Oct 2018 20:17:08 +0100
-Subject: [PATCH] staging: bcm2835-audio: interpolate audio delay
-
-commit a105a3a72824e0ac685a0711a67e4dbe29de62d0 upstream.
-
-When the BCM2835 audio output is used, userspace sees a jitter up to 10ms
-in the audio position, aka "delay" -- the number of frames that must
-be output before a new frame would be played.
-Make this a bit nicer for userspace by interpolating the position
-using the CPU clock.
-The overhead is small -- an extra ktime_get() every time a GPU message
-is sent -- and another call and a few calculations whenever the delay
-is sought from userland.
-At 48,000 frames per second, i.e. approximately 20 microseconds per
-frame, it would take a clock inaccuracy of
-20 microseconds in 10 milliseconds -- 2,000 parts per million --
-to result in an inaccurate estimate, whereas
-crystal- or resonator-based clocks typically have an
-inaccuracy of 10s to 100s of parts per million.
-
-Signed-off-by: Mike Brady <mikebrady@eircom.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 20 +++++++++++++++++++
- .../vc04_services/bcm2835-audio/bcm2835.h     |  1 +
- 2 files changed, 21 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -74,6 +74,7 @@ void bcm2835_playback_fifo(struct bcm283
-       atomic_set(&alsa_stream->pos, pos);
-       alsa_stream->period_offset += bytes;
-+      alsa_stream->interpolate_start = ktime_get();
-       if (alsa_stream->period_offset >= alsa_stream->period_size) {
-               alsa_stream->period_offset %= alsa_stream->period_size;
-               snd_pcm_period_elapsed(substream);
-@@ -237,6 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
-       atomic_set(&alsa_stream->pos, 0);
-       alsa_stream->period_offset = 0;
-       alsa_stream->draining = false;
-+      alsa_stream->interpolate_start = ktime_get();
-       return 0;
- }
-@@ -286,6 +288,24 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
- {
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-+      ktime_t now = ktime_get();
-+
-+      /* Give userspace better delay reporting by interpolating between GPU
-+       * notifications, assuming audio speed is close enough to the clock
-+       * used for ktime
-+       */
-+
-+      if ((ktime_to_ns(alsa_stream->interpolate_start)) &&
-+          (ktime_compare(alsa_stream->interpolate_start, now) < 0)) {
-+              u64 interval =
-+                      (ktime_to_ns(ktime_sub(now,
-+                              alsa_stream->interpolate_start)));
-+              u64 frames_output_in_interval =
-+                      div_u64((interval * runtime->rate), 1000000000);
-+              snd_pcm_sframes_t frames_output_in_interval_sized =
-+                      -frames_output_in_interval;
-+              runtime->delay = frames_output_in_interval_sized;
-+      }
-       return snd_pcm_indirect_playback_pointer(substream,
-               &alsa_stream->pcm_indirect,
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -78,6 +78,7 @@ struct bcm2835_alsa_stream {
-       unsigned int period_offset;
-       unsigned int buffer_size;
-       unsigned int period_size;
-+      ktime_t interpolate_start;
-       struct bcm2835_audio_instance *instance;
-       int idx;
diff --git a/target/linux/brcm2708/patches-4.19/950-0410-staging-bcm2835-audio-use-module_platform_driver-mac.patch b/target/linux/brcm2708/patches-4.19/950-0410-staging-bcm2835-audio-use-module_platform_driver-mac.patch
new file mode 100644 (file)
index 0000000..a0a5f76
--- /dev/null
@@ -0,0 +1,48 @@
+From 72c059360457babd76009697e652c96cb282856e Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Thu, 6 Dec 2018 19:28:57 +0100
+Subject: [PATCH] staging: bcm2835-audio: use module_platform_driver()
+ macro
+
+commit 1e55d56344b0777d6cee9b9e4a813d53728ee798 upstream.
+
+There is not much value behind this boilerplate, so use
+module_platform_driver() instead.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c     | 20 +------------------
+ 1 file changed, 1 insertion(+), 19 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -354,25 +354,7 @@ static struct platform_driver bcm2835_al
+               .of_match_table = snd_bcm2835_of_match_table,
+       },
+ };
+-
+-static int bcm2835_alsa_device_init(void)
+-{
+-      int retval;
+-
+-      retval = platform_driver_register(&bcm2835_alsa_driver);
+-      if (retval)
+-              pr_err("Error registering bcm2835_audio driver %d .\n", retval);
+-
+-      return retval;
+-}
+-
+-static void bcm2835_alsa_device_exit(void)
+-{
+-      platform_driver_unregister(&bcm2835_alsa_driver);
+-}
+-
+-late_initcall(bcm2835_alsa_device_init);
+-module_exit(bcm2835_alsa_device_exit);
++module_platform_driver(bcm2835_alsa_driver);
+ MODULE_AUTHOR("Dom Cobley");
+ MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
diff --git a/target/linux/brcm2708/patches-4.19/950-0411-staging-bcm2835-audio-Enable-compile-test.patch b/target/linux/brcm2708/patches-4.19/950-0411-staging-bcm2835-audio-Enable-compile-test.patch
deleted file mode 100644 (file)
index 3605c41..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From b338fbb56955b74b5f41a623aceab4d74ba7c173 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Thu, 6 Dec 2018 19:28:56 +0100
-Subject: [PATCH] staging: bcm2835-audio: Enable compile test
-
-commit 458d4866a34d0c129ffc3bd56345b2166ba46d77 upstream.
-
-Enable the compilation test for bcm2835-audio to gain more build coverage.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/Kconfig
-+++ b/drivers/staging/vc04_services/bcm2835-audio/Kconfig
-@@ -1,6 +1,6 @@
- config SND_BCM2835
-         tristate "BCM2835 Audio"
--        depends on ARCH_BCM2835 && SND
-+        depends on (ARCH_BCM2835 || COMPILE_TEST) && SND
-         select SND_PCM
-         select BCM2835_VCHIQ
-         help
diff --git a/target/linux/brcm2708/patches-4.19/950-0411-staging-bcm2835-audio-double-free-in-init-error-path.patch b/target/linux/brcm2708/patches-4.19/950-0411-staging-bcm2835-audio-double-free-in-init-error-path.patch
new file mode 100644 (file)
index 0000000..95b9d7a
--- /dev/null
@@ -0,0 +1,30 @@
+From 360a1982333c8e8f583663155479115d6eb7cd14 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 17 Dec 2018 10:08:54 +0300
+Subject: [PATCH] staging: bcm2835-audio: double free in init error
+ path
+
+commit 136ff5e49271c4c8fceeca5491c48e66b961564b upstream.
+
+We free instance here and in the caller.  It should be only the caller
+which handles it.
+
+Fixes: d7ca3a71545b ("staging: bcm2835-audio: Operate non-atomic PCM ops")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -145,7 +145,6 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+               dev_err(instance->dev,
+                       "failed to open VCHI service connection (status=%d)\n",
+                       status);
+-              kfree(instance);
+               return -EPERM;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0412-dts-Increase-default-coherent-pool-size.patch b/target/linux/brcm2708/patches-4.19/950-0412-dts-Increase-default-coherent-pool-size.patch
new file mode 100644 (file)
index 0000000..e39aeb0
--- /dev/null
@@ -0,0 +1,27 @@
+From e13c663bfc75a628ba25afdf3f3b4a40a2c0250e Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 1 May 2019 15:00:05 +0100
+Subject: [PATCH] dts: Increase default coherent pool size
+
+dwc_otg allocates DMA-coherent buffers in atomic context for misaligned
+transfer buffers. The pool that these allocations come from is set up
+at boot-time but can be overridden by a commandline parameter -
+increase this for now to prevent failures seen on 4.19 with multiple
+USB Ethernet devices.
+
+see: https://github.com/raspberrypi/linux/issues/2924
+---
+ arch/arm/boot/dts/bcm270x.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -3,7 +3,7 @@
+ / {
+       chosen {
+-              bootargs = "";
++              bootargs = "coherent_pool=1M";
+               /delete-property/ stdout-path;
+       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0412-staging-bcm2835-audio-use-module_platform_driver-mac.patch b/target/linux/brcm2708/patches-4.19/950-0412-staging-bcm2835-audio-use-module_platform_driver-mac.patch
deleted file mode 100644 (file)
index a0a5f76..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 72c059360457babd76009697e652c96cb282856e Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Thu, 6 Dec 2018 19:28:57 +0100
-Subject: [PATCH] staging: bcm2835-audio: use module_platform_driver()
- macro
-
-commit 1e55d56344b0777d6cee9b9e4a813d53728ee798 upstream.
-
-There is not much value behind this boilerplate, so use
-module_platform_driver() instead.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835.c     | 20 +------------------
- 1 file changed, 1 insertion(+), 19 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -354,25 +354,7 @@ static struct platform_driver bcm2835_al
-               .of_match_table = snd_bcm2835_of_match_table,
-       },
- };
--
--static int bcm2835_alsa_device_init(void)
--{
--      int retval;
--
--      retval = platform_driver_register(&bcm2835_alsa_driver);
--      if (retval)
--              pr_err("Error registering bcm2835_audio driver %d .\n", retval);
--
--      return retval;
--}
--
--static void bcm2835_alsa_device_exit(void)
--{
--      platform_driver_unregister(&bcm2835_alsa_driver);
--}
--
--late_initcall(bcm2835_alsa_device_init);
--module_exit(bcm2835_alsa_device_exit);
-+module_platform_driver(bcm2835_alsa_driver);
- MODULE_AUTHOR("Dom Cobley");
- MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
diff --git a/target/linux/brcm2708/patches-4.19/950-0413-lan78xx-use-default-alignment-for-rx-buffers.patch b/target/linux/brcm2708/patches-4.19/950-0413-lan78xx-use-default-alignment-for-rx-buffers.patch
new file mode 100644 (file)
index 0000000..6b93888
--- /dev/null
@@ -0,0 +1,23 @@
+From fdbe849f960ee92befd781cff14d9b76142b0981 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Thu, 2 May 2019 11:53:45 +0100
+Subject: [PATCH] lan78xx: use default alignment for rx buffers
+
+The lan78xx uses a 12-byte hardware rx header, so there is no need
+to allocate SKBs with NET_IP_ALIGN set. Removes alignment faults
+in both dwc_otg and in ipv6 processing.
+---
+ drivers/net/usb/lan78xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -3257,7 +3257,7 @@ static int rx_submit(struct lan78xx_net
+       size_t size = dev->rx_urb_size;
+       int ret = 0;
+-      skb = netdev_alloc_skb_ip_align(dev->net, size);
++      skb = netdev_alloc_skb(dev->net, size);
+       if (!skb) {
+               usb_free_urb(urb);
+               return -ENOMEM;
diff --git a/target/linux/brcm2708/patches-4.19/950-0413-staging-bcm2835-audio-double-free-in-init-error-path.patch b/target/linux/brcm2708/patches-4.19/950-0413-staging-bcm2835-audio-double-free-in-init-error-path.patch
deleted file mode 100644 (file)
index 95b9d7a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 360a1982333c8e8f583663155479115d6eb7cd14 Mon Sep 17 00:00:00 2001
-From: Dan Carpenter <dan.carpenter@oracle.com>
-Date: Mon, 17 Dec 2018 10:08:54 +0300
-Subject: [PATCH] staging: bcm2835-audio: double free in init error
- path
-
-commit 136ff5e49271c4c8fceeca5491c48e66b961564b upstream.
-
-We free instance here and in the caller.  It should be only the caller
-which handles it.
-
-Fixes: d7ca3a71545b ("staging: bcm2835-audio: Operate non-atomic PCM ops")
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Cc: stable <stable@vger.kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -145,7 +145,6 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
-               dev_err(instance->dev,
-                       "failed to open VCHI service connection (status=%d)\n",
-                       status);
--              kfree(instance);
-               return -EPERM;
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0414-dts-Increase-default-coherent-pool-size.patch b/target/linux/brcm2708/patches-4.19/950-0414-dts-Increase-default-coherent-pool-size.patch
deleted file mode 100644 (file)
index e39aeb0..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From e13c663bfc75a628ba25afdf3f3b4a40a2c0250e Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Wed, 1 May 2019 15:00:05 +0100
-Subject: [PATCH] dts: Increase default coherent pool size
-
-dwc_otg allocates DMA-coherent buffers in atomic context for misaligned
-transfer buffers. The pool that these allocations come from is set up
-at boot-time but can be overridden by a commandline parameter -
-increase this for now to prevent failures seen on 4.19 with multiple
-USB Ethernet devices.
-
-see: https://github.com/raspberrypi/linux/issues/2924
----
- arch/arm/boot/dts/bcm270x.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -3,7 +3,7 @@
- / {
-       chosen {
--              bootargs = "";
-+              bootargs = "coherent_pool=1M";
-               /delete-property/ stdout-path;
-       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0414-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch b/target/linux/brcm2708/patches-4.19/950-0414-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch
new file mode 100644 (file)
index 0000000..9e25fe1
--- /dev/null
@@ -0,0 +1,29 @@
+From 453caa19909edf2de1add80b369fb30570a440ed Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 2 May 2019 14:30:24 +0100
+Subject: [PATCH] staging: bcm2835-codec: Correct port width calc for
+ truncation
+
+The calculation converting from V4L2 bytesperline to MMAL
+width had an operator ordering issue that lead to Bayer raw 10
+(and 12 and 14) setting an incorrect stride for the buffer.
+Correct this operation ordering issue.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../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
+@@ -605,8 +605,8 @@ static void setup_mmal_port_format(struc
+       if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
+               /* Raw image format - set width/height */
+-              port->es.video.width = q_data->bytesperline /
+-                                              (q_data->fmt->depth >> 3);
++              port->es.video.width = (q_data->bytesperline << 3) /
++                                              q_data->fmt->depth;
+               port->es.video.height = q_data->height;
+               port->es.video.crop.width = q_data->crop_width;
+               port->es.video.crop.height = q_data->crop_height;
diff --git a/target/linux/brcm2708/patches-4.19/950-0415-lan78xx-use-default-alignment-for-rx-buffers.patch b/target/linux/brcm2708/patches-4.19/950-0415-lan78xx-use-default-alignment-for-rx-buffers.patch
deleted file mode 100644 (file)
index 6b93888..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From fdbe849f960ee92befd781cff14d9b76142b0981 Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Thu, 2 May 2019 11:53:45 +0100
-Subject: [PATCH] lan78xx: use default alignment for rx buffers
-
-The lan78xx uses a 12-byte hardware rx header, so there is no need
-to allocate SKBs with NET_IP_ALIGN set. Removes alignment faults
-in both dwc_otg and in ipv6 processing.
----
- drivers/net/usb/lan78xx.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -3257,7 +3257,7 @@ static int rx_submit(struct lan78xx_net
-       size_t size = dev->rx_urb_size;
-       int ret = 0;
--      skb = netdev_alloc_skb_ip_align(dev->net, size);
-+      skb = netdev_alloc_skb(dev->net, size);
-       if (!skb) {
-               usb_free_urb(urb);
-               return -ENOMEM;
diff --git a/target/linux/brcm2708/patches-4.19/950-0415-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch b/target/linux/brcm2708/patches-4.19/950-0415-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch
new file mode 100644 (file)
index 0000000..6f99736
--- /dev/null
@@ -0,0 +1,61 @@
+From 52e50b0f5017e823428849c42c1029306d790939 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 2 May 2019 14:32:21 +0100
+Subject: [PATCH] staging: bcm2835-codec: Remove height padding for ISP
+ role
+
+The ISP has no need for heights to be a multiple of macroblock
+sizes, therefore doesn't require the align on the height.
+Remove it for the ISP role. (It is required for the codecs).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c              | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1015,7 +1015,8 @@ static int vidioc_g_fmt_vid_cap(struct f
+       return vidioc_g_fmt(file2ctx(file), f);
+ }
+-static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
++static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
++                        struct bcm2835_codec_fmt *fmt)
+ {
+       /*
+        * The V4L2 specification requires the driver to correct the format
+@@ -1034,11 +1035,13 @@ static int vidioc_try_fmt(struct v4l2_fo
+                       f->fmt.pix.height = MIN_H;
+               /*
+-               * Buffer must have a vertical alignment of 16 lines.
++               * For codecs the buffer must have a vertical alignment of 16
++               * lines.
+                * The selection will reflect any cropping rectangle when only
+                * some of the pixels are active.
+                */
+-              f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
++              if (ctx->dev->role != ISP)
++                      f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
+       }
+       f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
+                                                  fmt);
+@@ -1065,7 +1068,7 @@ static int vidioc_try_fmt_vid_cap(struct
+               fmt = find_format(f, ctx->dev, true);
+       }
+-      return vidioc_try_fmt(f, fmt);
++      return vidioc_try_fmt(ctx, f, fmt);
+ }
+ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
+@@ -1084,7 +1087,7 @@ static int vidioc_try_fmt_vid_out(struct
+       if (!f->fmt.pix.colorspace)
+               f->fmt.pix.colorspace = ctx->colorspace;
+-      return vidioc_try_fmt(f, fmt);
++      return vidioc_try_fmt(ctx, f, fmt);
+ }
+ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
diff --git a/target/linux/brcm2708/patches-4.19/950-0416-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch b/target/linux/brcm2708/patches-4.19/950-0416-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch
deleted file mode 100644 (file)
index 9e25fe1..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 453caa19909edf2de1add80b369fb30570a440ed Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 2 May 2019 14:30:24 +0100
-Subject: [PATCH] staging: bcm2835-codec: Correct port width calc for
- truncation
-
-The calculation converting from V4L2 bytesperline to MMAL
-width had an operator ordering issue that lead to Bayer raw 10
-(and 12 and 14) setting an incorrect stride for the buffer.
-Correct this operation ordering issue.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../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
-@@ -605,8 +605,8 @@ static void setup_mmal_port_format(struc
-       if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
-               /* Raw image format - set width/height */
--              port->es.video.width = q_data->bytesperline /
--                                              (q_data->fmt->depth >> 3);
-+              port->es.video.width = (q_data->bytesperline << 3) /
-+                                              q_data->fmt->depth;
-               port->es.video.height = q_data->height;
-               port->es.video.crop.width = q_data->crop_width;
-               port->es.video.crop.height = q_data->crop_height;
diff --git a/target/linux/brcm2708/patches-4.19/950-0416-staging-mmal-vchiq-Free-the-event-context-for-contro.patch b/target/linux/brcm2708/patches-4.19/950-0416-staging-mmal-vchiq-Free-the-event-context-for-contro.patch
new file mode 100644 (file)
index 0000000..edd4c78
--- /dev/null
@@ -0,0 +1,28 @@
+From 6737574b4d3af54a56d2f9c49f516fb75d06a556 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 1 May 2019 13:27:23 +0100
+Subject: [PATCH] staging: mmal-vchiq: Free the event context for
+ control ports
+
+vchiq_mmal_component_init calls init_event_context for the
+control port, but vchiq_mmal_component_finalise didn't free
+it, causing a memory leak..
+
+Add the free call.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1982,6 +1982,8 @@ int vchiq_mmal_component_finalise(struct
+       for (idx = 0; idx < component->clocks; idx++)
+               free_event_context(&component->clock[idx]);
++      free_event_context(&component->control);
++
+       mutex_unlock(&instance->vchiq_mutex);
+       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0417-BCM270X_DT-Also-set-coherent_pool-1M-for-BT-Pis.patch b/target/linux/brcm2708/patches-4.19/950-0417-BCM270X_DT-Also-set-coherent_pool-1M-for-BT-Pis.patch
new file mode 100644 (file)
index 0000000..6b67955
--- /dev/null
@@ -0,0 +1,47 @@
+From f9c0f8057ffee5c039fe20c3e2dcd7fea70222e9 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 2 May 2019 22:14:34 +0100
+Subject: [PATCH] BCM270X_DT: Also set coherent_pool=1M for BT Pis
+
+See: https://github.com/raspberrypi/linux/issues/2924
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi-0-w.dts      | 2 +-
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 2 +-
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts      | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
+@@ -8,7 +8,7 @@
+       model = "Raspberry Pi Zero W";
+       chosen {
+-              bootargs = "8250.nr_uarts=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+       };
+       aliases {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -9,7 +9,7 @@
+       model = "Raspberry Pi 3 Model B+";
+       chosen {
+-              bootargs = "8250.nr_uarts=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+       };
+       aliases {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -9,7 +9,7 @@
+       model = "Raspberry Pi 3 Model B";
+       chosen {
+-              bootargs = "8250.nr_uarts=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+       };
+       aliases {
diff --git a/target/linux/brcm2708/patches-4.19/950-0417-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch b/target/linux/brcm2708/patches-4.19/950-0417-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch
deleted file mode 100644 (file)
index 6f99736..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From 52e50b0f5017e823428849c42c1029306d790939 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 2 May 2019 14:32:21 +0100
-Subject: [PATCH] staging: bcm2835-codec: Remove height padding for ISP
- role
-
-The ISP has no need for heights to be a multiple of macroblock
-sizes, therefore doesn't require the align on the height.
-Remove it for the ISP role. (It is required for the codecs).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c              | 13 ++++++++-----
- 1 file changed, 8 insertions(+), 5 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1015,7 +1015,8 @@ static int vidioc_g_fmt_vid_cap(struct f
-       return vidioc_g_fmt(file2ctx(file), f);
- }
--static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
-+static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
-+                        struct bcm2835_codec_fmt *fmt)
- {
-       /*
-        * The V4L2 specification requires the driver to correct the format
-@@ -1034,11 +1035,13 @@ static int vidioc_try_fmt(struct v4l2_fo
-                       f->fmt.pix.height = MIN_H;
-               /*
--               * Buffer must have a vertical alignment of 16 lines.
-+               * For codecs the buffer must have a vertical alignment of 16
-+               * lines.
-                * The selection will reflect any cropping rectangle when only
-                * some of the pixels are active.
-                */
--              f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
-+              if (ctx->dev->role != ISP)
-+                      f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
-       }
-       f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
-                                                  fmt);
-@@ -1065,7 +1068,7 @@ static int vidioc_try_fmt_vid_cap(struct
-               fmt = find_format(f, ctx->dev, true);
-       }
--      return vidioc_try_fmt(f, fmt);
-+      return vidioc_try_fmt(ctx, f, fmt);
- }
- static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
-@@ -1084,7 +1087,7 @@ static int vidioc_try_fmt_vid_out(struct
-       if (!f->fmt.pix.colorspace)
-               f->fmt.pix.colorspace = ctx->colorspace;
--      return vidioc_try_fmt(f, fmt);
-+      return vidioc_try_fmt(ctx, f, fmt);
- }
- static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
diff --git a/target/linux/brcm2708/patches-4.19/950-0418-arm-dts-overlays-rpi-sense-add-upstream-humidity-com.patch b/target/linux/brcm2708/patches-4.19/950-0418-arm-dts-overlays-rpi-sense-add-upstream-humidity-com.patch
new file mode 100644 (file)
index 0000000..568cd82
--- /dev/null
@@ -0,0 +1,26 @@
+From 50d3f15ea5d6ca2705a009722dd7d4108c9f75d9 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Sun, 5 May 2019 21:07:12 +0100
+Subject: [PATCH] arm: dts: overlays: rpi-sense: add upstream humidity
+ compatible
+
+The upstream humidiity driver uses "st,hts221" for the compatible
+string so add that in as well so it will work with an unmodified
+upstream kernel driver. We leave the downstream as the priority.
+
+Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
+---
+ arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
+@@ -38,7 +38,7 @@
+                       };
+                       hts221-humid@5f {
+-                              compatible = "st,hts221-humid";
++                              compatible = "st,hts221-humid", "st,hts221";
+                               reg = <0x5f>;
+                               status = "okay";
+                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0418-staging-mmal-vchiq-Free-the-event-context-for-contro.patch b/target/linux/brcm2708/patches-4.19/950-0418-staging-mmal-vchiq-Free-the-event-context-for-contro.patch
deleted file mode 100644 (file)
index edd4c78..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 6737574b4d3af54a56d2f9c49f516fb75d06a556 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 1 May 2019 13:27:23 +0100
-Subject: [PATCH] staging: mmal-vchiq: Free the event context for
- control ports
-
-vchiq_mmal_component_init calls init_event_context for the
-control port, but vchiq_mmal_component_finalise didn't free
-it, causing a memory leak..
-
-Add the free call.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1982,6 +1982,8 @@ int vchiq_mmal_component_finalise(struct
-       for (idx = 0; idx < component->clocks; idx++)
-               free_event_context(&component->clock[idx]);
-+      free_event_context(&component->control);
-+
-       mutex_unlock(&instance->vchiq_mutex);
-       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0419-BCM270X_DT-Also-set-coherent_pool-1M-for-BT-Pis.patch b/target/linux/brcm2708/patches-4.19/950-0419-BCM270X_DT-Also-set-coherent_pool-1M-for-BT-Pis.patch
deleted file mode 100644 (file)
index 6b67955..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From f9c0f8057ffee5c039fe20c3e2dcd7fea70222e9 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 2 May 2019 22:14:34 +0100
-Subject: [PATCH] BCM270X_DT: Also set coherent_pool=1M for BT Pis
-
-See: https://github.com/raspberrypi/linux/issues/2924
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi-0-w.dts      | 2 +-
- arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 2 +-
- arch/arm/boot/dts/bcm2710-rpi-3-b.dts      | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-@@ -8,7 +8,7 @@
-       model = "Raspberry Pi Zero W";
-       chosen {
--              bootargs = "8250.nr_uarts=1";
-+              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
-       };
-       aliases {
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-@@ -9,7 +9,7 @@
-       model = "Raspberry Pi 3 Model B+";
-       chosen {
--              bootargs = "8250.nr_uarts=1";
-+              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
-       };
-       aliases {
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-@@ -9,7 +9,7 @@
-       model = "Raspberry Pi 3 Model B";
-       chosen {
--              bootargs = "8250.nr_uarts=1";
-+              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
-       };
-       aliases {
diff --git a/target/linux/brcm2708/patches-4.19/950-0419-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch b/target/linux/brcm2708/patches-4.19/950-0419-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch
new file mode 100644 (file)
index 0000000..bfa88dd
--- /dev/null
@@ -0,0 +1,67 @@
+From 250db0df9643d122e00313313102c642f1adac72 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 2 May 2019 15:50:01 +0100
+Subject: [PATCH] staging: mmal-vchiq: Fix memory leak in error path
+
+On error, vchiq_mmal_component_init could leave the
+event context allocated for ports.
+Clean them up in the error path.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 27 +++++++++++++------
+ 1 file changed, 19 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1848,9 +1848,26 @@ static void free_event_context(struct vc
+ {
+       struct mmal_msg_context *ctx = port->event_context;
++      if (!ctx)
++              return;
++
+       kfree(ctx->u.bulk.buffer->buffer);
+       kfree(ctx->u.bulk.buffer);
+       release_msg_context(ctx);
++      port->event_context = NULL;
++}
++
++static void release_all_event_contexts(struct vchiq_mmal_component *component)
++{
++      int idx;
++
++      for (idx = 0; idx < component->inputs; idx++)
++              free_event_context(&component->input[idx]);
++      for (idx = 0; idx < component->outputs; idx++)
++              free_event_context(&component->output[idx]);
++      for (idx = 0; idx < component->clocks; idx++)
++              free_event_context(&component->clock[idx]);
++      free_event_context(&component->control);
+ }
+ /* Initialise a mmal component and its ports
+@@ -1948,6 +1965,7 @@ int vchiq_mmal_component_init(struct vch
+ release_component:
+       destroy_component(instance, component);
++      release_all_event_contexts(component);
+ unlock:
+       if (component)
+               component->in_use = 0;
+@@ -1975,14 +1993,7 @@ int vchiq_mmal_component_finalise(struct
+       component->in_use = 0;
+-      for (idx = 0; idx < component->inputs; idx++)
+-              free_event_context(&component->input[idx]);
+-      for (idx = 0; idx < component->outputs; idx++)
+-              free_event_context(&component->output[idx]);
+-      for (idx = 0; idx < component->clocks; idx++)
+-              free_event_context(&component->clock[idx]);
+-
+-      free_event_context(&component->control);
++      release_all_event_contexts(component);
+       mutex_unlock(&instance->vchiq_mutex);
diff --git a/target/linux/brcm2708/patches-4.19/950-0420-arm-dts-overlays-rpi-sense-add-upstream-humidity-com.patch b/target/linux/brcm2708/patches-4.19/950-0420-arm-dts-overlays-rpi-sense-add-upstream-humidity-com.patch
deleted file mode 100644 (file)
index 568cd82..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 50d3f15ea5d6ca2705a009722dd7d4108c9f75d9 Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Sun, 5 May 2019 21:07:12 +0100
-Subject: [PATCH] arm: dts: overlays: rpi-sense: add upstream humidity
- compatible
-
-The upstream humidiity driver uses "st,hts221" for the compatible
-string so add that in as well so it will work with an unmodified
-upstream kernel driver. We leave the downstream as the priority.
-
-Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
----
- arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-@@ -38,7 +38,7 @@
-                       };
-                       hts221-humid@5f {
--                              compatible = "st,hts221-humid";
-+                              compatible = "st,hts221-humid", "st,hts221";
-                               reg = <0x5f>;
-                               status = "okay";
-                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0420-staging-vchiq-mmal-Fix-memory-leak-of-vchiq-instance.patch b/target/linux/brcm2708/patches-4.19/950-0420-staging-vchiq-mmal-Fix-memory-leak-of-vchiq-instance.patch
new file mode 100644 (file)
index 0000000..f761ad7
--- /dev/null
@@ -0,0 +1,62 @@
+From 3e246d402582c6f19e5e636f89952d11e18e6442 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 3 May 2019 13:27:51 +0100
+Subject: [PATCH] staging: vchiq-mmal: Fix memory leak of vchiq
+ instance
+
+The vchiq instance was allocated from vchiq_mmal_init via
+vchi_initialise, but was never released with vchi_disconnect.
+
+Retain the handle and release it from vchiq_mmal_finalise.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -176,6 +176,7 @@ struct mmal_msg_context {
+ };
+ struct vchiq_mmal_instance {
++      VCHI_INSTANCE_T vchi_instance;
+       VCHI_SERVICE_HANDLE_T handle;
+       /* ensure serialised access to service */
+@@ -1981,7 +1982,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
+ int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
+                                 struct vchiq_mmal_component *component)
+ {
+-      int ret, idx;
++      int ret;
+       if (mutex_lock_interruptible(&instance->vchiq_mutex))
+               return -EINTR;
+@@ -2094,6 +2095,8 @@ int vchiq_mmal_finalise(struct vchiq_mma
+       idr_destroy(&instance->context_map);
++      vchi_disconnect(instance->vchi_instance);
++
+       kfree(instance);
+       return status;
+@@ -2105,7 +2108,7 @@ int vchiq_mmal_init(struct vchiq_mmal_in
+       int status;
+       struct vchiq_mmal_instance *instance;
+       static VCHI_CONNECTION_T *vchi_connection;
+-      static VCHI_INSTANCE_T vchi_instance;
++      VCHI_INSTANCE_T vchi_instance;
+       SERVICE_CREATION_T params = {
+               .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
+               .service_id             = VC_MMAL_SERVER_NAME,
+@@ -2151,6 +2154,8 @@ int vchiq_mmal_init(struct vchiq_mmal_in
+       if (!instance)
+               return -ENOMEM;
++      instance->vchi_instance = vchi_instance;
++
+       mutex_init(&instance->vchiq_mutex);
+       instance->bulk_scratch = vmalloc(PAGE_SIZE);
diff --git a/target/linux/brcm2708/patches-4.19/950-0421-Added-IQaudIO-Pi-Codec-board-support-2969.patch b/target/linux/brcm2708/patches-4.19/950-0421-Added-IQaudIO-Pi-Codec-board-support-2969.patch
new file mode 100644 (file)
index 0000000..b063e38
--- /dev/null
@@ -0,0 +1,376 @@
+From 930c49de8674acda0f143f7bc182ed2fad8c4f9d Mon Sep 17 00:00:00 2001
+From: IQaudIO <gordon@iqaudio.com>
+Date: Mon, 13 May 2019 21:53:05 +0100
+Subject: [PATCH] Added IQaudIO Pi-Codec board support (#2969)
+
+Add support for the IQaudIO Pi-Codec board.
+
+Signed-off-by: Gordon <gordon@iqaudio.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   6 +
+ .../dts/overlays/iqaudio-codec-overlay.dts    |  42 +++
+ sound/soc/bcm/Kconfig                         |   7 +
+ sound/soc/bcm/Makefile                        |   2 +
+ sound/soc/bcm/iqaudio-codec.c                 | 250 ++++++++++++++++++
+ 9 files changed, 311 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
+ create mode 100644 sound/soc/bcm/iqaudio-codec.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -68,6 +68,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       i2c1-bcm2708.dtbo \
+       i2s-gpio28-31.dtbo \
+       ilitek251x.dtbo \
++      iqaudio-codec.dtbo \
+       iqaudio-dac.dtbo \
+       iqaudio-dacplus.dtbo \
+       iqaudio-digi-wm8804-audio.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1160,6 +1160,12 @@ Params: interrupt               GPIO use
+                                 touchscreen (in pixels)
++Name:   iqaudio-codec
++Info:   Configures the IQaudio Codec audio card
++Load:   dtoverlay=iqaudio-codec
++Params: <None>
++
++
+ Name:   iqaudio-dac
+ Info:   Configures the IQaudio DAC audio card
+ Load:   dtoverlay=iqaudio-dac,<param>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
+@@ -0,0 +1,42 @@
++// Definitions for IQaudIO CODEC
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2708";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      da2713@1a {
++                              #sound-dai-cells = <0>;
++                              compatible = "dlg,da7213";
++                              reg = <0x1a>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&sound>;
++              iqaudio_dac: __overlay__ {
++                      compatible = "iqaudio,iqaudio-codec";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++
++      __overrides__ {
++      };
++};
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -108,6 +108,13 @@ config SND_BCM2708_SOC_JUSTBOOM_DIGI
+       help
+         Say Y or M if you want to add support for JustBoom Digi.
++config SND_BCM2708_SOC_IQAUDIO_CODEC
++      tristate "Support for IQaudIO-CODEC"
++      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++      select SND_SOC_DA7213
++      help
++        Say Y or M if you want to add support for IQaudIO-CODEC.
++
+ config SND_BCM2708_SOC_IQAUDIO_DAC
+       tristate "Support for IQaudIO-DAC"
+       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -18,6 +18,7 @@ snd-soc-hifiberry-dacplusadc-objs := hif
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
++snd-soc-iqaudio-codec-objs := iqaudio-codec.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
+  snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
+  obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
+--- /dev/null
++++ b/sound/soc/bcm/iqaudio-codec.c
+@@ -0,0 +1,250 @@
++/*
++ * ASoC Driver for IQaudIO Raspberry Pi Codec board
++ *
++ * Author:    Gordon Garrity <gordon@iqaudio.com>
++ *            (C) Copyright IQaudio Limited, 2017-2019
++ *
++ * 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/gpio/consumer.h>
++#include <linux/platform_device.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#include <linux/acpi.h>
++#include <linux/slab.h>
++#include "../codecs/da7213.h"
++
++static int pll_out = DA7213_PLL_FREQ_OUT_90316800;
++
++static int snd_rpi_iqaudio_pll_control(struct snd_soc_dapm_widget *w,
++                                     struct snd_kcontrol *k, int  event)
++{
++      int ret = 0;
++      struct snd_soc_dapm_context *dapm = w->dapm;
++      struct snd_soc_card *card = dapm->card;
++      struct snd_soc_pcm_runtime *rtd =
++              snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
++      struct snd_soc_dai *codec_dai = rtd->codec_dai;
++
++      if (SND_SOC_DAPM_EVENT_OFF(event)) {
++              ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_MCLK, 0,
++                                        0);
++              if (ret)
++                      dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
++      } else if (SND_SOC_DAPM_EVENT_ON(event)) {
++              ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
++                                        pll_out);
++              if (ret)
++                      dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
++      }
++
++      return ret;
++}
++
++static int snd_rpi_iqaudio_post_dapm_event(struct snd_soc_dapm_widget *w,
++                              struct snd_kcontrol *kcontrol,
++                              int event)
++{
++     switch (event) {
++     case SND_SOC_DAPM_POST_PMU:
++           /* Delay for mic bias ramp */
++           msleep(1000);
++           break;
++     default:
++           break;
++     }
++
++     return 0;
++}
++
++static const struct snd_soc_dapm_widget dapm_widgets[] = {
++      SND_SOC_DAPM_HP("HP Jack", NULL),
++      SND_SOC_DAPM_MIC("MIC Jack", NULL),
++      SND_SOC_DAPM_MIC("Onboard MIC", NULL),
++      SND_SOC_DAPM_LINE("AUX Jack", NULL),
++      SND_SOC_DAPM_SUPPLY("PLL Control", SND_SOC_NOPM, 0, 0,
++                          snd_rpi_iqaudio_pll_control,
++                          SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
++      SND_SOC_DAPM_POST("Post Power Up Event", snd_rpi_iqaudio_post_dapm_event),
++};
++
++static const struct snd_soc_dapm_route audio_map[] = {
++      {"HP Jack", NULL, "HPL"},
++      {"HP Jack", NULL, "HPR"},
++      {"HP Jack", NULL, "PLL Control"},
++
++      {"AUX Jack", NULL, "AUXR"},
++      {"AUX Jack", NULL, "AUXL"},
++      {"AUX Jack", NULL, "PLL Control"},
++
++      /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
++      {"MIC Jack", NULL, "MIC1"},
++      {"MIC Jack", NULL, "PLL Control"},
++      {"Onboard MIC", NULL, "MIC2"},
++      {"Onboard MIC", NULL, "PLL Control"},
++};
++
++/* machine stream operations */
++
++static int snd_rpi_iqaudio_codec_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_dai *codec_dai = rtd->codec_dai;
++      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++      int ret;
++
++      /* Set bclk ratio to align with codec's BCLK rate */
++      ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
++      if (ret) {
++              dev_err(rtd->dev, "Failed to set CPU BLCK ratio\n");
++              return ret;
++      }
++
++      /* Set MCLK frequency to codec, onboard 11.2896MHz clock */
++      return snd_soc_dai_set_sysclk(codec_dai, DA7213_CLKSRC_MCLK, 11289600,
++                                    SND_SOC_CLOCK_OUT);
++}
++
++static int snd_rpi_iqaudio_codec_hw_params(struct snd_pcm_substream *substream,
++                                         struct snd_pcm_hw_params *params)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      unsigned int samplerate = params_rate(params);
++
++      switch (samplerate) {
++      case  8000:
++      case 16000:
++      case 32000:
++      case 48000:
++      case 96000:
++              pll_out = DA7213_PLL_FREQ_OUT_98304000;
++              return 0;
++      case 44100:
++      case 88200:
++              pll_out = DA7213_PLL_FREQ_OUT_90316800;
++              return 0;
++      default:
++              dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate);
++              return -EINVAL;
++      }
++}
++
++static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = {
++      .hw_params = snd_rpi_iqaudio_codec_hw_params,
++};
++
++
++static struct snd_soc_dai_link snd_rpi_iqaudio_codec_dai[] = {
++{
++      .cpu_dai_name           = "bcm2708-i2s.0",
++      .codec_dai_name         = "da7213-hifi",
++      .platform_name          = "bmc2708-i2s.0",
++      .codec_name             = "da7213.1-001a",
++      .dai_fmt                = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++                                SND_SOC_DAIFMT_CBM_CFM,
++      .init                   = snd_rpi_iqaudio_codec_init,
++      .ops                    = &snd_rpi_iqaudio_codec_ops,
++      .symmetric_rates        = 1,
++      .symmetric_channels     = 1,
++      .symmetric_samplebits   = 1,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_iqaudio_codec = {
++      .owner                  = THIS_MODULE,
++      .dai_link               = snd_rpi_iqaudio_codec_dai,
++      .num_links              = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
++      .dapm_widgets           = dapm_widgets,
++      .num_dapm_widgets       = ARRAY_SIZE(dapm_widgets),
++      .dapm_routes            = audio_map,
++      .num_dapm_routes        = ARRAY_SIZE(audio_map),
++};
++
++static int snd_rpi_iqaudio_codec_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++
++      snd_rpi_iqaudio_codec.dev = &pdev->dev;
++
++      if (pdev->dev.of_node) {
++              struct device_node *i2s_node;
++              struct snd_soc_card *card = &snd_rpi_iqaudio_codec;
++              struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_codec_dai[0];
++
++              i2s_node = of_parse_phandle(pdev->dev.of_node,
++                                          "i2s-controller", 0);
++              if (i2s_node) {
++                      dai->cpu_dai_name = NULL;
++                      dai->cpu_of_node = i2s_node;
++                      dai->platform_name = NULL;
++                      dai->platform_of_node = i2s_node;
++              }
++
++              if (of_property_read_string(pdev->dev.of_node, "card_name",
++                                          &card->name))
++                      card->name = "IQaudIOCODEC";
++
++              if (of_property_read_string(pdev->dev.of_node, "dai_name",
++                                          &dai->name))
++                      dai->name = "IQaudIO CODEC";
++
++              if (of_property_read_string(pdev->dev.of_node,
++                                      "dai_stream_name", &dai->stream_name))
++                      dai->stream_name = "IQaudIO CODEC HiFi v1.1";
++
++      }
++
++      ret = snd_soc_register_card(&snd_rpi_iqaudio_codec);
++      if (ret) {
++              if (ret != -EPROBE_DEFER)
++                      dev_err(&pdev->dev,
++                              "snd_soc_register_card() failed: %d\n", ret);
++              return ret;
++      }
++
++      return 0;
++}
++
++static int snd_rpi_iqaudio_codec_remove(struct platform_device *pdev)
++{
++      return snd_soc_unregister_card(&snd_rpi_iqaudio_codec);
++}
++
++static const struct of_device_id iqaudio_of_match[] = {
++      { .compatible = "iqaudio,iqaudio-codec", },
++      {},
++};
++
++MODULE_DEVICE_TABLE(of, iqaudio_of_match);
++
++static struct platform_driver snd_rpi_iqaudio_codec_driver = {
++      .driver = {
++              .name   = "snd-rpi-iqaudio-codec",
++              .owner  = THIS_MODULE,
++              .of_match_table = iqaudio_of_match,
++      },
++      .probe          = snd_rpi_iqaudio_codec_probe,
++      .remove         = snd_rpi_iqaudio_codec_remove,
++};
++
++
++
++module_platform_driver(snd_rpi_iqaudio_codec_driver);
++
++MODULE_AUTHOR("Gordon Garrity <gordon@iqaudio.com>");
++MODULE_DESCRIPTION("ASoC Driver for IQaudIO CODEC");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0421-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch b/target/linux/brcm2708/patches-4.19/950-0421-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch
deleted file mode 100644 (file)
index bfa88dd..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From 250db0df9643d122e00313313102c642f1adac72 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 2 May 2019 15:50:01 +0100
-Subject: [PATCH] staging: mmal-vchiq: Fix memory leak in error path
-
-On error, vchiq_mmal_component_init could leave the
-event context allocated for ports.
-Clean them up in the error path.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-vchiq.c     | 27 +++++++++++++------
- 1 file changed, 19 insertions(+), 8 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1848,9 +1848,26 @@ static void free_event_context(struct vc
- {
-       struct mmal_msg_context *ctx = port->event_context;
-+      if (!ctx)
-+              return;
-+
-       kfree(ctx->u.bulk.buffer->buffer);
-       kfree(ctx->u.bulk.buffer);
-       release_msg_context(ctx);
-+      port->event_context = NULL;
-+}
-+
-+static void release_all_event_contexts(struct vchiq_mmal_component *component)
-+{
-+      int idx;
-+
-+      for (idx = 0; idx < component->inputs; idx++)
-+              free_event_context(&component->input[idx]);
-+      for (idx = 0; idx < component->outputs; idx++)
-+              free_event_context(&component->output[idx]);
-+      for (idx = 0; idx < component->clocks; idx++)
-+              free_event_context(&component->clock[idx]);
-+      free_event_context(&component->control);
- }
- /* Initialise a mmal component and its ports
-@@ -1948,6 +1965,7 @@ int vchiq_mmal_component_init(struct vch
- release_component:
-       destroy_component(instance, component);
-+      release_all_event_contexts(component);
- unlock:
-       if (component)
-               component->in_use = 0;
-@@ -1975,14 +1993,7 @@ int vchiq_mmal_component_finalise(struct
-       component->in_use = 0;
--      for (idx = 0; idx < component->inputs; idx++)
--              free_event_context(&component->input[idx]);
--      for (idx = 0; idx < component->outputs; idx++)
--              free_event_context(&component->output[idx]);
--      for (idx = 0; idx < component->clocks; idx++)
--              free_event_context(&component->clock[idx]);
--
--      free_event_context(&component->control);
-+      release_all_event_contexts(component);
-       mutex_unlock(&instance->vchiq_mutex);
diff --git a/target/linux/brcm2708/patches-4.19/950-0422-staging-vchiq-mmal-Fix-memory-leak-of-vchiq-instance.patch b/target/linux/brcm2708/patches-4.19/950-0422-staging-vchiq-mmal-Fix-memory-leak-of-vchiq-instance.patch
deleted file mode 100644 (file)
index f761ad7..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-From 3e246d402582c6f19e5e636f89952d11e18e6442 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 3 May 2019 13:27:51 +0100
-Subject: [PATCH] staging: vchiq-mmal: Fix memory leak of vchiq
- instance
-
-The vchiq instance was allocated from vchiq_mmal_init via
-vchi_initialise, but was never released with vchi_disconnect.
-
-Retain the handle and release it from vchiq_mmal_finalise.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -176,6 +176,7 @@ struct mmal_msg_context {
- };
- struct vchiq_mmal_instance {
-+      VCHI_INSTANCE_T vchi_instance;
-       VCHI_SERVICE_HANDLE_T handle;
-       /* ensure serialised access to service */
-@@ -1981,7 +1982,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
- int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
-                                 struct vchiq_mmal_component *component)
- {
--      int ret, idx;
-+      int ret;
-       if (mutex_lock_interruptible(&instance->vchiq_mutex))
-               return -EINTR;
-@@ -2094,6 +2095,8 @@ int vchiq_mmal_finalise(struct vchiq_mma
-       idr_destroy(&instance->context_map);
-+      vchi_disconnect(instance->vchi_instance);
-+
-       kfree(instance);
-       return status;
-@@ -2105,7 +2108,7 @@ int vchiq_mmal_init(struct vchiq_mmal_in
-       int status;
-       struct vchiq_mmal_instance *instance;
-       static VCHI_CONNECTION_T *vchi_connection;
--      static VCHI_INSTANCE_T vchi_instance;
-+      VCHI_INSTANCE_T vchi_instance;
-       SERVICE_CREATION_T params = {
-               .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
-               .service_id             = VC_MMAL_SERVER_NAME,
-@@ -2151,6 +2154,8 @@ int vchiq_mmal_init(struct vchiq_mmal_in
-       if (!instance)
-               return -ENOMEM;
-+      instance->vchi_instance = vchi_instance;
-+
-       mutex_init(&instance->vchiq_mutex);
-       instance->bulk_scratch = vmalloc(PAGE_SIZE);
diff --git a/target/linux/brcm2708/patches-4.19/950-0422-w1-ds2408-reset-on-output_write-retry-with-readback.patch b/target/linux/brcm2708/patches-4.19/950-0422-w1-ds2408-reset-on-output_write-retry-with-readback.patch
new file mode 100644 (file)
index 0000000..afdc22e
--- /dev/null
@@ -0,0 +1,140 @@
+From 714580d7c11f81afb5e08c71f79a03a1ed4ae44e Mon Sep 17 00:00:00 2001
+From: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
+Date: Thu, 28 Mar 2019 12:41:11 -0400
+Subject: [PATCH] w1: ds2408: reset on output_write retry with readback
+
+commit 49695ac46861180baf2b2b92c62da8619b6bf28f upstream.
+
+When we have success in 'Channel Access Write' but reading back latch
+states fails, a write is retried without doing a proper slave reset.
+This leads to protocol errors as the slave treats the next 'Channel
+Access Write' as the continuation of previous command.
+
+This commit is fixing this by making sure if the retry loop re-runs, a
+reset is performed, whatever the failure (CONFIRM_BYTE or the read
+back).
+
+The loop was quite due for a cleanup and this change mandated it. By
+isolating the CONFIG_W1_SLAVE_DS2408_READBACK case into it's own
+function, we vastly reduce the visual and branching(runtime and
+compile-time) noise.
+
+Reported-by: Mariusz Bialonczyk <manio@skyboo.net>
+Tested-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2408.c | 76 ++++++++++++++++++-----------------
+ 1 file changed, 39 insertions(+), 37 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2408.c
++++ b/drivers/w1/slaves/w1_ds2408.c
+@@ -138,14 +138,37 @@ static ssize_t status_control_read(struc
+               W1_F29_REG_CONTROL_AND_STATUS, buf);
+ }
++#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
++static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
++{
++      u8 w1_buf[3];
++
++      if (w1_reset_resume_command(sl->master))
++              return false;
++
++      w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
++      w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
++      w1_buf[2] = 0;
++
++      w1_write_block(sl->master, w1_buf, 3);
++
++      return (w1_read_8(sl->master) == expected);
++}
++#else
++static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
++{
++      return true;
++}
++#endif
++
+ static ssize_t output_write(struct file *filp, struct kobject *kobj,
+                           struct bin_attribute *bin_attr, char *buf,
+                           loff_t off, size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       u8 w1_buf[3];
+-      u8 readBack;
+       unsigned int retries = W1_F29_RETRIES;
++      ssize_t bytes_written = -EIO;
+       if (count != 1 || off != 0)
+               return -EFAULT;
+@@ -155,54 +178,33 @@ static ssize_t output_write(struct file
+       dev_dbg(&sl->dev, "mutex locked");
+       if (w1_reset_select_slave(sl))
+-              goto error;
++              goto out;
+-      while (retries--) {
++      do {
+               w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
+               w1_buf[1] = *buf;
+               w1_buf[2] = ~(*buf);
+-              w1_write_block(sl->master, w1_buf, 3);
+-              readBack = w1_read_8(sl->master);
++              w1_write_block(sl->master, w1_buf, 3);
+-              if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
+-                      if (w1_reset_resume_command(sl->master))
+-                              goto error;
+-                      /* try again, the slave is ready for a command */
+-                      continue;
++              if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
++                  optional_read_back_valid(sl, *buf)) {
++                      bytes_written = 1;
++                      goto out;
+               }
+-#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
+-              /* here the master could read another byte which
+-                 would be the PIO reg (the actual pin logic state)
+-                 since in this driver we don't know which pins are
+-                 in and outs, there's no value to read the state and
+-                 compare. with (*buf) so end this command abruptly: */
+               if (w1_reset_resume_command(sl->master))
+-                      goto error;
++                      goto out; /* unrecoverable error */
++              /* try again, the slave is ready for a command */
++      } while (--retries);
+-              /* go read back the output latches */
+-              /* (the direct effect of the write above) */
+-              w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
+-              w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
+-              w1_buf[2] = 0;
+-              w1_write_block(sl->master, w1_buf, 3);
+-              /* read the result of the READ_PIO_REGS command */
+-              if (w1_read_8(sl->master) == *buf)
+-#endif
+-              {
+-                      /* success! */
+-                      mutex_unlock(&sl->master->bus_mutex);
+-                      dev_dbg(&sl->dev,
+-                              "mutex unlocked, retries:%d", retries);
+-                      return 1;
+-              }
+-      }
+-error:
++out:
+       mutex_unlock(&sl->master->bus_mutex);
+-      dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
+-      return -EIO;
++      dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
++              (bytes_written > 0) ? "succeeded" : "error", retries);
++
++      return bytes_written;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0423-Added-IQaudIO-Pi-Codec-board-support-2969.patch b/target/linux/brcm2708/patches-4.19/950-0423-Added-IQaudIO-Pi-Codec-board-support-2969.patch
deleted file mode 100644 (file)
index b063e38..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-From 930c49de8674acda0f143f7bc182ed2fad8c4f9d Mon Sep 17 00:00:00 2001
-From: IQaudIO <gordon@iqaudio.com>
-Date: Mon, 13 May 2019 21:53:05 +0100
-Subject: [PATCH] Added IQaudIO Pi-Codec board support (#2969)
-
-Add support for the IQaudIO Pi-Codec board.
-
-Signed-off-by: Gordon <gordon@iqaudio.com>
----
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |   6 +
- .../dts/overlays/iqaudio-codec-overlay.dts    |  42 +++
- sound/soc/bcm/Kconfig                         |   7 +
- sound/soc/bcm/Makefile                        |   2 +
- sound/soc/bcm/iqaudio-codec.c                 | 250 ++++++++++++++++++
- 9 files changed, 311 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
- create mode 100644 sound/soc/bcm/iqaudio-codec.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -68,6 +68,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       i2c1-bcm2708.dtbo \
-       i2s-gpio28-31.dtbo \
-       ilitek251x.dtbo \
-+      iqaudio-codec.dtbo \
-       iqaudio-dac.dtbo \
-       iqaudio-dacplus.dtbo \
-       iqaudio-digi-wm8804-audio.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1160,6 +1160,12 @@ Params: interrupt               GPIO use
-                                 touchscreen (in pixels)
-+Name:   iqaudio-codec
-+Info:   Configures the IQaudio Codec audio card
-+Load:   dtoverlay=iqaudio-codec
-+Params: <None>
-+
-+
- Name:   iqaudio-dac
- Info:   Configures the IQaudio DAC audio card
- Load:   dtoverlay=iqaudio-dac,<param>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
-@@ -0,0 +1,42 @@
-+// Definitions for IQaudIO CODEC
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2708";
-+
-+      fragment@0 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      da2713@1a {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "dlg,da7213";
-+                              reg = <0x1a>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&sound>;
-+              iqaudio_dac: __overlay__ {
-+                      compatible = "iqaudio,iqaudio-codec";
-+                      i2s-controller = <&i2s>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      __overrides__ {
-+      };
-+};
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -108,6 +108,13 @@ config SND_BCM2708_SOC_JUSTBOOM_DIGI
-       help
-         Say Y or M if you want to add support for JustBoom Digi.
-+config SND_BCM2708_SOC_IQAUDIO_CODEC
-+      tristate "Support for IQaudIO-CODEC"
-+      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+      select SND_SOC_DA7213
-+      help
-+        Say Y or M if you want to add support for IQaudIO-CODEC.
-+
- config SND_BCM2708_SOC_IQAUDIO_DAC
-       tristate "Support for IQaudIO-DAC"
-       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -18,6 +18,7 @@ snd-soc-hifiberry-dacplusadc-objs := hif
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
-+snd-soc-iqaudio-codec-objs := iqaudio-codec.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
-  snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
-@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
-+obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
-  obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
---- /dev/null
-+++ b/sound/soc/bcm/iqaudio-codec.c
-@@ -0,0 +1,250 @@
-+/*
-+ * ASoC Driver for IQaudIO Raspberry Pi Codec board
-+ *
-+ * Author:    Gordon Garrity <gordon@iqaudio.com>
-+ *            (C) Copyright IQaudio Limited, 2017-2019
-+ *
-+ * 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/gpio/consumer.h>
-+#include <linux/platform_device.h>
-+
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+
-+#include <linux/acpi.h>
-+#include <linux/slab.h>
-+#include "../codecs/da7213.h"
-+
-+static int pll_out = DA7213_PLL_FREQ_OUT_90316800;
-+
-+static int snd_rpi_iqaudio_pll_control(struct snd_soc_dapm_widget *w,
-+                                     struct snd_kcontrol *k, int  event)
-+{
-+      int ret = 0;
-+      struct snd_soc_dapm_context *dapm = w->dapm;
-+      struct snd_soc_card *card = dapm->card;
-+      struct snd_soc_pcm_runtime *rtd =
-+              snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
-+      struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+
-+      if (SND_SOC_DAPM_EVENT_OFF(event)) {
-+              ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_MCLK, 0,
-+                                        0);
-+              if (ret)
-+                      dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
-+      } else if (SND_SOC_DAPM_EVENT_ON(event)) {
-+              ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
-+                                        pll_out);
-+              if (ret)
-+                      dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
-+      }
-+
-+      return ret;
-+}
-+
-+static int snd_rpi_iqaudio_post_dapm_event(struct snd_soc_dapm_widget *w,
-+                              struct snd_kcontrol *kcontrol,
-+                              int event)
-+{
-+     switch (event) {
-+     case SND_SOC_DAPM_POST_PMU:
-+           /* Delay for mic bias ramp */
-+           msleep(1000);
-+           break;
-+     default:
-+           break;
-+     }
-+
-+     return 0;
-+}
-+
-+static const struct snd_soc_dapm_widget dapm_widgets[] = {
-+      SND_SOC_DAPM_HP("HP Jack", NULL),
-+      SND_SOC_DAPM_MIC("MIC Jack", NULL),
-+      SND_SOC_DAPM_MIC("Onboard MIC", NULL),
-+      SND_SOC_DAPM_LINE("AUX Jack", NULL),
-+      SND_SOC_DAPM_SUPPLY("PLL Control", SND_SOC_NOPM, 0, 0,
-+                          snd_rpi_iqaudio_pll_control,
-+                          SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-+      SND_SOC_DAPM_POST("Post Power Up Event", snd_rpi_iqaudio_post_dapm_event),
-+};
-+
-+static const struct snd_soc_dapm_route audio_map[] = {
-+      {"HP Jack", NULL, "HPL"},
-+      {"HP Jack", NULL, "HPR"},
-+      {"HP Jack", NULL, "PLL Control"},
-+
-+      {"AUX Jack", NULL, "AUXR"},
-+      {"AUX Jack", NULL, "AUXL"},
-+      {"AUX Jack", NULL, "PLL Control"},
-+
-+      /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
-+      {"MIC Jack", NULL, "MIC1"},
-+      {"MIC Jack", NULL, "PLL Control"},
-+      {"Onboard MIC", NULL, "MIC2"},
-+      {"Onboard MIC", NULL, "PLL Control"},
-+};
-+
-+/* machine stream operations */
-+
-+static int snd_rpi_iqaudio_codec_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-+      int ret;
-+
-+      /* Set bclk ratio to align with codec's BCLK rate */
-+      ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
-+      if (ret) {
-+              dev_err(rtd->dev, "Failed to set CPU BLCK ratio\n");
-+              return ret;
-+      }
-+
-+      /* Set MCLK frequency to codec, onboard 11.2896MHz clock */
-+      return snd_soc_dai_set_sysclk(codec_dai, DA7213_CLKSRC_MCLK, 11289600,
-+                                    SND_SOC_CLOCK_OUT);
-+}
-+
-+static int snd_rpi_iqaudio_codec_hw_params(struct snd_pcm_substream *substream,
-+                                         struct snd_pcm_hw_params *params)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      unsigned int samplerate = params_rate(params);
-+
-+      switch (samplerate) {
-+      case  8000:
-+      case 16000:
-+      case 32000:
-+      case 48000:
-+      case 96000:
-+              pll_out = DA7213_PLL_FREQ_OUT_98304000;
-+              return 0;
-+      case 44100:
-+      case 88200:
-+              pll_out = DA7213_PLL_FREQ_OUT_90316800;
-+              return 0;
-+      default:
-+              dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate);
-+              return -EINVAL;
-+      }
-+}
-+
-+static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = {
-+      .hw_params = snd_rpi_iqaudio_codec_hw_params,
-+};
-+
-+
-+static struct snd_soc_dai_link snd_rpi_iqaudio_codec_dai[] = {
-+{
-+      .cpu_dai_name           = "bcm2708-i2s.0",
-+      .codec_dai_name         = "da7213-hifi",
-+      .platform_name          = "bmc2708-i2s.0",
-+      .codec_name             = "da7213.1-001a",
-+      .dai_fmt                = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+                                SND_SOC_DAIFMT_CBM_CFM,
-+      .init                   = snd_rpi_iqaudio_codec_init,
-+      .ops                    = &snd_rpi_iqaudio_codec_ops,
-+      .symmetric_rates        = 1,
-+      .symmetric_channels     = 1,
-+      .symmetric_samplebits   = 1,
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_iqaudio_codec = {
-+      .owner                  = THIS_MODULE,
-+      .dai_link               = snd_rpi_iqaudio_codec_dai,
-+      .num_links              = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
-+      .dapm_widgets           = dapm_widgets,
-+      .num_dapm_widgets       = ARRAY_SIZE(dapm_widgets),
-+      .dapm_routes            = audio_map,
-+      .num_dapm_routes        = ARRAY_SIZE(audio_map),
-+};
-+
-+static int snd_rpi_iqaudio_codec_probe(struct platform_device *pdev)
-+{
-+      int ret = 0;
-+
-+      snd_rpi_iqaudio_codec.dev = &pdev->dev;
-+
-+      if (pdev->dev.of_node) {
-+              struct device_node *i2s_node;
-+              struct snd_soc_card *card = &snd_rpi_iqaudio_codec;
-+              struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_codec_dai[0];
-+
-+              i2s_node = of_parse_phandle(pdev->dev.of_node,
-+                                          "i2s-controller", 0);
-+              if (i2s_node) {
-+                      dai->cpu_dai_name = NULL;
-+                      dai->cpu_of_node = i2s_node;
-+                      dai->platform_name = NULL;
-+                      dai->platform_of_node = i2s_node;
-+              }
-+
-+              if (of_property_read_string(pdev->dev.of_node, "card_name",
-+                                          &card->name))
-+                      card->name = "IQaudIOCODEC";
-+
-+              if (of_property_read_string(pdev->dev.of_node, "dai_name",
-+                                          &dai->name))
-+                      dai->name = "IQaudIO CODEC";
-+
-+              if (of_property_read_string(pdev->dev.of_node,
-+                                      "dai_stream_name", &dai->stream_name))
-+                      dai->stream_name = "IQaudIO CODEC HiFi v1.1";
-+
-+      }
-+
-+      ret = snd_soc_register_card(&snd_rpi_iqaudio_codec);
-+      if (ret) {
-+              if (ret != -EPROBE_DEFER)
-+                      dev_err(&pdev->dev,
-+                              "snd_soc_register_card() failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int snd_rpi_iqaudio_codec_remove(struct platform_device *pdev)
-+{
-+      return snd_soc_unregister_card(&snd_rpi_iqaudio_codec);
-+}
-+
-+static const struct of_device_id iqaudio_of_match[] = {
-+      { .compatible = "iqaudio,iqaudio-codec", },
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, iqaudio_of_match);
-+
-+static struct platform_driver snd_rpi_iqaudio_codec_driver = {
-+      .driver = {
-+              .name   = "snd-rpi-iqaudio-codec",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = iqaudio_of_match,
-+      },
-+      .probe          = snd_rpi_iqaudio_codec_probe,
-+      .remove         = snd_rpi_iqaudio_codec_remove,
-+};
-+
-+
-+
-+module_platform_driver(snd_rpi_iqaudio_codec_driver);
-+
-+MODULE_AUTHOR("Gordon Garrity <gordon@iqaudio.com>");
-+MODULE_DESCRIPTION("ASoC Driver for IQaudIO CODEC");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0423-w1-ds2482-cosmetic-fixes-after-54865314f5a1.patch b/target/linux/brcm2708/patches-4.19/950-0423-w1-ds2482-cosmetic-fixes-after-54865314f5a1.patch
new file mode 100644 (file)
index 0000000..3766707
--- /dev/null
@@ -0,0 +1,91 @@
+From 2bf6a79fb6555b5ebf21d03b1295e017804474c4 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 4 Mar 2019 12:23:36 +0100
+Subject: [PATCH] w1: ds2482: cosmetic fixes after 54865314f5a1
+
+commit 5cb27d30fc3a281e830a2099d520b469e2b82008 upstream.
+
+We have a helper function ds2482_calculate_config() which is calculating
+the config value, so just use it instead of passing the same variable
+in all calls to this function.
+
+Also fixes the placement of module parameters to match with:
+50fa2951bd74 (w1: Organize driver source to natural/common order)
+by Andrew F. Davis
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Cc: Andrew Worsley <amworsley@gmail.com>
+Cc: Andrew F. Davis <afd@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/masters/ds2482.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/w1/masters/ds2482.c
++++ b/drivers/w1/masters/ds2482.c
+@@ -37,6 +37,11 @@ module_param_named(active_pullup, ds2482
+ MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \
+                               "0-disable, 1-enable (default)");
++/* extra configurations - e.g. 1WS */
++static int extra_config;
++module_param(extra_config, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
++
+ /**
+  * The DS2482 registers - there are 3 registers that are addressed by a read
+  * pointer. The read pointer is set by the last command executed.
+@@ -70,8 +75,6 @@ MODULE_PARM_DESC(active_pullup, "Active
+ #define DS2482_REG_CFG_PPM            0x02    /* presence pulse masking */
+ #define DS2482_REG_CFG_APU            0x01    /* active pull-up */
+-/* extra configurations - e.g. 1WS */
+-static int extra_config;
+ /**
+  * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only).
+@@ -130,6 +133,8 @@ struct ds2482_data {
+  */
+ static inline u8 ds2482_calculate_config(u8 conf)
+ {
++      conf |= extra_config;
++
+       if (ds2482_active_pullup)
+               conf |= DS2482_REG_CFG_APU;
+@@ -405,7 +410,7 @@ static u8 ds2482_w1_reset_bus(void *data
+               /* If the chip did reset since detect, re-config it */
+               if (err & DS2482_REG_STS_RST)
+                       ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
+-                                      ds2482_calculate_config(extra_config));
++                                           ds2482_calculate_config(0x00));
+       }
+       mutex_unlock(&pdev->access_lock);
+@@ -431,7 +436,8 @@ static u8 ds2482_w1_set_pullup(void *dat
+               ds2482_wait_1wire_idle(pdev);
+               /* note: it seems like both SPU and APU have to be set! */
+               retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
+-                      ds2482_calculate_config(extra_config|DS2482_REG_CFG_SPU|DS2482_REG_CFG_APU));
++                      ds2482_calculate_config(DS2482_REG_CFG_SPU |
++                                              DS2482_REG_CFG_APU));
+               ds2482_wait_1wire_idle(pdev);
+       }
+@@ -484,7 +490,7 @@ static int ds2482_probe(struct i2c_clien
+       /* Set all config items to 0 (off) */
+       ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG,
+-              ds2482_calculate_config(extra_config));
++              ds2482_calculate_config(0x00));
+       mutex_init(&data->access_lock);
+@@ -559,7 +565,5 @@ module_i2c_driver(ds2482_driver);
+ MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+ MODULE_DESCRIPTION("DS2482 driver");
+-module_param(extra_config, int, S_IRUGO | S_IWUSR);
+-MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
+ MODULE_LICENSE("GPL");
diff --git a/target/linux/brcm2708/patches-4.19/950-0424-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch b/target/linux/brcm2708/patches-4.19/950-0424-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch
new file mode 100644 (file)
index 0000000..346cda8
--- /dev/null
@@ -0,0 +1,21 @@
+From 2c1e36e477550ea66824433c132fdff03b4ee020 Mon Sep 17 00:00:00 2001
+From: Klaus Schulz <klsschlz@gmail.com>
+Date: Thu, 16 May 2019 13:35:32 +0200
+Subject: [PATCH] sound: pcm512x-codec: Adding 352.8kHz samplerate
+ support
+
+---
+ sound/soc/codecs/pcm512x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/pcm512x.c
++++ b/sound/soc/codecs/pcm512x.c
+@@ -542,7 +542,7 @@ static unsigned long pcm512x_ncp_target(
+ static const u32 pcm512x_dai_rates[] = {
+       8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+-      88200, 96000, 176400, 192000, 384000,
++      88200, 96000, 176400, 192000, 352800, 384000,
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_slave = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0424-w1-ds2408-reset-on-output_write-retry-with-readback.patch b/target/linux/brcm2708/patches-4.19/950-0424-w1-ds2408-reset-on-output_write-retry-with-readback.patch
deleted file mode 100644 (file)
index afdc22e..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-From 714580d7c11f81afb5e08c71f79a03a1ed4ae44e Mon Sep 17 00:00:00 2001
-From: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
-Date: Thu, 28 Mar 2019 12:41:11 -0400
-Subject: [PATCH] w1: ds2408: reset on output_write retry with readback
-
-commit 49695ac46861180baf2b2b92c62da8619b6bf28f upstream.
-
-When we have success in 'Channel Access Write' but reading back latch
-states fails, a write is retried without doing a proper slave reset.
-This leads to protocol errors as the slave treats the next 'Channel
-Access Write' as the continuation of previous command.
-
-This commit is fixing this by making sure if the retry loop re-runs, a
-reset is performed, whatever the failure (CONFIRM_BYTE or the read
-back).
-
-The loop was quite due for a cleanup and this change mandated it. By
-isolating the CONFIG_W1_SLAVE_DS2408_READBACK case into it's own
-function, we vastly reduce the visual and branching(runtime and
-compile-time) noise.
-
-Reported-by: Mariusz Bialonczyk <manio@skyboo.net>
-Tested-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2408.c | 76 ++++++++++++++++++-----------------
- 1 file changed, 39 insertions(+), 37 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2408.c
-+++ b/drivers/w1/slaves/w1_ds2408.c
-@@ -138,14 +138,37 @@ static ssize_t status_control_read(struc
-               W1_F29_REG_CONTROL_AND_STATUS, buf);
- }
-+#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
-+static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
-+{
-+      u8 w1_buf[3];
-+
-+      if (w1_reset_resume_command(sl->master))
-+              return false;
-+
-+      w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
-+      w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
-+      w1_buf[2] = 0;
-+
-+      w1_write_block(sl->master, w1_buf, 3);
-+
-+      return (w1_read_8(sl->master) == expected);
-+}
-+#else
-+static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
-+{
-+      return true;
-+}
-+#endif
-+
- static ssize_t output_write(struct file *filp, struct kobject *kobj,
-                           struct bin_attribute *bin_attr, char *buf,
-                           loff_t off, size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-       u8 w1_buf[3];
--      u8 readBack;
-       unsigned int retries = W1_F29_RETRIES;
-+      ssize_t bytes_written = -EIO;
-       if (count != 1 || off != 0)
-               return -EFAULT;
-@@ -155,54 +178,33 @@ static ssize_t output_write(struct file
-       dev_dbg(&sl->dev, "mutex locked");
-       if (w1_reset_select_slave(sl))
--              goto error;
-+              goto out;
--      while (retries--) {
-+      do {
-               w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
-               w1_buf[1] = *buf;
-               w1_buf[2] = ~(*buf);
--              w1_write_block(sl->master, w1_buf, 3);
--              readBack = w1_read_8(sl->master);
-+              w1_write_block(sl->master, w1_buf, 3);
--              if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
--                      if (w1_reset_resume_command(sl->master))
--                              goto error;
--                      /* try again, the slave is ready for a command */
--                      continue;
-+              if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
-+                  optional_read_back_valid(sl, *buf)) {
-+                      bytes_written = 1;
-+                      goto out;
-               }
--#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
--              /* here the master could read another byte which
--                 would be the PIO reg (the actual pin logic state)
--                 since in this driver we don't know which pins are
--                 in and outs, there's no value to read the state and
--                 compare. with (*buf) so end this command abruptly: */
-               if (w1_reset_resume_command(sl->master))
--                      goto error;
-+                      goto out; /* unrecoverable error */
-+              /* try again, the slave is ready for a command */
-+      } while (--retries);
--              /* go read back the output latches */
--              /* (the direct effect of the write above) */
--              w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
--              w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
--              w1_buf[2] = 0;
--              w1_write_block(sl->master, w1_buf, 3);
--              /* read the result of the READ_PIO_REGS command */
--              if (w1_read_8(sl->master) == *buf)
--#endif
--              {
--                      /* success! */
--                      mutex_unlock(&sl->master->bus_mutex);
--                      dev_dbg(&sl->dev,
--                              "mutex unlocked, retries:%d", retries);
--                      return 1;
--              }
--      }
--error:
-+out:
-       mutex_unlock(&sl->master->bus_mutex);
--      dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
--      return -EIO;
-+      dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
-+              (bytes_written > 0) ? "succeeded" : "error", retries);
-+
-+      return bytes_written;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0425-ASoC-decommissioning-driver-for-3Dlab-Nano-soundcard.patch b/target/linux/brcm2708/patches-4.19/950-0425-ASoC-decommissioning-driver-for-3Dlab-Nano-soundcard.patch
new file mode 100644 (file)
index 0000000..97d69c6
--- /dev/null
@@ -0,0 +1,500 @@
+From 3150326498ba9388b85e5af2c8fcfeafc46eeaad Mon Sep 17 00:00:00 2001
+From: GT <dev@3d-lab-av.com>
+Date: Sat, 6 Apr 2019 21:16:39 +0100
+Subject: [PATCH] ASoC: decommissioning driver for 3Dlab Nano soundcard
+
+---
+ .../overlays/3dlab-nano-player-overlay.dts    |  32 --
+ arch/arm/boot/dts/overlays/Makefile           |   1 -
+ arch/arm/boot/dts/overlays/README             |   6 -
+ sound/soc/bcm/3dlab-nano-player.c             | 370 ------------------
+ sound/soc/bcm/Kconfig                         |   6 -
+ sound/soc/bcm/Makefile                        |   6 +-
+ 8 files changed, 2 insertions(+), 421 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
+ delete mode 100644 sound/soc/bcm/3dlab-nano-player.c
+
+--- a/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
++++ /dev/null
+@@ -1,32 +0,0 @@
+-// Definitions for 3Dlab Nano Player
+-/dts-v1/;
+-/plugin/;
+-
+-/ {
+-      compatible = "brcm,bcm2708";
+-
+-      fragment@0 {
+-              target = <&i2s>;
+-              __overlay__ {
+-                      status = "okay";
+-              };
+-      };
+-
+-      fragment@1 {
+-              target = <&i2c>;
+-              __overlay__ {
+-                      #address-cells = <1>;
+-                      #size-cells = <0>;
+-                      status = "okay";
+-
+-                      nano-player@41 {
+-                              compatible = "3dlab,nano-player";
+-                              reg = <0x41>;
+-                              i2s-controller = <&i2s>;
+-                              status = "okay";
+-                      };
+-              };
+-      };
+-};
+-
+-// EOF
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -1,7 +1,6 @@
+ # Overlays for the Raspberry Pi platform
+ dtbo-$(CONFIG_ARCH_BCM2835) += \
+-      3dlab-nano-player.dtbo \
+       adau1977-adc.dtbo \
+       adau7002-simple.dtbo \
+       ads1015.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -205,12 +205,6 @@ Params:
+         and the other i2c baudrate parameters.
+-Name:   3dlab-nano-player
+-Info:   Configures the 3Dlab Nano Player
+-Load:   dtoverlay=3dlab-nano-player
+-Params: <None>
+-
+-
+ Name:   adau1977-adc
+ Info:   Overlay for activation of ADAU1977 ADC codec over I2C for control
+         and I2S for data.
+--- a/sound/soc/bcm/3dlab-nano-player.c
++++ /dev/null
+@@ -1,370 +0,0 @@
+-/*
+- * 3Dlab Nano Player ALSA SoC Audio driver.
+- *
+- * Copyright (C) 2018 3Dlab.
+- *
+- * Author: GT <dev@3d-lab-av.com>
+- *
+- * 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/i2c.h>
+-#include <sound/soc.h>
+-#include <sound/pcm.h>
+-#include <sound/pcm_params.h>
+-#include <sound/control.h>
+-
+-#define NANO_ID               0x00
+-#define NANO_VER      0x01
+-#define NANO_CFG      0x02
+-#define NANO_STATUS   0x03
+-#define NANO_SPI_ADDR 0x04
+-#define NANO_SPI_DATA 0x05
+-
+-#define NANO_ID_VAL   0x3D
+-#define NANO_CFG_OFF  0x00
+-#define NANO_CFG_MULT1        0
+-#define NANO_CFG_MULT2        1
+-#define NANO_CFG_MULT4        2
+-#define NANO_CFG_MULT8        3
+-#define NANO_CFG_MULT16       4
+-#define NANO_CFG_CLK22        0
+-#define NANO_CFG_CLK24        BIT(3)
+-#define NANO_CFG_DSD  BIT(4)
+-#define NANO_CFG_ENA  BIT(5)
+-#define NANO_CFG_BLINK        BIT(6)
+-#define NANO_STATUS_P1  BIT(0)
+-#define NANO_STATUS_P2  BIT(1)
+-#define NANO_STATUS_FLG BIT(2)
+-#define NANO_STATUS_CLK BIT(3)
+-#define NANO_SPI_READ 0
+-#define NANO_SPI_WRITE        BIT(5)
+-
+-#define NANO_DAC_CTRL1        0x00
+-#define NANO_DAC_CTRL2        0x01
+-#define NANO_DAC_CTRL3        0x02
+-#define NANO_DAC_LATT 0x03
+-#define NANO_DAC_RATT 0x04
+-
+-#define NANO_CTRL2_VAL        0x22
+-
+-static int nano_player_spi_write(struct regmap *map,
+-                               unsigned int reg, unsigned int val)
+-{
+-      /* indirect register access */
+-      regmap_write(map, NANO_SPI_DATA, val);
+-      regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
+-      return 0;
+-}
+-
+-static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
+-                               struct snd_ctl_elem_info *uinfo)
+-{
+-      /* describe control element */
+-      if (strstr(kcontrol->id.name, "Volume")) {
+-              uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+-              uinfo->count = 1;
+-              uinfo->value.integer.min = 0;
+-              uinfo->value.integer.max = 100;
+-      } else {
+-              uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+-              uinfo->count = 1;
+-              uinfo->value.integer.min = 0;
+-              uinfo->value.integer.max = 1;
+-      }
+-
+-      return 0;
+-}
+-
+-static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
+-                              struct snd_ctl_elem_value *ucontrol)
+-{
+-      /* program control value to hardware */
+-      struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+-      struct regmap *regmap = snd_soc_card_get_drvdata(card);
+-
+-      if (strstr(kcontrol->id.name, "Volume")) {
+-              unsigned int vol = ucontrol->value.integer.value[0];
+-              unsigned int att = 255 - (2 * (100 - vol));
+-
+-              nano_player_spi_write(regmap, NANO_DAC_LATT, att);
+-              nano_player_spi_write(regmap, NANO_DAC_RATT, att);
+-              kcontrol->private_value = vol;
+-      } else {
+-              unsigned int mute = ucontrol->value.integer.value[0];
+-              unsigned int reg = NANO_CTRL2_VAL | mute;
+-
+-              nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
+-              kcontrol->private_value = mute;
+-      }
+-      return 0;
+-}
+-
+-static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
+-                              struct snd_ctl_elem_value *ucontrol)
+-{
+-      /* return last programmed value */
+-      ucontrol->value.integer.value[0] = kcontrol->private_value;
+-      return 0;
+-}
+-
+-#define SOC_NANO_PLAYER_CTRL(xname) \
+-{     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+-      .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+-      .info = nano_player_ctrl_info, \
+-      .put = nano_player_ctrl_put, \
+-      .get = nano_player_ctrl_get }
+-
+-static const struct snd_kcontrol_new nano_player_controls[] = {
+-      SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
+-      SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
+-};
+-
+-static const unsigned int nano_player_rates[] = {
+-      44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
+-      705600, 768000 /* only possible with fast clocks */
+-};
+-
+-static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
+-      .list   = nano_player_rates,
+-      .count  = ARRAY_SIZE(nano_player_rates),
+-};
+-
+-static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
+-{
+-      struct snd_soc_card *card = rtd->card;
+-      struct regmap *regmap = snd_soc_card_get_drvdata(card);
+-      struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
+-      struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
+-      unsigned int sample_bits = 32;
+-      unsigned int val;
+-
+-      /* configure cpu dai */
+-      cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
+-      cpu->rate_max = 768000;
+-
+-      /* configure dummy codec dai */
+-      codec->rate_min = 44100;
+-      codec->rates = SNDRV_PCM_RATE_KNOT;
+-      codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
+-
+-      /* configure max supported rate */
+-      regmap_read(regmap, NANO_STATUS, &val);
+-      if (val & NANO_STATUS_CLK) {
+-              dev_notice(card->dev, "Board with fast clocks installed\n");
+-              codec->rate_max = 768000;
+-      } else {
+-              dev_notice(card->dev, "Board with normal clocks installed\n");
+-              codec->rate_max = 384000;
+-      }
+-
+-      /* frame length enforced by hardware */
+-      return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
+-}
+-
+-static int nano_player_startup(struct snd_pcm_substream *substream)
+-{
+-      return snd_pcm_hw_constraint_list(substream->runtime, 0,
+-                                        SNDRV_PCM_HW_PARAM_RATE,
+-                                        &nano_player_constraint_rates);
+-}
+-
+-static int nano_player_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_card *card = rtd->card;
+-      struct regmap *regmap = snd_soc_card_get_drvdata(card);
+-      unsigned int config = NANO_CFG_ENA;
+-      struct snd_mask *fmt;
+-
+-      /* configure PCM or DSD */
+-      fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+-      if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
+-              /* embed DSD in PCM data */
+-              snd_mask_none(fmt);
+-              snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
+-              /* enable DSD mode */
+-              config |= NANO_CFG_DSD;
+-      }
+-
+-      /* configure clocks */
+-      switch (params_rate(params)) {
+-      case 44100:
+-              config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
+-              break;
+-      case 88200:
+-              config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
+-              break;
+-      case 176400:
+-              config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
+-              break;
+-      case 352800:
+-              config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
+-              break;
+-      case 705600:
+-              config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
+-              break;
+-      case 48000:
+-              config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
+-              break;
+-      case 96000:
+-              config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
+-              break;
+-      case 192000:
+-              config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
+-              break;
+-      case 384000:
+-              config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
+-              break;
+-      case 768000:
+-              config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
+-
+-      dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
+-      return regmap_write(regmap, NANO_CFG, config);
+-}
+-
+-static struct snd_soc_ops nano_player_ops = {
+-      .startup        = nano_player_startup,
+-      .hw_params      = nano_player_hw_params,
+-};
+-
+-static struct snd_soc_dai_link nano_player_link = {
+-      .name           = "3Dlab Nano Player",
+-      .stream_name    = "3Dlab Nano Player HiFi",
+-      .platform_name  = "bcm2708-i2s.0",
+-      .cpu_dai_name   = "bcm2708-i2s.0",
+-      .codec_name     = "snd-soc-dummy",
+-      .codec_dai_name = "snd-soc-dummy-dai",
+-      .dai_fmt        = SND_SOC_DAIFMT_I2S |
+-                        SND_SOC_DAIFMT_CONT |
+-                        SND_SOC_DAIFMT_NB_NF |
+-                        SND_SOC_DAIFMT_CBM_CFM,
+-      .init           = nano_player_init,
+-      .ops            = &nano_player_ops,
+-};
+-
+-static const struct regmap_config nano_player_regmap = {
+-      .reg_bits       = 8,
+-      .val_bits       = 8,
+-      .max_register   = 128,
+-      .cache_type     = REGCACHE_RBTREE,
+-};
+-
+-static int nano_player_card_probe(struct snd_soc_card *card)
+-{
+-      struct regmap *regmap = snd_soc_card_get_drvdata(card);
+-      unsigned int val;
+-
+-      /* check hardware integrity */
+-      regmap_read(regmap, NANO_ID, &val);
+-      if (val != NANO_ID_VAL) {
+-              dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
+-              return -ENODEV;
+-      }
+-
+-      /* report version to the user */
+-      regmap_read(regmap, NANO_VER, &val);
+-      dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
+-
+-      /* enable internal audio bus and blink status LED */
+-      return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
+-}
+-
+-static int nano_player_card_remove(struct snd_soc_card *card)
+-{
+-      /* disable internal audio bus */
+-      struct regmap *regmap = snd_soc_card_get_drvdata(card);
+-
+-      return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
+-}
+-
+-static struct snd_soc_card nano_player_card = {
+-      .name           = "3Dlab_Nano_Player",
+-      .owner          = THIS_MODULE,
+-      .dai_link       = &nano_player_link,
+-      .num_links      = 1,
+-      .controls       = nano_player_controls,
+-      .num_controls   = ARRAY_SIZE(nano_player_controls),
+-      .probe          = nano_player_card_probe,
+-      .remove         = nano_player_card_remove,
+-};
+-
+-static int nano_player_i2c_probe(struct i2c_client *i2c,
+-                               const struct i2c_device_id *id)
+-{
+-      struct regmap *regmap;
+-      int ret;
+-
+-      regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
+-      if (IS_ERR(regmap)) {
+-              ret = PTR_ERR(regmap);
+-              dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
+-              return ret;
+-      }
+-
+-      if (i2c->dev.of_node) {
+-              struct snd_soc_dai_link *dai = &nano_player_link;
+-              struct device_node *node;
+-
+-              /* cpu handle configured by device tree */
+-              node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
+-              if (node) {
+-                      dai->platform_name = NULL;
+-                      dai->platform_of_node = node;
+-                      dai->cpu_dai_name = NULL;
+-                      dai->cpu_of_node = node;
+-              }
+-      }
+-
+-      nano_player_card.dev = &i2c->dev;
+-      snd_soc_card_set_drvdata(&nano_player_card, regmap);
+-      ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
+-
+-      if (ret && ret != -EPROBE_DEFER)
+-              dev_err(&i2c->dev, "Failed to register card %d\n", ret);
+-
+-      return ret;
+-}
+-
+-static const struct of_device_id nano_player_of_match[] = {
+-      { .compatible = "3dlab,nano-player", },
+-      { }
+-};
+-MODULE_DEVICE_TABLE(of, nano_player_of_match);
+-
+-static const struct i2c_device_id nano_player_i2c_id[] = {
+-      { "nano-player", 0 },
+-      { }
+-};
+-MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
+-
+-static struct i2c_driver nano_player_i2c_driver = {
+-      .probe          = nano_player_i2c_probe,
+-      .id_table       = nano_player_i2c_id,
+-      .driver         = {
+-              .name           = "nano-player",
+-              .owner          = THIS_MODULE,
+-              .of_match_table = nano_player_of_match,
+-      },
+-};
+-
+-module_i2c_driver(nano_player_i2c_driver);
+-
+-MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
+-MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
+-MODULE_LICENSE("GPL v2");
+-
+-/* EOF */
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -17,12 +17,6 @@ config SND_SOC_CYGNUS
+         If you don't know what to do here, say N.
+-config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
+-      tristate "Support for 3Dlab Nano Player"
+-      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+-      help
+-        Say Y or M if you want to add support for 3Dlab Nano Player.
+-
+ config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
+       tristate "Support for Google voiceHAT soundcard"
+       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -12,7 +12,6 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
+ snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
+ # BCM2708 Machine Support
+-snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+@@ -20,7 +19,7 @@ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+ snd-soc-iqaudio-codec-objs := iqaudio-codec.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
+- snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
++snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+ snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
+ snd-soc-audiosense-pi-objs := audiosense-pi.o
+@@ -36,7 +35,6 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
+ snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
+ snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
+-obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.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
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
+@@ -45,7 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS)
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
+- obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
++obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
+ obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
diff --git a/target/linux/brcm2708/patches-4.19/950-0425-w1-ds2482-cosmetic-fixes-after-54865314f5a1.patch b/target/linux/brcm2708/patches-4.19/950-0425-w1-ds2482-cosmetic-fixes-after-54865314f5a1.patch
deleted file mode 100644 (file)
index 3766707..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-From 2bf6a79fb6555b5ebf21d03b1295e017804474c4 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Mon, 4 Mar 2019 12:23:36 +0100
-Subject: [PATCH] w1: ds2482: cosmetic fixes after 54865314f5a1
-
-commit 5cb27d30fc3a281e830a2099d520b469e2b82008 upstream.
-
-We have a helper function ds2482_calculate_config() which is calculating
-the config value, so just use it instead of passing the same variable
-in all calls to this function.
-
-Also fixes the placement of module parameters to match with:
-50fa2951bd74 (w1: Organize driver source to natural/common order)
-by Andrew F. Davis
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Cc: Andrew Worsley <amworsley@gmail.com>
-Cc: Andrew F. Davis <afd@ti.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/masters/ds2482.c | 18 +++++++++++-------
- 1 file changed, 11 insertions(+), 7 deletions(-)
-
---- a/drivers/w1/masters/ds2482.c
-+++ b/drivers/w1/masters/ds2482.c
-@@ -37,6 +37,11 @@ module_param_named(active_pullup, ds2482
- MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \
-                               "0-disable, 1-enable (default)");
-+/* extra configurations - e.g. 1WS */
-+static int extra_config;
-+module_param(extra_config, int, S_IRUGO | S_IWUSR);
-+MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
-+
- /**
-  * The DS2482 registers - there are 3 registers that are addressed by a read
-  * pointer. The read pointer is set by the last command executed.
-@@ -70,8 +75,6 @@ MODULE_PARM_DESC(active_pullup, "Active
- #define DS2482_REG_CFG_PPM            0x02    /* presence pulse masking */
- #define DS2482_REG_CFG_APU            0x01    /* active pull-up */
--/* extra configurations - e.g. 1WS */
--static int extra_config;
- /**
-  * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only).
-@@ -130,6 +133,8 @@ struct ds2482_data {
-  */
- static inline u8 ds2482_calculate_config(u8 conf)
- {
-+      conf |= extra_config;
-+
-       if (ds2482_active_pullup)
-               conf |= DS2482_REG_CFG_APU;
-@@ -405,7 +410,7 @@ static u8 ds2482_w1_reset_bus(void *data
-               /* If the chip did reset since detect, re-config it */
-               if (err & DS2482_REG_STS_RST)
-                       ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
--                                      ds2482_calculate_config(extra_config));
-+                                           ds2482_calculate_config(0x00));
-       }
-       mutex_unlock(&pdev->access_lock);
-@@ -431,7 +436,8 @@ static u8 ds2482_w1_set_pullup(void *dat
-               ds2482_wait_1wire_idle(pdev);
-               /* note: it seems like both SPU and APU have to be set! */
-               retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
--                      ds2482_calculate_config(extra_config|DS2482_REG_CFG_SPU|DS2482_REG_CFG_APU));
-+                      ds2482_calculate_config(DS2482_REG_CFG_SPU |
-+                                              DS2482_REG_CFG_APU));
-               ds2482_wait_1wire_idle(pdev);
-       }
-@@ -484,7 +490,7 @@ static int ds2482_probe(struct i2c_clien
-       /* Set all config items to 0 (off) */
-       ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG,
--              ds2482_calculate_config(extra_config));
-+              ds2482_calculate_config(0x00));
-       mutex_init(&data->access_lock);
-@@ -559,7 +565,5 @@ module_i2c_driver(ds2482_driver);
- MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
- MODULE_DESCRIPTION("DS2482 driver");
--module_param(extra_config, int, S_IRUGO | S_IWUSR);
--MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
- MODULE_LICENSE("GPL");
diff --git a/target/linux/brcm2708/patches-4.19/950-0426-.gitignore-Add-.dtbo-explicitly.patch b/target/linux/brcm2708/patches-4.19/950-0426-.gitignore-Add-.dtbo-explicitly.patch
new file mode 100644 (file)
index 0000000..6a4566a
--- /dev/null
@@ -0,0 +1,22 @@
+From bd4e0a6ad64c1211094776923bf61bd6ede3f043 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 21 May 2019 15:17:33 +0100
+Subject: [PATCH] .gitignore: Add *.dtbo explicitly
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ .gitignore | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/.gitignore
++++ b/.gitignore
+@@ -15,7 +15,8 @@
+ *.bin
+ *.bz2
+ *.c.[012]*.*
+-*.dtb*
++*.dtb
++*.dtbo
+ *.dtb.S
+ *.dwo
+ *.elf
diff --git a/target/linux/brcm2708/patches-4.19/950-0426-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch b/target/linux/brcm2708/patches-4.19/950-0426-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch
deleted file mode 100644 (file)
index 346cda8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-From 2c1e36e477550ea66824433c132fdff03b4ee020 Mon Sep 17 00:00:00 2001
-From: Klaus Schulz <klsschlz@gmail.com>
-Date: Thu, 16 May 2019 13:35:32 +0200
-Subject: [PATCH] sound: pcm512x-codec: Adding 352.8kHz samplerate
- support
-
----
- sound/soc/codecs/pcm512x.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/sound/soc/codecs/pcm512x.c
-+++ b/sound/soc/codecs/pcm512x.c
-@@ -542,7 +542,7 @@ static unsigned long pcm512x_ncp_target(
- static const u32 pcm512x_dai_rates[] = {
-       8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
--      88200, 96000, 176400, 192000, 384000,
-+      88200, 96000, 176400, 192000, 352800, 384000,
- };
- static const struct snd_pcm_hw_constraint_list constraints_slave = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0427-ASoC-decommissioning-driver-for-3Dlab-Nano-soundcard.patch b/target/linux/brcm2708/patches-4.19/950-0427-ASoC-decommissioning-driver-for-3Dlab-Nano-soundcard.patch
deleted file mode 100644 (file)
index 97d69c6..0000000
+++ /dev/null
@@ -1,500 +0,0 @@
-From 3150326498ba9388b85e5af2c8fcfeafc46eeaad Mon Sep 17 00:00:00 2001
-From: GT <dev@3d-lab-av.com>
-Date: Sat, 6 Apr 2019 21:16:39 +0100
-Subject: [PATCH] ASoC: decommissioning driver for 3Dlab Nano soundcard
-
----
- .../overlays/3dlab-nano-player-overlay.dts    |  32 --
- arch/arm/boot/dts/overlays/Makefile           |   1 -
- arch/arm/boot/dts/overlays/README             |   6 -
- sound/soc/bcm/3dlab-nano-player.c             | 370 ------------------
- sound/soc/bcm/Kconfig                         |   6 -
- sound/soc/bcm/Makefile                        |   6 +-
- 8 files changed, 2 insertions(+), 421 deletions(-)
- delete mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
- delete mode 100644 sound/soc/bcm/3dlab-nano-player.c
-
---- a/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
-+++ /dev/null
-@@ -1,32 +0,0 @@
--// Definitions for 3Dlab Nano Player
--/dts-v1/;
--/plugin/;
--
--/ {
--      compatible = "brcm,bcm2708";
--
--      fragment@0 {
--              target = <&i2s>;
--              __overlay__ {
--                      status = "okay";
--              };
--      };
--
--      fragment@1 {
--              target = <&i2c>;
--              __overlay__ {
--                      #address-cells = <1>;
--                      #size-cells = <0>;
--                      status = "okay";
--
--                      nano-player@41 {
--                              compatible = "3dlab,nano-player";
--                              reg = <0x41>;
--                              i2s-controller = <&i2s>;
--                              status = "okay";
--                      };
--              };
--      };
--};
--
--// EOF
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -1,7 +1,6 @@
- # Overlays for the Raspberry Pi platform
- dtbo-$(CONFIG_ARCH_BCM2835) += \
--      3dlab-nano-player.dtbo \
-       adau1977-adc.dtbo \
-       adau7002-simple.dtbo \
-       ads1015.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -205,12 +205,6 @@ Params:
-         and the other i2c baudrate parameters.
--Name:   3dlab-nano-player
--Info:   Configures the 3Dlab Nano Player
--Load:   dtoverlay=3dlab-nano-player
--Params: <None>
--
--
- Name:   adau1977-adc
- Info:   Overlay for activation of ADAU1977 ADC codec over I2C for control
-         and I2S for data.
---- a/sound/soc/bcm/3dlab-nano-player.c
-+++ /dev/null
-@@ -1,370 +0,0 @@
--/*
-- * 3Dlab Nano Player ALSA SoC Audio driver.
-- *
-- * Copyright (C) 2018 3Dlab.
-- *
-- * Author: GT <dev@3d-lab-av.com>
-- *
-- * 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/i2c.h>
--#include <sound/soc.h>
--#include <sound/pcm.h>
--#include <sound/pcm_params.h>
--#include <sound/control.h>
--
--#define NANO_ID               0x00
--#define NANO_VER      0x01
--#define NANO_CFG      0x02
--#define NANO_STATUS   0x03
--#define NANO_SPI_ADDR 0x04
--#define NANO_SPI_DATA 0x05
--
--#define NANO_ID_VAL   0x3D
--#define NANO_CFG_OFF  0x00
--#define NANO_CFG_MULT1        0
--#define NANO_CFG_MULT2        1
--#define NANO_CFG_MULT4        2
--#define NANO_CFG_MULT8        3
--#define NANO_CFG_MULT16       4
--#define NANO_CFG_CLK22        0
--#define NANO_CFG_CLK24        BIT(3)
--#define NANO_CFG_DSD  BIT(4)
--#define NANO_CFG_ENA  BIT(5)
--#define NANO_CFG_BLINK        BIT(6)
--#define NANO_STATUS_P1  BIT(0)
--#define NANO_STATUS_P2  BIT(1)
--#define NANO_STATUS_FLG BIT(2)
--#define NANO_STATUS_CLK BIT(3)
--#define NANO_SPI_READ 0
--#define NANO_SPI_WRITE        BIT(5)
--
--#define NANO_DAC_CTRL1        0x00
--#define NANO_DAC_CTRL2        0x01
--#define NANO_DAC_CTRL3        0x02
--#define NANO_DAC_LATT 0x03
--#define NANO_DAC_RATT 0x04
--
--#define NANO_CTRL2_VAL        0x22
--
--static int nano_player_spi_write(struct regmap *map,
--                               unsigned int reg, unsigned int val)
--{
--      /* indirect register access */
--      regmap_write(map, NANO_SPI_DATA, val);
--      regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
--      return 0;
--}
--
--static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
--                               struct snd_ctl_elem_info *uinfo)
--{
--      /* describe control element */
--      if (strstr(kcontrol->id.name, "Volume")) {
--              uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
--              uinfo->count = 1;
--              uinfo->value.integer.min = 0;
--              uinfo->value.integer.max = 100;
--      } else {
--              uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
--              uinfo->count = 1;
--              uinfo->value.integer.min = 0;
--              uinfo->value.integer.max = 1;
--      }
--
--      return 0;
--}
--
--static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
--                              struct snd_ctl_elem_value *ucontrol)
--{
--      /* program control value to hardware */
--      struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
--      struct regmap *regmap = snd_soc_card_get_drvdata(card);
--
--      if (strstr(kcontrol->id.name, "Volume")) {
--              unsigned int vol = ucontrol->value.integer.value[0];
--              unsigned int att = 255 - (2 * (100 - vol));
--
--              nano_player_spi_write(regmap, NANO_DAC_LATT, att);
--              nano_player_spi_write(regmap, NANO_DAC_RATT, att);
--              kcontrol->private_value = vol;
--      } else {
--              unsigned int mute = ucontrol->value.integer.value[0];
--              unsigned int reg = NANO_CTRL2_VAL | mute;
--
--              nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
--              kcontrol->private_value = mute;
--      }
--      return 0;
--}
--
--static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
--                              struct snd_ctl_elem_value *ucontrol)
--{
--      /* return last programmed value */
--      ucontrol->value.integer.value[0] = kcontrol->private_value;
--      return 0;
--}
--
--#define SOC_NANO_PLAYER_CTRL(xname) \
--{     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
--      .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
--      .info = nano_player_ctrl_info, \
--      .put = nano_player_ctrl_put, \
--      .get = nano_player_ctrl_get }
--
--static const struct snd_kcontrol_new nano_player_controls[] = {
--      SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
--      SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
--};
--
--static const unsigned int nano_player_rates[] = {
--      44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
--      705600, 768000 /* only possible with fast clocks */
--};
--
--static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
--      .list   = nano_player_rates,
--      .count  = ARRAY_SIZE(nano_player_rates),
--};
--
--static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
--{
--      struct snd_soc_card *card = rtd->card;
--      struct regmap *regmap = snd_soc_card_get_drvdata(card);
--      struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
--      struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
--      unsigned int sample_bits = 32;
--      unsigned int val;
--
--      /* configure cpu dai */
--      cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
--      cpu->rate_max = 768000;
--
--      /* configure dummy codec dai */
--      codec->rate_min = 44100;
--      codec->rates = SNDRV_PCM_RATE_KNOT;
--      codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
--
--      /* configure max supported rate */
--      regmap_read(regmap, NANO_STATUS, &val);
--      if (val & NANO_STATUS_CLK) {
--              dev_notice(card->dev, "Board with fast clocks installed\n");
--              codec->rate_max = 768000;
--      } else {
--              dev_notice(card->dev, "Board with normal clocks installed\n");
--              codec->rate_max = 384000;
--      }
--
--      /* frame length enforced by hardware */
--      return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
--}
--
--static int nano_player_startup(struct snd_pcm_substream *substream)
--{
--      return snd_pcm_hw_constraint_list(substream->runtime, 0,
--                                        SNDRV_PCM_HW_PARAM_RATE,
--                                        &nano_player_constraint_rates);
--}
--
--static int nano_player_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_card *card = rtd->card;
--      struct regmap *regmap = snd_soc_card_get_drvdata(card);
--      unsigned int config = NANO_CFG_ENA;
--      struct snd_mask *fmt;
--
--      /* configure PCM or DSD */
--      fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
--      if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
--              /* embed DSD in PCM data */
--              snd_mask_none(fmt);
--              snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
--              /* enable DSD mode */
--              config |= NANO_CFG_DSD;
--      }
--
--      /* configure clocks */
--      switch (params_rate(params)) {
--      case 44100:
--              config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
--              break;
--      case 88200:
--              config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
--              break;
--      case 176400:
--              config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
--              break;
--      case 352800:
--              config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
--              break;
--      case 705600:
--              config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
--              break;
--      case 48000:
--              config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
--              break;
--      case 96000:
--              config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
--              break;
--      case 192000:
--              config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
--              break;
--      case 384000:
--              config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
--              break;
--      case 768000:
--              config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
--      return regmap_write(regmap, NANO_CFG, config);
--}
--
--static struct snd_soc_ops nano_player_ops = {
--      .startup        = nano_player_startup,
--      .hw_params      = nano_player_hw_params,
--};
--
--static struct snd_soc_dai_link nano_player_link = {
--      .name           = "3Dlab Nano Player",
--      .stream_name    = "3Dlab Nano Player HiFi",
--      .platform_name  = "bcm2708-i2s.0",
--      .cpu_dai_name   = "bcm2708-i2s.0",
--      .codec_name     = "snd-soc-dummy",
--      .codec_dai_name = "snd-soc-dummy-dai",
--      .dai_fmt        = SND_SOC_DAIFMT_I2S |
--                        SND_SOC_DAIFMT_CONT |
--                        SND_SOC_DAIFMT_NB_NF |
--                        SND_SOC_DAIFMT_CBM_CFM,
--      .init           = nano_player_init,
--      .ops            = &nano_player_ops,
--};
--
--static const struct regmap_config nano_player_regmap = {
--      .reg_bits       = 8,
--      .val_bits       = 8,
--      .max_register   = 128,
--      .cache_type     = REGCACHE_RBTREE,
--};
--
--static int nano_player_card_probe(struct snd_soc_card *card)
--{
--      struct regmap *regmap = snd_soc_card_get_drvdata(card);
--      unsigned int val;
--
--      /* check hardware integrity */
--      regmap_read(regmap, NANO_ID, &val);
--      if (val != NANO_ID_VAL) {
--              dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
--              return -ENODEV;
--      }
--
--      /* report version to the user */
--      regmap_read(regmap, NANO_VER, &val);
--      dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
--
--      /* enable internal audio bus and blink status LED */
--      return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
--}
--
--static int nano_player_card_remove(struct snd_soc_card *card)
--{
--      /* disable internal audio bus */
--      struct regmap *regmap = snd_soc_card_get_drvdata(card);
--
--      return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
--}
--
--static struct snd_soc_card nano_player_card = {
--      .name           = "3Dlab_Nano_Player",
--      .owner          = THIS_MODULE,
--      .dai_link       = &nano_player_link,
--      .num_links      = 1,
--      .controls       = nano_player_controls,
--      .num_controls   = ARRAY_SIZE(nano_player_controls),
--      .probe          = nano_player_card_probe,
--      .remove         = nano_player_card_remove,
--};
--
--static int nano_player_i2c_probe(struct i2c_client *i2c,
--                               const struct i2c_device_id *id)
--{
--      struct regmap *regmap;
--      int ret;
--
--      regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
--      if (IS_ERR(regmap)) {
--              ret = PTR_ERR(regmap);
--              dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
--              return ret;
--      }
--
--      if (i2c->dev.of_node) {
--              struct snd_soc_dai_link *dai = &nano_player_link;
--              struct device_node *node;
--
--              /* cpu handle configured by device tree */
--              node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
--              if (node) {
--                      dai->platform_name = NULL;
--                      dai->platform_of_node = node;
--                      dai->cpu_dai_name = NULL;
--                      dai->cpu_of_node = node;
--              }
--      }
--
--      nano_player_card.dev = &i2c->dev;
--      snd_soc_card_set_drvdata(&nano_player_card, regmap);
--      ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
--
--      if (ret && ret != -EPROBE_DEFER)
--              dev_err(&i2c->dev, "Failed to register card %d\n", ret);
--
--      return ret;
--}
--
--static const struct of_device_id nano_player_of_match[] = {
--      { .compatible = "3dlab,nano-player", },
--      { }
--};
--MODULE_DEVICE_TABLE(of, nano_player_of_match);
--
--static const struct i2c_device_id nano_player_i2c_id[] = {
--      { "nano-player", 0 },
--      { }
--};
--MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
--
--static struct i2c_driver nano_player_i2c_driver = {
--      .probe          = nano_player_i2c_probe,
--      .id_table       = nano_player_i2c_id,
--      .driver         = {
--              .name           = "nano-player",
--              .owner          = THIS_MODULE,
--              .of_match_table = nano_player_of_match,
--      },
--};
--
--module_i2c_driver(nano_player_i2c_driver);
--
--MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
--MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
--MODULE_LICENSE("GPL v2");
--
--/* EOF */
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -17,12 +17,6 @@ config SND_SOC_CYGNUS
-         If you don't know what to do here, say N.
--config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
--      tristate "Support for 3Dlab Nano Player"
--      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
--      help
--        Say Y or M if you want to add support for 3Dlab Nano Player.
--
- config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
-       tristate "Support for Google voiceHAT soundcard"
-       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -12,7 +12,6 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
- snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
- # BCM2708 Machine Support
--snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
- snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-justboom-dac-objs := justboom-dac.o
-@@ -20,7 +19,7 @@ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
- snd-soc-iqaudio-codec-objs := iqaudio-codec.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
-- snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
-+snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
- snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
- snd-soc-audiosense-pi-objs := audiosense-pi.o
-@@ -36,7 +35,6 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
- snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
- snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
--obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.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
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
-@@ -45,7 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS)
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
-- obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
-+obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
- obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
diff --git a/target/linux/brcm2708/patches-4.19/950-0427-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch b/target/linux/brcm2708/patches-4.19/950-0427-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch
new file mode 100644 (file)
index 0000000..ac7a9ae
--- /dev/null
@@ -0,0 +1,39 @@
+From 83f0a8986ae42e33bc16acda0451dce2cf4dfb55 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
+@@ -1282,8 +1282,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;
diff --git a/target/linux/brcm2708/patches-4.19/950-0428-.gitignore-Add-.dtbo-explicitly.patch b/target/linux/brcm2708/patches-4.19/950-0428-.gitignore-Add-.dtbo-explicitly.patch
deleted file mode 100644 (file)
index 6a4566a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-From bd4e0a6ad64c1211094776923bf61bd6ede3f043 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 21 May 2019 15:17:33 +0100
-Subject: [PATCH] .gitignore: Add *.dtbo explicitly
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- .gitignore | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/.gitignore
-+++ b/.gitignore
-@@ -15,7 +15,8 @@
- *.bin
- *.bz2
- *.c.[012]*.*
--*.dtb*
-+*.dtb
-+*.dtbo
- *.dtb.S
- *.dwo
- *.elf
diff --git a/target/linux/brcm2708/patches-4.19/950-0428-usb-dwc_otg-Clean-up-interrupt-claiming-code.patch b/target/linux/brcm2708/patches-4.19/950-0428-usb-dwc_otg-Clean-up-interrupt-claiming-code.patch
new file mode 100644 (file)
index 0000000..ba021f1
--- /dev/null
@@ -0,0 +1,157 @@
+From efb54d0f0445f3d279a7eae7395b566c96d080de Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 17:23:41 +0100
+Subject: [PATCH] usb: dwc_otg: Clean up interrupt claiming code
+
+The FIQ/IRQ interrupt number identification code is scattered through
+the dwc_otg driver. Rationalise it, simplifying the code and solving
+an existing issue.
+
+See: https://github.com/raspberrypi/linux/issues/2612
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c    | 18 +++++++++-----
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 +++-----
+ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h    |  6 +++++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 26 +++-----------------
+ 4 files changed, 25 insertions(+), 35 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+@@ -624,11 +624,7 @@ static int dwc_otg_driver_remove(
+        * Free the IRQ
+        */
+       if (otg_dev->common_irq_installed) {
+-#ifdef PLATFORM_INTERFACE
+-              free_irq(platform_get_irq(_dev, 0), otg_dev);
+-#else
+-              free_irq(_dev->irq, otg_dev);
+-#endif
++              free_irq(otg_dev->os_dep.irq_num, otg_dev);
+         } else {
+               DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
+               return REM_RETVAL(-ENXIO);
+@@ -905,7 +901,9 @@ static int dwc_otg_driver_probe(
+        */
+ #if defined(PLATFORM_INTERFACE)
+-      devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
++      devirq = platform_get_irq_byname(_dev, fiq_enable ? "soft" : "usb");
++      if (devirq < 0)
++          devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
+ #else
+       devirq = _dev->irq;
+ #endif
+@@ -922,6 +920,14 @@ static int dwc_otg_driver_probe(
+       } else {
+               dwc_otg_device->common_irq_installed = 1;
+       }
++      dwc_otg_device->os_dep.irq_num = devirq;
++      dwc_otg_device->os_dep.fiq_num = -EINVAL;
++      if (fiq_enable) {
++              int devfiq = platform_get_irq_byname(_dev, "usb");
++              if (devfiq < 0)
++                      devfiq = platform_get_irq(_dev, 1);
++              dwc_otg_device->os_dep.fiq_num = devfiq;
++      }
+ #ifndef IRQF_TRIGGER_LOW
+ #if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -492,7 +492,7 @@ static void hcd_init_fiq(void *cookie)
+ #endif
+       // Enable FIQ interrupt from USB peripheral
+ #ifdef CONFIG_ARM64
+-      irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
++      irq = otg_dev->os_dep.fiq_num;
+       if (irq < 0) {
+               DWC_ERROR("Can't get SIM-FIQ irq");
+@@ -509,7 +509,7 @@ static void hcd_init_fiq(void *cookie)
+       simfiq_irq = irq;
+ #else
+ #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
+-      irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
++      irq = otg_dev->os_dep.fiq_num;
+ #else
+       irq = INTERRUPT_VC_USB;
+ #endif
+@@ -626,11 +626,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
+        * allocates the DMA buffer pool, registers the USB bus, requests the
+        * IRQ line, and calls hcd_start method.
+        */
+-#ifdef PLATFORM_INTERFACE
+-      retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED);
+-#else
+-      retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED);
+-#endif
++      retval = usb_add_hcd(hcd, otg_dev->os_dep.irq_num, IRQF_SHARED);
+       if (retval < 0) {
+               goto error2;
+       }
+--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+@@ -102,6 +102,12 @@ typedef struct os_dependent {
+       /** Base address for MPHI peripheral */
+       void *mphi_base;
++      /** IRQ number (<0 if not valid) */
++      int irq_num;
++
++      /** FIQ number (<0 if not valid) */
++      int fiq_num;
++
+ #ifdef LM_INTERFACE
+       struct lm_device *lmdev;
+ #elif  defined(PCI_INTERFACE)
+--- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
+@@ -1224,30 +1224,16 @@ int pcd_init(dwc_bus_dev_t *_dev)
+       /*
+        * Setup interupt handler
+        */
+-#ifdef PLATFORM_INTERFACE
+       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
+-                    platform_get_irq(_dev, fiq_enable ? 0 : 1));
+-      retval = request_irq(platform_get_irq(_dev, fiq_enable ? 0 : 1), dwc_otg_pcd_irq,
++                    otg_dev->os_dep.irq_num);
++      retval = request_irq(otg_dev->os_dep.irq_num, dwc_otg_pcd_irq,
+                            IRQF_SHARED, gadget_wrapper->gadget.name,
+                            otg_dev->pcd);
+       if (retval != 0) {
+-              DWC_ERROR("request of irq%d failed\n",
+-                          platform_get_irq(_dev, fiq_enable ? 0 : 1));
++              DWC_ERROR("request of irq%d failed\n", otg_dev->os_dep.irq_num);
+               free_wrapper(gadget_wrapper);
+               return -EBUSY;
+       }
+-#else
+-      DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
+-                    _dev->irq);
+-      retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
+-                           IRQF_SHARED | IRQF_DISABLED,
+-                           gadget_wrapper->gadget.name, otg_dev->pcd);
+-      if (retval != 0) {
+-              DWC_ERROR("request of irq%d failed\n", _dev->irq);
+-              free_wrapper(gadget_wrapper);
+-              return -EBUSY;
+-      }
+-#endif
+       dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
+@@ -1267,11 +1253,7 @@ void pcd_remove(dwc_bus_dev_t *_dev)
+       /*
+        * Free the IRQ
+        */
+-#ifdef PLATFORM_INTERFACE
+-      free_irq(platform_get_irq(_dev, 0), pcd);
+-#else
+-      free_irq(_dev->irq, pcd);
+-#endif
++      free_irq(otg_dev->os_dep.irq_num, pcd);
+       dwc_otg_pcd_remove(otg_dev->pcd);
+       free_wrapper(gadget_wrapper);
+       otg_dev->pcd = 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0429-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch b/target/linux/brcm2708/patches-4.19/950-0429-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch
deleted file mode 100644 (file)
index ac7a9ae..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From 83f0a8986ae42e33bc16acda0451dce2cf4dfb55 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
-@@ -1282,8 +1282,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;
diff --git a/target/linux/brcm2708/patches-4.19/950-0429-overlays-Delete-the-deprecated-sdio-1bit-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0429-overlays-Delete-the-deprecated-sdio-1bit-overlay.patch
new file mode 100644 (file)
index 0000000..dac4386
--- /dev/null
@@ -0,0 +1,90 @@
+From 5edb8789ba5f9694698386683f2e4e97c70e765a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 14:27:35 +0100
+Subject: [PATCH] overlays: Delete the deprecated sdio-1bit overlay
+
+Use dtoverlay=sdio,bus_width=1,gpios_22_25 instead.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 -
+ .../boot/dts/overlays/sdio-1bit-overlay.dts   | 63 -------------------
+ 2 files changed, 64 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -126,7 +126,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       sc16is752-spi1.dtbo \
+       sdhost.dtbo \
+       sdio.dtbo \
+-      sdio-1bit.dtbo \
+       sdtweak.dtbo \
+       smi.dtbo \
+       smi-dev.dtbo \
+--- a/arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Enable 1-bit SDIO from MMC interface via GPIOs 22-25. Includes sdhost overlay. */
+-
+-/{
+-      compatible = "brcm,bcm2708";
+-
+-      fragment@0 {
+-              target = <&mmc>;
+-              __overlay__ {
+-                      status = "disabled";
+-              };
+-      };
+-
+-      fragment@1 {
+-              target = <&soc>;
+-              __overlay__ {
+-                      #address-cells = <1>;
+-                      #size-cells = <1>;
+-
+-                      sdio_1bit: sdio@7e300000 {
+-                              compatible = "brcm,bcm2835-mmc",
+-                                           "brcm,bcm2835-sdhci";
+-                              reg = <0x7e300000 0x100>;
+-                              interrupts = <2 30>;
+-                              clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
+-                              dmas = <&dma 11>;
+-                              dma-names = "rx-tx";
+-                              brcm,overclock-50 = <0>;
+-                              status = "okay";
+-                              pinctrl-names = "default";
+-                              pinctrl-0 = <&sdio_1bit_pins>;
+-                              non-removable;
+-                              bus-width = <1>;
+-                      };
+-              };
+-      };
+-
+-      fragment@2 {
+-              target = <&gpio>;
+-              __overlay__ {
+-                      sdio_1bit_pins: sdio_1bit_pins {
+-                              brcm,pins = <22 23 24 25>;
+-                              brcm,function = <7>; /* ALT3 = SD1 */
+-                              brcm,pull = <0 2 2 2>;
+-                      };
+-              };
+-      };
+-
+-      fragment@3 {
+-              target-path = "/aliases";
+-              __overlay__ {
+-                      mmc1 = "/soc/sdio@7e300000";
+-              };
+-      };
+-
+-
+-      __overrides__ {
+-              poll_once = <&sdio_1bit>,"non-removable?";
+-              sdio_overclock = <&sdio_1bit>,"brcm,overclock-50:0";
+-      };
+-};
diff --git a/target/linux/brcm2708/patches-4.19/950-0430-overlays-Remove-upstream-aux-interrupt-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0430-overlays-Remove-upstream-aux-interrupt-overlay.patch
new file mode 100644 (file)
index 0000000..c6e54f3
--- /dev/null
@@ -0,0 +1,97 @@
+From 2b584d25f295e07ef58efc2a60057be58015d693 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 10:06:04 +0100
+Subject: [PATCH] overlays: Remove upstream-aux-interrupt overlay
+
+We no longer have a downstream-specific auxilliary interrupt
+driver, so the overlay to disable it is no longer needed.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 -
+ arch/arm/boot/dts/overlays/README             | 12 +++----
+ .../upstream-aux-interrupt-overlay.dts        | 33 -------------------
+ .../boot/dts/overlays/upstream-overlay.dts    |  2 +-
+ 4 files changed, 6 insertions(+), 42 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -151,7 +151,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       uart1.dtbo \
+       udrc.dtbo \
+       upstream.dtbo \
+-      upstream-aux-interrupt.dtbo \
+       vc4-fkms-v3d.dtbo \
+       vc4-kms-kippah-7inch.dtbo \
+       vc4-kms-v3d.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2206,18 +2206,16 @@ Params: alsaname                Name of
+ Name:   upstream
+-Info:   Allow usage of downstream .dtb with upstream kernel. Comprises
+-        vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
++Info:   Allow usage of downstream .dtb with upstream kernel. Comprises the
++        vc4-kms-v3d and dwc2 overlays.
+ Load:   dtoverlay=upstream
+ Params: <None>
+ Name:   upstream-aux-interrupt
+-Info:   Allow usage of downstream .dtb with upstream kernel by binding AUX
+-        devices directly to the shared AUX interrupt line. One of the parts
+-        of the 'upstream' overlay
+-Load:   dtoverlay=upstream-aux-interrupt
+-Params: <None>
++Info:   This overlay has been deprecated and removed because it is no longer
++        necessary.
++Load:   <Deprecated>
+ Name:   vc4-fkms-v3d
+--- a/arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
++++ /dev/null
+@@ -1,33 +0,0 @@
+-// Overlay for missing AUX interrupt controller
+-// Instead we bind all AUX devices to the generic AUX interrupt line
+-/dts-v1/;
+-/plugin/;
+-
+-/ {
+-    compatible = "brcm,bcm2708";
+-
+-    fragment@0 {
+-        target = <&uart1>;
+-        __overlay__ {
+-            interrupt-parent = <&intc>;
+-            interrupts = <0x1 0x1d>;
+-        };
+-    };
+-
+-    fragment@1 {
+-        target = <&spi1>;
+-        __overlay__ {
+-            interrupt-parent = <&intc>;
+-            interrupts = <0x1 0x1d>;
+-        };
+-    };
+-
+-    fragment@2 {
+-        target = <&spi2>;
+-        __overlay__ {
+-            interrupt-parent = <&intc>;
+-            interrupts = <0x1 0x1d>;
+-        };
+-    };
+-};
+-
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -1,4 +1,4 @@
+-// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg upstream-aux-interrupt-overlay.dts,
++// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg
+ /dts-v1/;
+ /plugin/;
diff --git a/target/linux/brcm2708/patches-4.19/950-0430-usb-dwc_otg-Clean-up-interrupt-claiming-code.patch b/target/linux/brcm2708/patches-4.19/950-0430-usb-dwc_otg-Clean-up-interrupt-claiming-code.patch
deleted file mode 100644 (file)
index ba021f1..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-From efb54d0f0445f3d279a7eae7395b566c96d080de Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 17:23:41 +0100
-Subject: [PATCH] usb: dwc_otg: Clean up interrupt claiming code
-
-The FIQ/IRQ interrupt number identification code is scattered through
-the dwc_otg driver. Rationalise it, simplifying the code and solving
-an existing issue.
-
-See: https://github.com/raspberrypi/linux/issues/2612
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_driver.c    | 18 +++++++++-----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 +++-----
- drivers/usb/host/dwc_otg/dwc_otg_os_dep.h    |  6 +++++
- drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 26 +++-----------------
- 4 files changed, 25 insertions(+), 35 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-@@ -624,11 +624,7 @@ static int dwc_otg_driver_remove(
-        * Free the IRQ
-        */
-       if (otg_dev->common_irq_installed) {
--#ifdef PLATFORM_INTERFACE
--              free_irq(platform_get_irq(_dev, 0), otg_dev);
--#else
--              free_irq(_dev->irq, otg_dev);
--#endif
-+              free_irq(otg_dev->os_dep.irq_num, otg_dev);
-         } else {
-               DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
-               return REM_RETVAL(-ENXIO);
-@@ -905,7 +901,9 @@ static int dwc_otg_driver_probe(
-        */
- #if defined(PLATFORM_INTERFACE)
--      devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
-+      devirq = platform_get_irq_byname(_dev, fiq_enable ? "soft" : "usb");
-+      if (devirq < 0)
-+          devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
- #else
-       devirq = _dev->irq;
- #endif
-@@ -922,6 +920,14 @@ static int dwc_otg_driver_probe(
-       } else {
-               dwc_otg_device->common_irq_installed = 1;
-       }
-+      dwc_otg_device->os_dep.irq_num = devirq;
-+      dwc_otg_device->os_dep.fiq_num = -EINVAL;
-+      if (fiq_enable) {
-+              int devfiq = platform_get_irq_byname(_dev, "usb");
-+              if (devfiq < 0)
-+                      devfiq = platform_get_irq(_dev, 1);
-+              dwc_otg_device->os_dep.fiq_num = devfiq;
-+      }
- #ifndef IRQF_TRIGGER_LOW
- #if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -492,7 +492,7 @@ static void hcd_init_fiq(void *cookie)
- #endif
-       // Enable FIQ interrupt from USB peripheral
- #ifdef CONFIG_ARM64
--      irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
-+      irq = otg_dev->os_dep.fiq_num;
-       if (irq < 0) {
-               DWC_ERROR("Can't get SIM-FIQ irq");
-@@ -509,7 +509,7 @@ static void hcd_init_fiq(void *cookie)
-       simfiq_irq = irq;
- #else
- #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
--      irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
-+      irq = otg_dev->os_dep.fiq_num;
- #else
-       irq = INTERRUPT_VC_USB;
- #endif
-@@ -626,11 +626,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
-        * allocates the DMA buffer pool, registers the USB bus, requests the
-        * IRQ line, and calls hcd_start method.
-        */
--#ifdef PLATFORM_INTERFACE
--      retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED);
--#else
--      retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED);
--#endif
-+      retval = usb_add_hcd(hcd, otg_dev->os_dep.irq_num, IRQF_SHARED);
-       if (retval < 0) {
-               goto error2;
-       }
---- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-@@ -102,6 +102,12 @@ typedef struct os_dependent {
-       /** Base address for MPHI peripheral */
-       void *mphi_base;
-+      /** IRQ number (<0 if not valid) */
-+      int irq_num;
-+
-+      /** FIQ number (<0 if not valid) */
-+      int fiq_num;
-+
- #ifdef LM_INTERFACE
-       struct lm_device *lmdev;
- #elif  defined(PCI_INTERFACE)
---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
-@@ -1224,30 +1224,16 @@ int pcd_init(dwc_bus_dev_t *_dev)
-       /*
-        * Setup interupt handler
-        */
--#ifdef PLATFORM_INTERFACE
-       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
--                    platform_get_irq(_dev, fiq_enable ? 0 : 1));
--      retval = request_irq(platform_get_irq(_dev, fiq_enable ? 0 : 1), dwc_otg_pcd_irq,
-+                    otg_dev->os_dep.irq_num);
-+      retval = request_irq(otg_dev->os_dep.irq_num, dwc_otg_pcd_irq,
-                            IRQF_SHARED, gadget_wrapper->gadget.name,
-                            otg_dev->pcd);
-       if (retval != 0) {
--              DWC_ERROR("request of irq%d failed\n",
--                          platform_get_irq(_dev, fiq_enable ? 0 : 1));
-+              DWC_ERROR("request of irq%d failed\n", otg_dev->os_dep.irq_num);
-               free_wrapper(gadget_wrapper);
-               return -EBUSY;
-       }
--#else
--      DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
--                    _dev->irq);
--      retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
--                           IRQF_SHARED | IRQF_DISABLED,
--                           gadget_wrapper->gadget.name, otg_dev->pcd);
--      if (retval != 0) {
--              DWC_ERROR("request of irq%d failed\n", _dev->irq);
--              free_wrapper(gadget_wrapper);
--              return -EBUSY;
--      }
--#endif
-       dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
-@@ -1267,11 +1253,7 @@ void pcd_remove(dwc_bus_dev_t *_dev)
-       /*
-        * Free the IRQ
-        */
--#ifdef PLATFORM_INTERFACE
--      free_irq(platform_get_irq(_dev, 0), pcd);
--#else
--      free_irq(_dev->irq, pcd);
--#endif
-+      free_irq(otg_dev->os_dep.irq_num, pcd);
-       dwc_otg_pcd_remove(otg_dev->pcd);
-       free_wrapper(gadget_wrapper);
-       otg_dev->pcd = 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0431-overlays-Delete-the-deprecated-sdio-1bit-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0431-overlays-Delete-the-deprecated-sdio-1bit-overlay.patch
deleted file mode 100644 (file)
index dac4386..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-From 5edb8789ba5f9694698386683f2e4e97c70e765a Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 14:27:35 +0100
-Subject: [PATCH] overlays: Delete the deprecated sdio-1bit overlay
-
-Use dtoverlay=sdio,bus_width=1,gpios_22_25 instead.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 -
- .../boot/dts/overlays/sdio-1bit-overlay.dts   | 63 -------------------
- 2 files changed, 64 deletions(-)
- delete mode 100644 arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -126,7 +126,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       sc16is752-spi1.dtbo \
-       sdhost.dtbo \
-       sdio.dtbo \
--      sdio-1bit.dtbo \
-       sdtweak.dtbo \
-       smi.dtbo \
-       smi-dev.dtbo \
---- a/arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
-+++ /dev/null
-@@ -1,63 +0,0 @@
--/dts-v1/;
--/plugin/;
--
--/* Enable 1-bit SDIO from MMC interface via GPIOs 22-25. Includes sdhost overlay. */
--
--/{
--      compatible = "brcm,bcm2708";
--
--      fragment@0 {
--              target = <&mmc>;
--              __overlay__ {
--                      status = "disabled";
--              };
--      };
--
--      fragment@1 {
--              target = <&soc>;
--              __overlay__ {
--                      #address-cells = <1>;
--                      #size-cells = <1>;
--
--                      sdio_1bit: sdio@7e300000 {
--                              compatible = "brcm,bcm2835-mmc",
--                                           "brcm,bcm2835-sdhci";
--                              reg = <0x7e300000 0x100>;
--                              interrupts = <2 30>;
--                              clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
--                              dmas = <&dma 11>;
--                              dma-names = "rx-tx";
--                              brcm,overclock-50 = <0>;
--                              status = "okay";
--                              pinctrl-names = "default";
--                              pinctrl-0 = <&sdio_1bit_pins>;
--                              non-removable;
--                              bus-width = <1>;
--                      };
--              };
--      };
--
--      fragment@2 {
--              target = <&gpio>;
--              __overlay__ {
--                      sdio_1bit_pins: sdio_1bit_pins {
--                              brcm,pins = <22 23 24 25>;
--                              brcm,function = <7>; /* ALT3 = SD1 */
--                              brcm,pull = <0 2 2 2>;
--                      };
--              };
--      };
--
--      fragment@3 {
--              target-path = "/aliases";
--              __overlay__ {
--                      mmc1 = "/soc/sdio@7e300000";
--              };
--      };
--
--
--      __overrides__ {
--              poll_once = <&sdio_1bit>,"non-removable?";
--              sdio_overclock = <&sdio_1bit>,"brcm,overclock-50:0";
--      };
--};
diff --git a/target/linux/brcm2708/patches-4.19/950-0431-overlays-Standardise-on-compatible-brcm-bcm2835.patch b/target/linux/brcm2708/patches-4.19/950-0431-overlays-Standardise-on-compatible-brcm-bcm2835.patch
new file mode 100644 (file)
index 0000000..b1f95e3
--- /dev/null
@@ -0,0 +1,1767 @@
+From ba6646d6bc62108f33a7a3e95367534a0a634beb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 14 May 2019 13:33:05 +0100
+Subject: [PATCH] overlays: Standardise on compatible="brcm,bcm2835"
+
+Curb the proliferation of compatible string combinations by
+standardising on "brcm,bcm2835" to denote BCM2835 and its descendants.
+
+As nothing in the firmware or kernel is checking overlay compatible
+strings, this should be a purely cosmetic change.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts          | 2 +-
+ arch/arm/boot/dts/overlays/ads1015-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/ads1115-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/ads7846-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/adv7282m-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/adv728x-m-overlay.dts                | 2 +-
+ arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts      | 2 +-
+ .../boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts   | 2 +-
+ arch/arm/boot/dts/overlays/allo-digione-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts    | 2 +-
+ .../boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts  | 2 +-
+ .../dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts  | 2 +-
+ arch/arm/boot/dts/overlays/applepi-dac-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/at86rf233-overlay.dts                | 2 +-
+ arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts     | 2 +-
+ arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts      | 2 +-
+ .../boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts    | 2 +-
+ arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/audremap-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/balena-fin-overlay.dts               | 2 +-
+ arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts        | 2 +-
+ arch/arm/boot/dts/overlays/dht11-overlay.dts                    | 2 +-
+ arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts        | 2 +-
+ arch/arm/boot/dts/overlays/dpi18-overlay.dts                    | 2 +-
+ arch/arm/boot/dts/overlays/dpi24-overlay.dts                    | 2 +-
+ arch/arm/boot/dts/overlays/draws-overlay.dts                    | 2 +-
+ arch/arm/boot/dts/overlays/dwc-otg-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/dwc2-overlay.dts                     | 2 +-
+ arch/arm/boot/dts/overlays/enc28j60-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/exc3000-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/goodix-overlay.dts                   | 2 +-
+ arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/gpio-fan-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/gpio-ir-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts               | 2 +-
+ arch/arm/boot/dts/overlays/gpio-key-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts        | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts     | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-digi-pro-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/hy28b-overlay.dts                    | 2 +-
+ arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/i2c-mux-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts         | 2 +-
+ arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts               | 2 +-
+ arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/ilitek251x-overlay.dts               | 2 +-
+ arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts          | 2 +-
+ .../arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/justboom-dac-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/justboom-digi-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/max98357a-overlay.dts                | 2 +-
+ arch/arm/boot/dts/overlays/mbed-dac-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/mcp23017-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/mcp23s17-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/mcp3008-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/mcp3202-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/mcp342x-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/media-center-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/mmc-overlay.dts                      | 2 +-
+ arch/arm/boot/dts/overlays/mpu6050-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/mz61581-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/ov5647-overlay.dts                   | 2 +-
+ arch/arm/boot/dts/overlays/papirus-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts         | 2 +-
+ arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts          | 2 +-
+ arch/arm/boot/dts/overlays/pibell-overlay.dts                   | 2 +-
+ arch/arm/boot/dts/overlays/piglow-overlay.dts                   | 2 +-
+ arch/arm/boot/dts/overlays/piscreen-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/piscreen2r-overlay.dts               | 2 +-
+ arch/arm/boot/dts/overlays/pisound-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/pitft22-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts       | 2 +-
+ arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts        | 2 +-
+ arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts        | 2 +-
+ arch/arm/boot/dts/overlays/pps-gpio-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts                | 2 +-
+ arch/arm/boot/dts/overlays/qca7000-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts        | 2 +-
+ arch/arm/boot/dts/overlays/rpi-dac-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/rpi-display-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts               | 2 +-
+ arch/arm/boot/dts/overlays/rpi-poe-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/rpi-proto-overlay.dts                | 2 +-
+ arch/arm/boot/dts/overlays/rpi-sense-overlay.dts                | 2 +-
+ arch/arm/boot/dts/overlays/rpi-tv-overlay.dts                   | 2 +-
+ .../arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/sdhost-overlay.dts                   | 2 +-
+ arch/arm/boot/dts/overlays/sdio-overlay.dts                     | 2 +-
+ arch/arm/boot/dts/overlays/sdtweak-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/smi-nand-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/smi-overlay.dts                      | 2 +-
+ arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts            | 2 +-
+ arch/arm/boot/dts/overlays/spi-rtc-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/spi0-cs-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts               | 2 +-
+ arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/ssd1306-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/superaudioboard-overlay.dts          | 2 +-
+ arch/arm/boot/dts/overlays/sx150x-overlay.dts                   | 2 +-
+ arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/tc358743-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts                | 2 +-
+ arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/uart0-overlay.dts                    | 2 +-
+ arch/arm/boot/dts/overlays/uart1-overlay.dts                    | 2 +-
+ arch/arm/boot/dts/overlays/udrc-overlay.dts                     | 2 +-
+ arch/arm/boot/dts/overlays/upstream-overlay.dts                 | 2 +-
+ arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts             | 2 +-
+ arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts     | 2 +-
+ arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts              | 2 +-
+ arch/arm/boot/dts/overlays/vga666-overlay.dts                   | 2 +-
+ arch/arm/boot/dts/overlays/w1-gpio-overlay.dts                  | 2 +-
+ arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/wittypi-overlay.dts                  | 2 +-
+ 146 files changed, 146 insertions(+), 146 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+     
+       fragment@0 {
+               target = <&i2c>;
+--- a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2708";
++    compatible = "brcm,bcm2835";
+     fragment@0 {
+         target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/ads1015-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads1015-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2708";
++    compatible = "brcm,bcm2835";
+     /* ----------- ADS1015 ------------ */
+     fragment@0 {
+         target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/ads7846-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_vc>;
+--- a/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
+@@ -5,7 +5,7 @@
+ #include "adv7282m-overlay.dts"
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       // Fragment numbers deliberately high to avoid conflicts with the
+       // included adv7282m overlay file.
+--- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/clocks";
+--- a/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
+@@ -13,7 +13,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- 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
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2708";
++    compatible = "brcm,bcm2835";
+     fragment@0 {
+         target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
++++ b/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Overlay for Atmel AT86RF233 IEEE 802.15.4 WPAN transceiver on spi0.0 */
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
+@@ -5,7 +5,7 @@
+ #include <dt-bindings/gpio/gpio.h>
+ / {
+-      compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-        compatible = "brcm,bcm2708";
++        compatible = "brcm,bcm2835";
+         fragment@0 {
+                 target = <&audio_pins>;
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-        compatible = "brcm,bcm2708";
++        compatible = "brcm,bcm2835";
+         fragment@0 {
+                 target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
+@@ -8,7 +8,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       // There is no DPI driver module, but we need a platform device
+       // node (that doesn't already use pinctrl) to hang the pinctrl
+--- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       // There is no DPI driver module, but we need a platform device
+       // node (that doesn't already use pinctrl) to hang the pinctrl
+--- a/arch/arm/boot/dts/overlays/draws-overlay.dts
++++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++    compatible = "brcm,bcm2835";
+     fragment@0 {
+         target = <&i2s>;
+         __overlay__ {
+--- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&usb>;
+--- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&usb>;
+--- a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
++++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi2>;
+--- a/arch/arm/boot/dts/overlays/exc3000-overlay.dts
++++ b/arch/arm/boot/dts/overlays/exc3000-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&clocks>;
+--- a/arch/arm/boot/dts/overlays/goodix-overlay.dts
++++ b/arch/arm/boot/dts/overlays/goodix-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
++++ b/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
+@@ -38,7 +38,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-        compatible = "brcm,bcm2708";
++        compatible = "brcm,bcm2835";
+         fragment@0 {
+                 target-path = "/";
+--- a/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               // Configure the gpio pin controller
+--- a/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
+@@ -10,7 +10,7 @@
+ // note that GPIO3 has an external pullup on at least some boards).
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               // Configure the gpio pin controller
+--- a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/clocks";
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/clocks";
+--- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hy28a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/hy28b-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+ /{
+-   compatible = "brcm,bcm2708";
++   compatible = "brcm,bcm2835";
+    fragment@0 {
+       target = <&i2c0>;
+--- a/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+ /{
+-   compatible = "brcm,bcm2708";
++   compatible = "brcm,bcm2835";
+    fragment@0 {
+       target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s_pins>;
+--- a/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+  / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
+@@ -13,7 +13,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       // disable spi-dev on spi0.0
+       fragment@0 {
+--- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/max98357a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
+@@ -8,7 +8,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       /* Enable I2S */
+       fragment@0 {
+--- a/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
+@@ -20,7 +20,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       // disable spi-dev on spi0.0
+       fragment@0 {
+--- a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++    compatible = "brcm,bcm2835";
+     /* disable spi-dev for spi0.0 */
+     fragment@0 {
+         target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++    compatible = "brcm,bcm2835";
+     /* disable spi-dev for spi0.1 */
+     fragment@0 {
+         target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/media-center-overlay.dts
++++ b/arch/arm/boot/dts/overlays/media-center-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-        compatible = "brcm,bcm2708";
++        compatible = "brcm,bcm2835";
+         fragment@0 {
+                 target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/mz61581-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_vc>;
+--- a/arch/arm/boot/dts/overlays/papirus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/papirus-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
+@@ -11,7 +11,7 @@
+ */
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&act_led>;
+--- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
+@@ -9,7 +9,7 @@
+ */
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&uart1>;
+--- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
+@@ -16,7 +16,7 @@
+ */
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&uart0>;
+--- a/arch/arm/boot/dts/overlays/pibell-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pibell-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2708";
++    compatible = "brcm,bcm2835";
+     fragment@0 {
+         target-path = "/";
+--- a/arch/arm/boot/dts/overlays/piglow-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pisound-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts
+@@ -23,7 +23,7 @@
+ #include <dt-bindings/gpio/gpio.h>
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft22-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft22-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-        compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++        compatible = "brcm,bcm2835";
+         fragment@0 {
+                 target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-        compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++        compatible = "brcm,bcm2835";
+         fragment@0 {
+                 target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+               __overlay__ {
+--- a/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/qca7000-overlay.dts
++++ b/arch/arm/boot/dts/overlays/qca7000-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
+@@ -6,7 +6,7 @@
+ #include <dt-bindings/mfd/arizona.h>
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Provide backwards compatible aliases for the old sdhost dtparams. */
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&sdhost>;
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Provide backwards compatible aliases for the old sdhost dtparams. */
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&sdhost>;
+--- a/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
++++ b/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&smi>;
+--- a/arch/arm/boot/dts/overlays/smi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/smi-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&smi>;
+--- a/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2718";
++    compatible = "brcm,bcm2835";
+     fragment@0 {
+       target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
++++ b/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/sx150x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sx150x-overlay.dts
+@@ -22,7 +22,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       // Enable I2C#0 interface
+       fragment@0 {
+--- a/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/tc358743-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2c_vc>;
+--- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
+@@ -24,7 +24,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
+@@ -8,7 +8,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/uart0-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart0-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&uart0>;
+--- a/arch/arm/boot/dts/overlays/uart1-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart1-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&uart1>;
+--- a/arch/arm/boot/dts/overlays/udrc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+ / {
+-    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++    compatible = "brcm,bcm2835";
+     fragment@0 {
+         target = <&i2s>;
+         __overlay__ {
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -6,7 +6,7 @@
+ #include <dt-bindings/clock/bcm2835.h>
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/chosen";
+               __dormant__ {
+--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/chosen";
+--- a/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
+@@ -8,7 +8,7 @@
+ #include <dt-bindings/pinctrl/bcm2835.h>
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
+@@ -8,7 +8,7 @@
+ #include <dt-bindings/clock/bcm2835.h>
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/chosen";
+--- a/arch/arm/boot/dts/overlays/vga666-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vga666-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       // There is no VGA driver module, but we need a platform device
+       // node (that doesn't already use pinctrl) to hang the pinctrl
+--- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/";
+--- a/arch/arm/boot/dts/overlays/wittypi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/wittypi-overlay.dts
+@@ -8,7 +8,7 @@
+ / {
+-      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&leds>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0432-overlays-Remove-upstream-aux-interrupt-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0432-overlays-Remove-upstream-aux-interrupt-overlay.patch
deleted file mode 100644 (file)
index c6e54f3..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-From 2b584d25f295e07ef58efc2a60057be58015d693 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 10:06:04 +0100
-Subject: [PATCH] overlays: Remove upstream-aux-interrupt overlay
-
-We no longer have a downstream-specific auxilliary interrupt
-driver, so the overlay to disable it is no longer needed.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 -
- arch/arm/boot/dts/overlays/README             | 12 +++----
- .../upstream-aux-interrupt-overlay.dts        | 33 -------------------
- .../boot/dts/overlays/upstream-overlay.dts    |  2 +-
- 4 files changed, 6 insertions(+), 42 deletions(-)
- delete mode 100644 arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -151,7 +151,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       uart1.dtbo \
-       udrc.dtbo \
-       upstream.dtbo \
--      upstream-aux-interrupt.dtbo \
-       vc4-fkms-v3d.dtbo \
-       vc4-kms-kippah-7inch.dtbo \
-       vc4-kms-v3d.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2206,18 +2206,16 @@ Params: alsaname                Name of
- Name:   upstream
--Info:   Allow usage of downstream .dtb with upstream kernel. Comprises
--        vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
-+Info:   Allow usage of downstream .dtb with upstream kernel. Comprises the
-+        vc4-kms-v3d and dwc2 overlays.
- Load:   dtoverlay=upstream
- Params: <None>
- Name:   upstream-aux-interrupt
--Info:   Allow usage of downstream .dtb with upstream kernel by binding AUX
--        devices directly to the shared AUX interrupt line. One of the parts
--        of the 'upstream' overlay
--Load:   dtoverlay=upstream-aux-interrupt
--Params: <None>
-+Info:   This overlay has been deprecated and removed because it is no longer
-+        necessary.
-+Load:   <Deprecated>
- Name:   vc4-fkms-v3d
---- a/arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
-+++ /dev/null
-@@ -1,33 +0,0 @@
--// Overlay for missing AUX interrupt controller
--// Instead we bind all AUX devices to the generic AUX interrupt line
--/dts-v1/;
--/plugin/;
--
--/ {
--    compatible = "brcm,bcm2708";
--
--    fragment@0 {
--        target = <&uart1>;
--        __overlay__ {
--            interrupt-parent = <&intc>;
--            interrupts = <0x1 0x1d>;
--        };
--    };
--
--    fragment@1 {
--        target = <&spi1>;
--        __overlay__ {
--            interrupt-parent = <&intc>;
--            interrupts = <0x1 0x1d>;
--        };
--    };
--
--    fragment@2 {
--        target = <&spi2>;
--        __overlay__ {
--            interrupt-parent = <&intc>;
--            interrupts = <0x1 0x1d>;
--        };
--    };
--};
--
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -1,4 +1,4 @@
--// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg upstream-aux-interrupt-overlay.dts,
-+// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg
- /dts-v1/;
- /plugin/;
diff --git a/target/linux/brcm2708/patches-4.19/950-0432-vc4-Remove-interrupt-and-DMA-trampling.patch b/target/linux/brcm2708/patches-4.19/950-0432-vc4-Remove-interrupt-and-DMA-trampling.patch
new file mode 100644 (file)
index 0000000..34fe856
--- /dev/null
@@ -0,0 +1,121 @@
+From 343e24f4a112e1118e955fd58316e71b208a22f3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 22 May 2019 12:58:47 +0100
+Subject: [PATCH] vc4: Remove interrupt and DMA trampling
+
+As part of the effort to clean up the overlays, remove the interrupt
+and DMA mask declarations from the vc4 overlays which just duplicate
+that which is in the base DTBs.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../boot/dts/overlays/vc4-fkms-v3d-overlay.dts |  8 --------
+ .../boot/dts/overlays/vc4-kms-v3d-overlay.dts  | 18 ++----------------
+ 2 files changed, 2 insertions(+), 24 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
+@@ -60,7 +60,6 @@
+       fragment@7 {
+               target = <&v3d>;
+               __overlay__  {
+-                      interrupts = <1 10>;
+                       status = "okay";
+               };
+       };
+@@ -72,13 +71,6 @@
+               };
+       };
+-      fragment@9 {
+-              target-path = "/soc/dma";
+-              __overlay__ {
+-                      brcm,dma-channel-mask = <0x7f35>;
+-              };
+-      };
+-
+       __overrides__ {
+               cma-256 = <0>,"+0-1-2-3-4";
+               cma-192 = <0>,"-0+1-2-3-4";
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
+@@ -62,7 +62,6 @@
+       fragment@7 {
+               target = <&pixelvalve0>;
+               __overlay__  {
+-                      interrupts = <2 13>; /* pwa0 */
+                       status = "okay";
+               };
+       };
+@@ -70,7 +69,6 @@
+       fragment@8 {
+               target = <&pixelvalve1>;
+               __overlay__  {
+-                      interrupts = <2 14>; /* pwa1 */
+                       status = "okay";
+               };
+       };
+@@ -78,7 +76,6 @@
+       fragment@9 {
+               target = <&pixelvalve2>;
+               __overlay__  {
+-                      interrupts = <2 10>; /* pixelvalve */
+                       status = "okay";
+               };
+       };
+@@ -86,7 +83,6 @@
+       fragment@10 {
+               target = <&hvs>;
+               __overlay__  {
+-                      interrupts = <2 1>;
+                       status = "okay";
+               };
+       };
+@@ -94,7 +90,6 @@
+       fragment@11 {
+               target = <&hdmi>;
+               __overlay__  {
+-                      interrupts = <2 8>, <2 9>;
+                       status = "okay";
+               };
+       };
+@@ -102,7 +97,6 @@
+       fragment@12 {
+               target = <&v3d>;
+               __overlay__  {
+-                      interrupts = <1 10>;
+                       status = "okay";
+               };
+       };
+@@ -115,14 +109,6 @@
+       };
+       fragment@14 {
+-              target-path = "/soc/dma";
+-              __overlay__ {
+-                      brcm,dma-channel-mask = <0x7f35>;
+-              };
+-      };
+-
+-
+-      fragment@15 {
+               target = <&clocks>;
+               __overlay__  {
+                       claim-clocks = <
+@@ -134,14 +120,14 @@
+               };
+       };
+-      fragment@16 {
++      fragment@15 {
+               target = <&vec>;
+               __overlay__  {
+                       status = "okay";
+               };
+       };
+-      fragment@17 {
++      fragment@16 {
+               target = <&txp>;
+               __overlay__  {
+                       status = "okay";
diff --git a/target/linux/brcm2708/patches-4.19/950-0433-BCM270X_DT-Add-non-removable-clone-of-mmc-node.patch b/target/linux/brcm2708/patches-4.19/950-0433-BCM270X_DT-Add-non-removable-clone-of-mmc-node.patch
new file mode 100644 (file)
index 0000000..8e854bd
--- /dev/null
@@ -0,0 +1,206 @@
+From c63b13bddf317347ba0b69807c1591526d50ba47 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 14:29:38 +0100
+Subject: [PATCH] BCM270X_DT: Add non-removable clone of mmc node
+
+non-removable is a boolean property, and as such can't be unset by an
+overlay if it is set in a base DTB. Until now the workaround for this
+problem has been for overlays to clone non-removable nodes without
+the offending property, but this involves a lot of unnecessary
+replication. Instead, add a clone of the mmc node with non-removable
+already set to the base DTB, selecting the required version using
+the status properties.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi-0-w.dts       |  4 +--
+ arch/arm/boot/dts/bcm2708-rpi.dtsi          |  3 +-
+ arch/arm/boot/dts/bcm270x.dtsi              | 13 ++++++++
+ 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/overlays/mmc-overlay.dts  |  7 +++++
+ arch/arm/boot/dts/overlays/sdio-overlay.dts | 33 +++++++--------------
+ 7 files changed, 38 insertions(+), 32 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
+@@ -14,6 +14,7 @@
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart0;
++              mmc1 = &mmcnr;
+       };
+ };
+@@ -73,10 +74,9 @@
+       };
+ };
+-&mmc {
++&mmcnr {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio_pins>;
+-      non-removable;
+       bus-width = <4>;
+       status = "okay";
+ };
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -118,7 +118,8 @@
+               sd_force_pio = <&sdhost>,"brcm,force-pio?";
+               sd_pio_limit = <&sdhost>,"brcm,pio-limit:0";
+               sd_debug     = <&sdhost>,"brcm,debug";
+-              sdio_overclock = <&mmc>,"brcm,overclock-50:0";
++              sdio_overclock = <&mmc>,"brcm,overclock-50:0",
++                               <&mmcnr>,"brcm,overclock-50:0";
+               axiperf      = <&axiperf>,"status";
+       };
+ };
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -79,6 +79,19 @@
+                       status = "disabled";
+               };
++              /* A clone of mmc but with non-removable set */
++              mmcnr: mmcnr@7e300000 {
++                      compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
++                      reg = <0x7e300000 0x100>;
++                      interrupts = <2 30>;
++                      clocks = <&clocks BCM2835_CLOCK_EMMC>;
++                      dmas = <&dma 11>;
++                      dma-names = "rx-tx";
++                      brcm,overclock-50 = <0>;
++                      non-removable;
++                      status = "disabled";
++              };
++
+               hvs: hvs@7e400000 {
+                       /* Add alias */
+                       status = "disabled";
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -15,6 +15,7 @@
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart0;
++              mmc1 = &mmcnr;
+       };
+ };
+@@ -74,13 +75,11 @@
+       };
+ };
+-&mmc {
++&mmcnr {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio_pins>;
+-      non-removable;
+       bus-width = <4>;
+       status = "okay";
+-      brcm,overclock-50 = <0>;
+ };
+ &firmware {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -15,6 +15,7 @@
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart0;
++              mmc1 = &mmcnr;
+       };
+ };
+@@ -74,13 +75,11 @@
+       };
+ };
+-&mmc {
++&mmcnr {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio_pins>;
+-      non-removable;
+       bus-width = <4>;
+       status = "okay";
+-      brcm,overclock-50 = <0>;
+ };
+ &soc {
+--- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
+@@ -33,6 +33,13 @@
+               };
+       };
++      fragment@3 {
++              target = <&mmcnr>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
+       __overrides__ {
+               overclock_50     = <&frag0>,"brcm,overclock-50:0";
+       };
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -1,39 +1,26 @@
+ /dts-v1/;
+ /plugin/;
+-/* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
++/* Enable SDIO from MMC interface via various GPIO groups */
+ /{
+       compatible = "brcm,bcm2835";
+       fragment@0 {
+-              target = <&mmc>;
++              target = <&mmcnr>;
+               __overlay__ {
+                       status = "disabled";
+               };
+       };
+       fragment@1 {
+-              target = <&soc>;
+-              __overlay__ {
+-                      #address-cells = <1>;
+-                      #size-cells = <1>;
+-
+-                      sdio_ovl: sdio@7e300000 {
+-                              compatible = "brcm,bcm2835-mmc",
+-                                           "brcm,bcm2835-sdhci";
+-                              reg = <0x7e300000 0x100>;
+-                              interrupts = <2 30>;
+-                              clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
+-                              dmas = <&dma 11>;
+-                              dma-names = "rx-tx";
+-                              brcm,overclock-50 = <0>;
+-                              status = "okay";
+-                              pinctrl-names = "default";
+-                              pinctrl-0 = <&sdio_ovl_pins>;
+-                              non-removable;
+-                              bus-width = <4>;
+-                      };
++              target = <&mmc>;
++              sdio_ovl: __overlay__ {
++                      pinctrl-0 = <&sdio_ovl_pins>;
++                      pinctrl-names = "default";
++                      non-removable;
++                      bus-width = <4>;
++                      status = "okay";
+               };
+       };
+@@ -75,7 +62,7 @@
+       fragment@6 {
+               target-path = "/aliases";
+               __overlay__ {
+-                      mmc1 = "/soc/sdio@7e300000";
++                      mmc1 = "/soc/mmc@7e300000";
+               };
+       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0433-overlays-Standardise-on-compatible-brcm-bcm2835.patch b/target/linux/brcm2708/patches-4.19/950-0433-overlays-Standardise-on-compatible-brcm-bcm2835.patch
deleted file mode 100644 (file)
index b1f95e3..0000000
+++ /dev/null
@@ -1,1767 +0,0 @@
-From ba6646d6bc62108f33a7a3e95367534a0a634beb Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 14 May 2019 13:33:05 +0100
-Subject: [PATCH] overlays: Standardise on compatible="brcm,bcm2835"
-
-Curb the proliferation of compatible string combinations by
-standardising on "brcm,bcm2835" to denote BCM2835 and its descendants.
-
-As nothing in the firmware or kernel is checking overlay compatible
-strings, this should be a purely cosmetic change.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts          | 2 +-
- arch/arm/boot/dts/overlays/ads1015-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/ads1115-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/ads7846-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/adv7282m-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/adv728x-m-overlay.dts                | 2 +-
- arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts      | 2 +-
- .../boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts   | 2 +-
- arch/arm/boot/dts/overlays/allo-digione-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts    | 2 +-
- .../boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts  | 2 +-
- .../dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts  | 2 +-
- arch/arm/boot/dts/overlays/applepi-dac-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/at86rf233-overlay.dts                | 2 +-
- arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts     | 2 +-
- arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts      | 2 +-
- .../boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts    | 2 +-
- arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/audremap-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/balena-fin-overlay.dts               | 2 +-
- arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts        | 2 +-
- arch/arm/boot/dts/overlays/dht11-overlay.dts                    | 2 +-
- arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts           | 2 +-
- arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts        | 2 +-
- arch/arm/boot/dts/overlays/dpi18-overlay.dts                    | 2 +-
- arch/arm/boot/dts/overlays/dpi24-overlay.dts                    | 2 +-
- arch/arm/boot/dts/overlays/draws-overlay.dts                    | 2 +-
- arch/arm/boot/dts/overlays/dwc-otg-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/dwc2-overlay.dts                     | 2 +-
- arch/arm/boot/dts/overlays/enc28j60-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/exc3000-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/goodix-overlay.dts                   | 2 +-
- arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/gpio-fan-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/gpio-ir-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts               | 2 +-
- arch/arm/boot/dts/overlays/gpio-key-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts        | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts     | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts           | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-digi-pro-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/hy28b-overlay.dts                    | 2 +-
- arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/i2c-mux-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts         | 2 +-
- arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts               | 2 +-
- arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/ilitek251x-overlay.dts               | 2 +-
- arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts          | 2 +-
- .../arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/justboom-dac-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/justboom-digi-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/max98357a-overlay.dts                | 2 +-
- arch/arm/boot/dts/overlays/mbed-dac-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/mcp23017-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/mcp23s17-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/mcp3008-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/mcp3202-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/mcp342x-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/media-center-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/mmc-overlay.dts                      | 2 +-
- arch/arm/boot/dts/overlays/mpu6050-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/mz61581-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/ov5647-overlay.dts                   | 2 +-
- arch/arm/boot/dts/overlays/papirus-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts           | 2 +-
- arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts         | 2 +-
- arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts          | 2 +-
- arch/arm/boot/dts/overlays/pibell-overlay.dts                   | 2 +-
- arch/arm/boot/dts/overlays/piglow-overlay.dts                   | 2 +-
- arch/arm/boot/dts/overlays/piscreen-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/piscreen2r-overlay.dts               | 2 +-
- arch/arm/boot/dts/overlays/pisound-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/pitft22-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts       | 2 +-
- arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts        | 2 +-
- arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts        | 2 +-
- arch/arm/boot/dts/overlays/pps-gpio-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts                | 2 +-
- arch/arm/boot/dts/overlays/qca7000-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts           | 2 +-
- arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts        | 2 +-
- arch/arm/boot/dts/overlays/rpi-dac-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/rpi-display-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts               | 2 +-
- arch/arm/boot/dts/overlays/rpi-poe-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/rpi-proto-overlay.dts                | 2 +-
- arch/arm/boot/dts/overlays/rpi-sense-overlay.dts                | 2 +-
- arch/arm/boot/dts/overlays/rpi-tv-overlay.dts                   | 2 +-
- .../arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts           | 2 +-
- arch/arm/boot/dts/overlays/sdhost-overlay.dts                   | 2 +-
- arch/arm/boot/dts/overlays/sdio-overlay.dts                     | 2 +-
- arch/arm/boot/dts/overlays/sdtweak-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/smi-nand-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/smi-overlay.dts                      | 2 +-
- arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts            | 2 +-
- arch/arm/boot/dts/overlays/spi-rtc-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/spi0-cs-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts               | 2 +-
- arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/ssd1306-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/superaudioboard-overlay.dts          | 2 +-
- arch/arm/boot/dts/overlays/sx150x-overlay.dts                   | 2 +-
- arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts           | 2 +-
- arch/arm/boot/dts/overlays/tc358743-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/tinylcd35-overlay.dts                | 2 +-
- arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/uart0-overlay.dts                    | 2 +-
- arch/arm/boot/dts/overlays/uart1-overlay.dts                    | 2 +-
- arch/arm/boot/dts/overlays/udrc-overlay.dts                     | 2 +-
- arch/arm/boot/dts/overlays/upstream-overlay.dts                 | 2 +-
- arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts             | 2 +-
- arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts     | 2 +-
- arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts              | 2 +-
- arch/arm/boot/dts/overlays/vga666-overlay.dts                   | 2 +-
- arch/arm/boot/dts/overlays/w1-gpio-overlay.dts                  | 2 +-
- arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts           | 2 +-
- arch/arm/boot/dts/overlays/wittypi-overlay.dts                  | 2 +-
- 146 files changed, 146 insertions(+), 146 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-     
-       fragment@0 {
-               target = <&i2c>;
---- a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2708";
-+    compatible = "brcm,bcm2835";
-     fragment@0 {
-         target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/ads1015-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ads1015-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2708";
-+    compatible = "brcm,bcm2835";
-     /* ----------- ADS1015 ------------ */
-     fragment@0 {
-         target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/ads7846-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_vc>;
---- a/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
-@@ -5,7 +5,7 @@
- #include "adv7282m-overlay.dts"
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       // Fragment numbers deliberately high to avoid conflicts with the
-       // included adv7282m overlay file.
---- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/clocks";
---- a/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
-@@ -13,7 +13,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- 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
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2708";
-+    compatible = "brcm,bcm2835";
-     fragment@0 {
-         target = <&sound>;
---- a/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
-@@ -4,7 +4,7 @@
- /* Overlay for Atmel AT86RF233 IEEE 802.15.4 WPAN transceiver on spi0.0 */
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-@@ -5,7 +5,7 @@
- #include <dt-bindings/gpio/gpio.h>
- / {
--      compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--        compatible = "brcm,bcm2708";
-+        compatible = "brcm,bcm2835";
-         fragment@0 {
-                 target = <&audio_pins>;
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--        compatible = "brcm,bcm2708";
-+        compatible = "brcm,bcm2835";
-         fragment@0 {
-                 target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
-@@ -8,7 +8,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
-@@ -9,7 +9,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&sound>;
---- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       // There is no DPI driver module, but we need a platform device
-       // node (that doesn't already use pinctrl) to hang the pinctrl
---- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       // There is no DPI driver module, but we need a platform device
-       // node (that doesn't already use pinctrl) to hang the pinctrl
---- a/arch/arm/boot/dts/overlays/draws-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+    compatible = "brcm,bcm2835";
-     fragment@0 {
-         target = <&i2s>;
-         __overlay__ {
---- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&usb>;
---- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&usb>;
---- a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi2>;
---- a/arch/arm/boot/dts/overlays/exc3000-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/exc3000-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&clocks>;
---- a/arch/arm/boot/dts/overlays/goodix-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/goodix-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
-@@ -38,7 +38,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--        compatible = "brcm,bcm2708";
-+        compatible = "brcm,bcm2835";
-         fragment@0 {
-                 target-path = "/";
---- a/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               // Configure the gpio pin controller
---- a/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
-@@ -10,7 +10,7 @@
- // note that GPIO3 has an external pullup on at least some boards).
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               // Configure the gpio pin controller
---- a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/clocks";
---- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/clocks";
---- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hy28a-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/hy28b-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&sound>;
---- a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
-@@ -9,7 +9,7 @@
- /plugin/;
- /{
--   compatible = "brcm,bcm2708";
-+   compatible = "brcm,bcm2835";
-    fragment@0 {
-       target = <&i2c0>;
---- a/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
-@@ -9,7 +9,7 @@
- /plugin/;
- /{
--   compatible = "brcm,bcm2708";
-+   compatible = "brcm,bcm2835";
-    fragment@0 {
-       target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s_pins>;
---- a/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-  / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
-@@ -13,7 +13,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       // disable spi-dev on spi0.0
-       fragment@0 {
---- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/max98357a-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
-@@ -8,7 +8,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       /* Enable I2S */
-       fragment@0 {
---- a/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
-@@ -20,7 +20,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       // disable spi-dev on spi0.0
-       fragment@0 {
---- a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+    compatible = "brcm,bcm2835";
-     /* disable spi-dev for spi0.0 */
-     fragment@0 {
-         target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+    compatible = "brcm,bcm2835";
-     /* disable spi-dev for spi0.1 */
-     fragment@0 {
-         target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/media-center-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/media-center-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--        compatible = "brcm,bcm2708";
-+        compatible = "brcm,bcm2835";
-         fragment@0 {
-                 target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/mz61581-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_vc>;
---- a/arch/arm/boot/dts/overlays/papirus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/papirus-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-@@ -11,7 +11,7 @@
- */
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&act_led>;
---- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-@@ -9,7 +9,7 @@
- */
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&uart1>;
---- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-@@ -16,7 +16,7 @@
- */
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&uart0>;
---- a/arch/arm/boot/dts/overlays/pibell-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pibell-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2708";
-+    compatible = "brcm,bcm2835";
-     fragment@0 {
-         target-path = "/";
---- a/arch/arm/boot/dts/overlays/piglow-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pisound-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts
-@@ -23,7 +23,7 @@
- #include <dt-bindings/gpio/gpio.h>
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft22-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft22-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--        compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+        compatible = "brcm,bcm2835";
-         fragment@0 {
-                 target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--        compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+        compatible = "brcm,bcm2835";
-         fragment@0 {
-                 target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
-               __overlay__ {
---- a/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/qca7000-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/qca7000-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-@@ -6,7 +6,7 @@
- #include <dt-bindings/mfd/arizona.h>
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-@@ -4,7 +4,7 @@
- /* Provide backwards compatible aliases for the old sdhost dtparams. */
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&sdhost>;
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -4,7 +4,7 @@
- /* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
-@@ -4,7 +4,7 @@
- /* Provide backwards compatible aliases for the old sdhost dtparams. */
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&sdhost>;
---- a/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&smi>;
---- a/arch/arm/boot/dts/overlays/smi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/smi-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&smi>;
---- a/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2718";
-+    compatible = "brcm,bcm2835";
-     fragment@0 {
-       target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&sound>;
---- a/arch/arm/boot/dts/overlays/sx150x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sx150x-overlay.dts
-@@ -22,7 +22,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       // Enable I2C#0 interface
-       fragment@0 {
---- a/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/tc358743-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&i2c_vc>;
---- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-@@ -24,7 +24,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-@@ -8,7 +8,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/uart0-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart0-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&uart0>;
---- a/arch/arm/boot/dts/overlays/uart1-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart1-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&uart1>;
---- a/arch/arm/boot/dts/overlays/udrc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
- / {
--    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+    compatible = "brcm,bcm2835";
-     fragment@0 {
-         target = <&i2s>;
-         __overlay__ {
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -6,7 +6,7 @@
- #include <dt-bindings/clock/bcm2835.h>
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/chosen";
-               __dormant__ {
---- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/chosen";
---- a/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
-@@ -8,7 +8,7 @@
- #include <dt-bindings/pinctrl/bcm2835.h>
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-@@ -8,7 +8,7 @@
- #include <dt-bindings/clock/bcm2835.h>
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/chosen";
---- a/arch/arm/boot/dts/overlays/vga666-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vga666-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       // There is no VGA driver module, but we need a platform device
-       // node (that doesn't already use pinctrl) to hang the pinctrl
---- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
- / {
--      compatible = "brcm,bcm2708";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target-path = "/";
---- a/arch/arm/boot/dts/overlays/wittypi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/wittypi-overlay.dts
-@@ -8,7 +8,7 @@
- / {
--      compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+      compatible = "brcm,bcm2835";
-       fragment@0 {
-               target = <&leds>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0434-BCM270X_DT-usb-Refactor-DTS-and-overlays.patch b/target/linux/brcm2708/patches-4.19/950-0434-BCM270X_DT-usb-Refactor-DTS-and-overlays.patch
new file mode 100644 (file)
index 0000000..162c28e
--- /dev/null
@@ -0,0 +1,60 @@
+From 61c44e24ea212b92bf6a420b94070ee6fc715811 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 8 May 2019 10:08:31 +0100
+Subject: [PATCH] BCM270X_DT: usb: Refactor DTS and overlays
+
+Move the IRQ interrupt declaration in the usb node before the FIQ
+declaration, so that the dwc2 driver will find it. Name the
+interrupts appropriately so that the dwc_otg driver can still find
+them. Then remove the interrupt rewriting from the overlays.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm270x.dtsi                 | 6 ++++--
+ arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 6 ------
+ arch/arm/boot/dts/overlays/dwc2-overlay.dts    | 2 --
+ 3 files changed, 4 insertions(+), 10 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -131,8 +131,10 @@
+                       compatible = "brcm,bcm2708-usb";
+                       reg = <0x7e980000 0x10000>,
+                             <0x7e006000 0x1000>;
+-                      interrupts = <2 0>,
+-                                   <1 9>;
++                      interrupt-names = "usb",
++                                        "soft";
++                      interrupts = <1 9>,
++                                   <2 0>;
+               };
+               v3d@7ec00000 { /* vd3 */
+--- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
+@@ -6,14 +6,8 @@
+       fragment@0 {
+               target = <&usb>;
+-              #address-cells = <1>;
+-              #size-cells = <1>;
+               __overlay__ {
+                       compatible = "brcm,bcm2708-usb";
+-                      reg = <0x7e980000 0x10000>,
+-                            <0x7e006000 0x1000>;
+-                      interrupts = <2 0>,
+-                                   <1 9>;
+                       status = "okay";
+               };
+       };
+--- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
+@@ -10,8 +10,6 @@
+               #size-cells = <1>;
+               dwc2_usb: __overlay__ {
+                       compatible = "brcm,bcm2835-usb";
+-                      reg = <0x7e980000 0x10000>;
+-                      interrupts = <1 9>;
+                       dr_mode = "otg";
+                       g-np-tx-fifo-size = <32>;
+                       g-rx-fifo-size = <256>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0434-vc4-Remove-interrupt-and-DMA-trampling.patch b/target/linux/brcm2708/patches-4.19/950-0434-vc4-Remove-interrupt-and-DMA-trampling.patch
deleted file mode 100644 (file)
index 34fe856..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-From 343e24f4a112e1118e955fd58316e71b208a22f3 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 22 May 2019 12:58:47 +0100
-Subject: [PATCH] vc4: Remove interrupt and DMA trampling
-
-As part of the effort to clean up the overlays, remove the interrupt
-and DMA mask declarations from the vc4 overlays which just duplicate
-that which is in the base DTBs.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../boot/dts/overlays/vc4-fkms-v3d-overlay.dts |  8 --------
- .../boot/dts/overlays/vc4-kms-v3d-overlay.dts  | 18 ++----------------
- 2 files changed, 2 insertions(+), 24 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-@@ -60,7 +60,6 @@
-       fragment@7 {
-               target = <&v3d>;
-               __overlay__  {
--                      interrupts = <1 10>;
-                       status = "okay";
-               };
-       };
-@@ -72,13 +71,6 @@
-               };
-       };
--      fragment@9 {
--              target-path = "/soc/dma";
--              __overlay__ {
--                      brcm,dma-channel-mask = <0x7f35>;
--              };
--      };
--
-       __overrides__ {
-               cma-256 = <0>,"+0-1-2-3-4";
-               cma-192 = <0>,"-0+1-2-3-4";
---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-@@ -62,7 +62,6 @@
-       fragment@7 {
-               target = <&pixelvalve0>;
-               __overlay__  {
--                      interrupts = <2 13>; /* pwa0 */
-                       status = "okay";
-               };
-       };
-@@ -70,7 +69,6 @@
-       fragment@8 {
-               target = <&pixelvalve1>;
-               __overlay__  {
--                      interrupts = <2 14>; /* pwa1 */
-                       status = "okay";
-               };
-       };
-@@ -78,7 +76,6 @@
-       fragment@9 {
-               target = <&pixelvalve2>;
-               __overlay__  {
--                      interrupts = <2 10>; /* pixelvalve */
-                       status = "okay";
-               };
-       };
-@@ -86,7 +83,6 @@
-       fragment@10 {
-               target = <&hvs>;
-               __overlay__  {
--                      interrupts = <2 1>;
-                       status = "okay";
-               };
-       };
-@@ -94,7 +90,6 @@
-       fragment@11 {
-               target = <&hdmi>;
-               __overlay__  {
--                      interrupts = <2 8>, <2 9>;
-                       status = "okay";
-               };
-       };
-@@ -102,7 +97,6 @@
-       fragment@12 {
-               target = <&v3d>;
-               __overlay__  {
--                      interrupts = <1 10>;
-                       status = "okay";
-               };
-       };
-@@ -115,14 +109,6 @@
-       };
-       fragment@14 {
--              target-path = "/soc/dma";
--              __overlay__ {
--                      brcm,dma-channel-mask = <0x7f35>;
--              };
--      };
--
--
--      fragment@15 {
-               target = <&clocks>;
-               __overlay__  {
-                       claim-clocks = <
-@@ -134,14 +120,14 @@
-               };
-       };
--      fragment@16 {
-+      fragment@15 {
-               target = <&vec>;
-               __overlay__  {
-                       status = "okay";
-               };
-       };
--      fragment@17 {
-+      fragment@16 {
-               target = <&txp>;
-               __overlay__  {
-                       status = "okay";
diff --git a/target/linux/brcm2708/patches-4.19/950-0435-BCM270X_DT-Add-non-removable-clone-of-mmc-node.patch b/target/linux/brcm2708/patches-4.19/950-0435-BCM270X_DT-Add-non-removable-clone-of-mmc-node.patch
deleted file mode 100644 (file)
index 8e854bd..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-From c63b13bddf317347ba0b69807c1591526d50ba47 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 14:29:38 +0100
-Subject: [PATCH] BCM270X_DT: Add non-removable clone of mmc node
-
-non-removable is a boolean property, and as such can't be unset by an
-overlay if it is set in a base DTB. Until now the workaround for this
-problem has been for overlays to clone non-removable nodes without
-the offending property, but this involves a lot of unnecessary
-replication. Instead, add a clone of the mmc node with non-removable
-already set to the base DTB, selecting the required version using
-the status properties.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi-0-w.dts       |  4 +--
- arch/arm/boot/dts/bcm2708-rpi.dtsi          |  3 +-
- arch/arm/boot/dts/bcm270x.dtsi              | 13 ++++++++
- 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/overlays/mmc-overlay.dts  |  7 +++++
- arch/arm/boot/dts/overlays/sdio-overlay.dts | 33 +++++++--------------
- 7 files changed, 38 insertions(+), 32 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-@@ -14,6 +14,7 @@
-       aliases {
-               serial0 = &uart1;
-               serial1 = &uart0;
-+              mmc1 = &mmcnr;
-       };
- };
-@@ -73,10 +74,9 @@
-       };
- };
--&mmc {
-+&mmcnr {
-       pinctrl-names = "default";
-       pinctrl-0 = <&sdio_pins>;
--      non-removable;
-       bus-width = <4>;
-       status = "okay";
- };
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -118,7 +118,8 @@
-               sd_force_pio = <&sdhost>,"brcm,force-pio?";
-               sd_pio_limit = <&sdhost>,"brcm,pio-limit:0";
-               sd_debug     = <&sdhost>,"brcm,debug";
--              sdio_overclock = <&mmc>,"brcm,overclock-50:0";
-+              sdio_overclock = <&mmc>,"brcm,overclock-50:0",
-+                               <&mmcnr>,"brcm,overclock-50:0";
-               axiperf      = <&axiperf>,"status";
-       };
- };
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -79,6 +79,19 @@
-                       status = "disabled";
-               };
-+              /* A clone of mmc but with non-removable set */
-+              mmcnr: mmcnr@7e300000 {
-+                      compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
-+                      reg = <0x7e300000 0x100>;
-+                      interrupts = <2 30>;
-+                      clocks = <&clocks BCM2835_CLOCK_EMMC>;
-+                      dmas = <&dma 11>;
-+                      dma-names = "rx-tx";
-+                      brcm,overclock-50 = <0>;
-+                      non-removable;
-+                      status = "disabled";
-+              };
-+
-               hvs: hvs@7e400000 {
-                       /* Add alias */
-                       status = "disabled";
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-@@ -15,6 +15,7 @@
-       aliases {
-               serial0 = &uart1;
-               serial1 = &uart0;
-+              mmc1 = &mmcnr;
-       };
- };
-@@ -74,13 +75,11 @@
-       };
- };
--&mmc {
-+&mmcnr {
-       pinctrl-names = "default";
-       pinctrl-0 = <&sdio_pins>;
--      non-removable;
-       bus-width = <4>;
-       status = "okay";
--      brcm,overclock-50 = <0>;
- };
- &firmware {
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-@@ -15,6 +15,7 @@
-       aliases {
-               serial0 = &uart1;
-               serial1 = &uart0;
-+              mmc1 = &mmcnr;
-       };
- };
-@@ -74,13 +75,11 @@
-       };
- };
--&mmc {
-+&mmcnr {
-       pinctrl-names = "default";
-       pinctrl-0 = <&sdio_pins>;
--      non-removable;
-       bus-width = <4>;
-       status = "okay";
--      brcm,overclock-50 = <0>;
- };
- &soc {
---- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
-@@ -33,6 +33,13 @@
-               };
-       };
-+      fragment@3 {
-+              target = <&mmcnr>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
-+
-       __overrides__ {
-               overclock_50     = <&frag0>,"brcm,overclock-50:0";
-       };
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -1,39 +1,26 @@
- /dts-v1/;
- /plugin/;
--/* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
-+/* Enable SDIO from MMC interface via various GPIO groups */
- /{
-       compatible = "brcm,bcm2835";
-       fragment@0 {
--              target = <&mmc>;
-+              target = <&mmcnr>;
-               __overlay__ {
-                       status = "disabled";
-               };
-       };
-       fragment@1 {
--              target = <&soc>;
--              __overlay__ {
--                      #address-cells = <1>;
--                      #size-cells = <1>;
--
--                      sdio_ovl: sdio@7e300000 {
--                              compatible = "brcm,bcm2835-mmc",
--                                           "brcm,bcm2835-sdhci";
--                              reg = <0x7e300000 0x100>;
--                              interrupts = <2 30>;
--                              clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
--                              dmas = <&dma 11>;
--                              dma-names = "rx-tx";
--                              brcm,overclock-50 = <0>;
--                              status = "okay";
--                              pinctrl-names = "default";
--                              pinctrl-0 = <&sdio_ovl_pins>;
--                              non-removable;
--                              bus-width = <4>;
--                      };
-+              target = <&mmc>;
-+              sdio_ovl: __overlay__ {
-+                      pinctrl-0 = <&sdio_ovl_pins>;
-+                      pinctrl-names = "default";
-+                      non-removable;
-+                      bus-width = <4>;
-+                      status = "okay";
-               };
-       };
-@@ -75,7 +62,7 @@
-       fragment@6 {
-               target-path = "/aliases";
-               __overlay__ {
--                      mmc1 = "/soc/sdio@7e300000";
-+                      mmc1 = "/soc/mmc@7e300000";
-               };
-       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0435-overlays-Update-upstream-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0435-overlays-Update-upstream-overlay.patch
new file mode 100644 (file)
index 0000000..4547668
--- /dev/null
@@ -0,0 +1,126 @@
+From 61c487e6a1985e52307d6df5834b610a50219819 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 22 May 2019 13:29:56 +0100
+Subject: [PATCH] overlays: Update upstream overlay
+
+The recent DT/overlay changes have had a corresponding effect on the
+upstream overlay, which is a composite of the vc4-kms-v3d and dwc2
+overlays.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../boot/dts/overlays/upstream-overlay.dts    | 41 ++-----------------
+ 1 file changed, 3 insertions(+), 38 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -52,42 +52,36 @@
+       fragment@7 {
+               target = <&pixelvalve0>;
+               __overlay__ {
+-                      interrupts = <2 13>;
+                       status = "okay";
+               };
+       };
+       fragment@8 {
+               target = <&pixelvalve1>;
+               __overlay__ {
+-                      interrupts = <2 14>;
+                       status = "okay";
+               };
+       };
+       fragment@9 {
+               target = <&pixelvalve2>;
+               __overlay__ {
+-                      interrupts = <2 10>;
+                       status = "okay";
+               };
+       };
+       fragment@10 {
+               target = <&hvs>;
+               __overlay__ {
+-                      interrupts = <2 1>;
+                       status = "okay";
+               };
+       };
+       fragment@11 {
+               target = <&hdmi>;
+               __overlay__ {
+-                      interrupts = <2 8>, <2 9>;
+                       status = "okay";
+               };
+       };
+       fragment@12 {
+               target = <&v3d>;
+               __overlay__ {
+-                      interrupts = <1 10>;
+                       status = "okay";
+               };
+       };
+@@ -98,37 +92,29 @@
+               };
+       };
+       fragment@14 {
+-              target-path = "/soc/dma";
+-              __overlay__ {
+-                      brcm,dma-channel-mask = <0x7f35>;
+-              };
+-      };
+-      fragment@15 {
+               target = <&clocks>;
+               __overlay__ {
+                       claim-clocks = <BCM2835_PLLD_DSI0 BCM2835_PLLD_DSI1 BCM2835_PLLH_AUX BCM2835_PLLH_PIX>;
+               };
+       };
+-      fragment@16 {
++      fragment@15 {
+               target = <&vec>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@17 {
++      fragment@16 {
+               target = <&txp>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@18 {
++      fragment@17 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               dwc2_usb: __overlay__ {
+                       compatible = "brcm,bcm2835-usb";
+-                      reg = <0x7e980000 0x10000>;
+-                      interrupts = <1 9>;
+                       dr_mode = "otg";
+                       g-np-tx-fifo-size = <32>;
+                       g-rx-fifo-size = <256>;
+@@ -136,25 +122,4 @@
+                       status = "okay";
+               };
+       };
+-      fragment@19 {
+-              target = <&uart1>;
+-              __overlay__ {
+-                      interrupt-parent = <&intc>;
+-                      interrupts = <0x1 0x1d>;
+-              };
+-      };
+-      fragment@20 {
+-              target = <&spi1>;
+-              __overlay__ {
+-                      interrupt-parent = <&intc>;
+-                      interrupts = <0x1 0x1d>;
+-              };
+-      };
+-      fragment@21 {
+-              target = <&spi2>;
+-              __overlay__ {
+-                      interrupt-parent = <&intc>;
+-                      interrupts = <0x1 0x1d>;
+-              };
+-      };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0436-BCM270X_DT-usb-Refactor-DTS-and-overlays.patch b/target/linux/brcm2708/patches-4.19/950-0436-BCM270X_DT-usb-Refactor-DTS-and-overlays.patch
deleted file mode 100644 (file)
index 162c28e..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From 61c44e24ea212b92bf6a420b94070ee6fc715811 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 8 May 2019 10:08:31 +0100
-Subject: [PATCH] BCM270X_DT: usb: Refactor DTS and overlays
-
-Move the IRQ interrupt declaration in the usb node before the FIQ
-declaration, so that the dwc2 driver will find it. Name the
-interrupts appropriately so that the dwc_otg driver can still find
-them. Then remove the interrupt rewriting from the overlays.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm270x.dtsi                 | 6 ++++--
- arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 6 ------
- arch/arm/boot/dts/overlays/dwc2-overlay.dts    | 2 --
- 3 files changed, 4 insertions(+), 10 deletions(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -131,8 +131,10 @@
-                       compatible = "brcm,bcm2708-usb";
-                       reg = <0x7e980000 0x10000>,
-                             <0x7e006000 0x1000>;
--                      interrupts = <2 0>,
--                                   <1 9>;
-+                      interrupt-names = "usb",
-+                                        "soft";
-+                      interrupts = <1 9>,
-+                                   <2 0>;
-               };
-               v3d@7ec00000 { /* vd3 */
---- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-@@ -6,14 +6,8 @@
-       fragment@0 {
-               target = <&usb>;
--              #address-cells = <1>;
--              #size-cells = <1>;
-               __overlay__ {
-                       compatible = "brcm,bcm2708-usb";
--                      reg = <0x7e980000 0x10000>,
--                            <0x7e006000 0x1000>;
--                      interrupts = <2 0>,
--                                   <1 9>;
-                       status = "okay";
-               };
-       };
---- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-@@ -10,8 +10,6 @@
-               #size-cells = <1>;
-               dwc2_usb: __overlay__ {
-                       compatible = "brcm,bcm2835-usb";
--                      reg = <0x7e980000 0x10000>;
--                      interrupts = <1 9>;
-                       dr_mode = "otg";
-                       g-np-tx-fifo-size = <32>;
-                       g-rx-fifo-size = <256>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0436-w1-ds2408-Fix-typo-after-49695ac46861-reset-on-outpu.patch b/target/linux/brcm2708/patches-4.19/950-0436-w1-ds2408-Fix-typo-after-49695ac46861-reset-on-outpu.patch
new file mode 100644 (file)
index 0000000..c3d32ee
--- /dev/null
@@ -0,0 +1,31 @@
+From f74fe07cab3e8816c029de25029b71c80004619c Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Thu, 16 May 2019 14:39:21 +0200
+Subject: [PATCH] w1: ds2408: Fix typo after 49695ac46861 (reset on
+ output_write retry with readback)
+
+commit 6660a04feb7ef648e50c792e19084d675fa6f3a2 upstream.
+
+Fix a typo in commit:
+49695ac46861 w1: ds2408: reset on output_write retry with readback
+
+Fixes: 49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
+Reported-by: Phil Elwell <phil@raspberrypi.org>
+Cc: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2408.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/w1/slaves/w1_ds2408.c
++++ b/drivers/w1/slaves/w1_ds2408.c
+@@ -138,7 +138,7 @@ static ssize_t status_control_read(struc
+               W1_F29_REG_CONTROL_AND_STATUS, buf);
+ }
+-#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
++#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
+ static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
+ {
+       u8 w1_buf[3];
diff --git a/target/linux/brcm2708/patches-4.19/950-0437-BCM270X_DT-Rename-Pi-Zero-W-DT-files.patch b/target/linux/brcm2708/patches-4.19/950-0437-BCM270X_DT-Rename-Pi-Zero-W-DT-files.patch
new file mode 100644 (file)
index 0000000..37bb4fd
--- /dev/null
@@ -0,0 +1,367 @@
+From 9542646d9211ab4305beb75da97f61cc1968ae6c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 28 May 2019 16:36:04 +0100
+Subject: [PATCH] BCM270X_DT: Rename Pi Zero W DT files
+
+The downtream Pi Zero W dts file uses the digit 0, whereas upstream
+chose to spell it out - "zero-w". The firmware has, for a long time,
+looked for bcm2708-rpi-zero-w.dtb first before falling back to the
+numerical version. Therefore it is better to follow upstream and
+make the switch to "bcm2708-rpi-zero-w".
+
+At the same time, remove some overrides that duplicate values
+inherited from the shared .dtsi files.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile                                   | 2 +-
+ .../boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} | 5 -----
+ 2 files changed, 1 insertion(+), 6 deletions(-)
+ rename arch/arm/boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} (97%)
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -4,7 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2708-rpi-b.dtb \
+       bcm2708-rpi-b-plus.dtb \
+       bcm2708-rpi-cm.dtb \
+-      bcm2708-rpi-0-w.dtb \
++      bcm2708-rpi-zero-w.dtb \
+       bcm2709-rpi-2-b.dtb \
+       bcm2710-rpi-3-b.dtb \
+       bcm2710-rpi-3-b-plus.dtb \
+--- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
++++ /dev/null
+@@ -1,167 +0,0 @@
+-/dts-v1/;
+-
+-#include "bcm2708.dtsi"
+-#include "bcm283x-rpi-csi1-2lane.dtsi"
+-
+-/ {
+-      compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
+-      model = "Raspberry Pi Zero W";
+-
+-      chosen {
+-              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+-      };
+-
+-      aliases {
+-              serial0 = &uart1;
+-              serial1 = &uart0;
+-              mmc1 = &mmcnr;
+-      };
+-};
+-
+-&gpio {
+-      spi0_pins: spi0_pins {
+-              brcm,pins = <9 10 11>;
+-              brcm,function = <4>; /* alt0 */
+-      };
+-
+-      spi0_cs_pins: spi0_cs_pins {
+-              brcm,pins = <8 7>;
+-              brcm,function = <1>; /* output */
+-      };
+-
+-      i2c0_pins: i2c0 {
+-              brcm,pins = <0 1>;
+-              brcm,function = <4>;
+-      };
+-
+-      i2c1_pins: i2c1 {
+-              brcm,pins = <2 3>;
+-              brcm,function = <4>;
+-      };
+-
+-      i2s_pins: i2s {
+-              brcm,pins = <18 19 20 21>;
+-              brcm,function = <4>; /* alt0 */
+-      };
+-
+-      sdio_pins: sdio_pins {
+-              brcm,pins = <34 35 36 37 38 39>;
+-              brcm,function = <7>; /* ALT3 = SD1 */
+-              brcm,pull = <0 2 2 2 2 2>;
+-      };
+-
+-      bt_pins: bt_pins {
+-              brcm,pins = <43>;
+-              brcm,function = <4>; /* alt0:GPCLK2 */
+-              brcm,pull = <0>; /* none */
+-      };
+-
+-      uart0_pins: uart0_pins {
+-              brcm,pins = <30 31 32 33>;
+-              brcm,function = <7>; /* alt3=UART0 */
+-              brcm,pull = <2 0 0 2>; /* up none none up */
+-      };
+-
+-      uart1_pins: uart1_pins {
+-              brcm,pins;
+-              brcm,function;
+-              brcm,pull;
+-      };
+-
+-      audio_pins: audio_pins {
+-              brcm,pins = <>;
+-              brcm,function = <>;
+-      };
+-};
+-
+-&mmcnr {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&sdio_pins>;
+-      bus-width = <4>;
+-      status = "okay";
+-};
+-
+-&uart0 {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&uart0_pins &bt_pins>;
+-      status = "okay";
+-};
+-
+-&uart1 {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&uart1_pins>;
+-      status = "okay";
+-};
+-
+-&spi0 {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
+-      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
+-
+-      spidev0: spidev@0{
+-              compatible = "spidev";
+-              reg = <0>;      /* CE0 */
+-              #address-cells = <1>;
+-              #size-cells = <0>;
+-              spi-max-frequency = <125000000>;
+-      };
+-
+-      spidev1: spidev@1{
+-              compatible = "spidev";
+-              reg = <1>;      /* CE1 */
+-              #address-cells = <1>;
+-              #size-cells = <0>;
+-              spi-max-frequency = <125000000>;
+-      };
+-};
+-
+-&i2c0 {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&i2c0_pins>;
+-      clock-frequency = <100000>;
+-};
+-
+-&i2c1 {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&i2c1_pins>;
+-      clock-frequency = <100000>;
+-};
+-
+-&i2c2 {
+-      clock-frequency = <100000>;
+-};
+-
+-&i2s {
+-      #sound-dai-cells = <0>;
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&i2s_pins>;
+-};
+-
+-&random {
+-      status = "okay";
+-};
+-
+-&leds {
+-      act_led: act {
+-              label = "led0";
+-              linux,default-trigger = "mmc0";
+-              gpios = <&gpio 47 0>;
+-      };
+-};
+-
+-&hdmi {
+-      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+-};
+-
+-&audio {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&audio_pins>;
+-};
+-
+-/ {
+-      __overrides__ {
+-              act_led_gpio = <&act_led>,"gpios:4";
+-              act_led_activelow = <&act_led>,"gpios:8";
+-              act_led_trigger = <&act_led>,"linux,default-trigger";
+-      };
+-};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -0,0 +1,162 @@
++/dts-v1/;
++
++#include "bcm2708.dtsi"
++#include "bcm283x-rpi-csi1-2lane.dtsi"
++
++/ {
++      compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
++      model = "Raspberry Pi Zero W";
++
++      chosen {
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
++      };
++
++      aliases {
++              serial0 = &uart1;
++              serial1 = &uart0;
++              mmc1 = &mmcnr;
++      };
++};
++
++&gpio {
++      spi0_pins: spi0_pins {
++              brcm,pins = <9 10 11>;
++              brcm,function = <4>; /* alt0 */
++      };
++
++      spi0_cs_pins: spi0_cs_pins {
++              brcm,pins = <8 7>;
++              brcm,function = <1>; /* output */
++      };
++
++      i2c0_pins: i2c0 {
++              brcm,pins = <0 1>;
++              brcm,function = <4>;
++      };
++
++      i2c1_pins: i2c1 {
++              brcm,pins = <2 3>;
++              brcm,function = <4>;
++      };
++
++      i2s_pins: i2s {
++              brcm,pins = <18 19 20 21>;
++              brcm,function = <4>; /* alt0 */
++      };
++
++      sdio_pins: sdio_pins {
++              brcm,pins = <34 35 36 37 38 39>;
++              brcm,function = <7>; /* ALT3 = SD1 */
++              brcm,pull = <0 2 2 2 2 2>;
++      };
++
++      bt_pins: bt_pins {
++              brcm,pins = <43>;
++              brcm,function = <4>; /* alt0:GPCLK2 */
++              brcm,pull = <0>; /* none */
++      };
++
++      uart0_pins: uart0_pins {
++              brcm,pins = <30 31 32 33>;
++              brcm,function = <7>; /* alt3=UART0 */
++              brcm,pull = <2 0 0 2>; /* up none none up */
++      };
++
++      uart1_pins: uart1_pins {
++              brcm,pins;
++              brcm,function;
++              brcm,pull;
++      };
++
++      audio_pins: audio_pins {
++              brcm,pins = <>;
++              brcm,function = <>;
++      };
++};
++
++&mmcnr {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdio_pins>;
++      bus-width = <4>;
++      status = "okay";
++};
++
++&uart0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart0_pins &bt_pins>;
++      status = "okay";
++};
++
++&uart1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart1_pins>;
++      status = "okay";
++};
++
++&spi0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
++      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
++
++      spidev0: spidev@0{
++              compatible = "spidev";
++              reg = <0>;      /* CE0 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++
++      spidev1: spidev@1{
++              compatible = "spidev";
++              reg = <1>;      /* CE1 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++};
++
++&i2c0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c0_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c1_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c2 {
++      clock-frequency = <100000>;
++};
++
++&i2s {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2s_pins>;
++};
++
++&leds {
++      act_led: act {
++              label = "led0";
++              linux,default-trigger = "mmc0";
++              gpios = <&gpio 47 0>;
++      };
++};
++
++&hdmi {
++      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++};
++
++&audio {
++      pinctrl-names = "default";
++      pinctrl-0 = <&audio_pins>;
++};
++
++/ {
++      __overrides__ {
++              act_led_gpio = <&act_led>,"gpios:4";
++              act_led_activelow = <&act_led>,"gpios:8";
++              act_led_trigger = <&act_led>,"linux,default-trigger";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0437-overlays-Update-upstream-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0437-overlays-Update-upstream-overlay.patch
deleted file mode 100644 (file)
index 4547668..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-From 61c487e6a1985e52307d6df5834b610a50219819 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 22 May 2019 13:29:56 +0100
-Subject: [PATCH] overlays: Update upstream overlay
-
-The recent DT/overlay changes have had a corresponding effect on the
-upstream overlay, which is a composite of the vc4-kms-v3d and dwc2
-overlays.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../boot/dts/overlays/upstream-overlay.dts    | 41 ++-----------------
- 1 file changed, 3 insertions(+), 38 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -52,42 +52,36 @@
-       fragment@7 {
-               target = <&pixelvalve0>;
-               __overlay__ {
--                      interrupts = <2 13>;
-                       status = "okay";
-               };
-       };
-       fragment@8 {
-               target = <&pixelvalve1>;
-               __overlay__ {
--                      interrupts = <2 14>;
-                       status = "okay";
-               };
-       };
-       fragment@9 {
-               target = <&pixelvalve2>;
-               __overlay__ {
--                      interrupts = <2 10>;
-                       status = "okay";
-               };
-       };
-       fragment@10 {
-               target = <&hvs>;
-               __overlay__ {
--                      interrupts = <2 1>;
-                       status = "okay";
-               };
-       };
-       fragment@11 {
-               target = <&hdmi>;
-               __overlay__ {
--                      interrupts = <2 8>, <2 9>;
-                       status = "okay";
-               };
-       };
-       fragment@12 {
-               target = <&v3d>;
-               __overlay__ {
--                      interrupts = <1 10>;
-                       status = "okay";
-               };
-       };
-@@ -98,37 +92,29 @@
-               };
-       };
-       fragment@14 {
--              target-path = "/soc/dma";
--              __overlay__ {
--                      brcm,dma-channel-mask = <0x7f35>;
--              };
--      };
--      fragment@15 {
-               target = <&clocks>;
-               __overlay__ {
-                       claim-clocks = <BCM2835_PLLD_DSI0 BCM2835_PLLD_DSI1 BCM2835_PLLH_AUX BCM2835_PLLH_PIX>;
-               };
-       };
--      fragment@16 {
-+      fragment@15 {
-               target = <&vec>;
-               __overlay__ {
-                       status = "okay";
-               };
-       };
--      fragment@17 {
-+      fragment@16 {
-               target = <&txp>;
-               __overlay__ {
-                       status = "okay";
-               };
-       };
--      fragment@18 {
-+      fragment@17 {
-               target = <&usb>;
-               #address-cells = <1>;
-               #size-cells = <1>;
-               dwc2_usb: __overlay__ {
-                       compatible = "brcm,bcm2835-usb";
--                      reg = <0x7e980000 0x10000>;
--                      interrupts = <1 9>;
-                       dr_mode = "otg";
-                       g-np-tx-fifo-size = <32>;
-                       g-rx-fifo-size = <256>;
-@@ -136,25 +122,4 @@
-                       status = "okay";
-               };
-       };
--      fragment@19 {
--              target = <&uart1>;
--              __overlay__ {
--                      interrupt-parent = <&intc>;
--                      interrupts = <0x1 0x1d>;
--              };
--      };
--      fragment@20 {
--              target = <&spi1>;
--              __overlay__ {
--                      interrupt-parent = <&intc>;
--                      interrupts = <0x1 0x1d>;
--              };
--      };
--      fragment@21 {
--              target = <&spi2>;
--              __overlay__ {
--                      interrupt-parent = <&intc>;
--                      interrupts = <0x1 0x1d>;
--              };
--      };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0438-BCM270X_DT-Create-bcm2708-rpi-zero.dts.patch b/target/linux/brcm2708/patches-4.19/950-0438-BCM270X_DT-Create-bcm2708-rpi-zero.dts.patch
new file mode 100644 (file)
index 0000000..fa60926
--- /dev/null
@@ -0,0 +1,148 @@
+From e819b50b0c384f11f4eaf6e1ea76030c320f4511 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 28 May 2019 16:23:51 +0100
+Subject: [PATCH] BCM270X_DT: Create bcm2708-rpi-zero.dts
+
+The Pi Zero deserves a dedicated .dtb file - sharing the b-plus .dtb
+has been observed to cause an issue with the MAC address of some
+Ethernet dongles.
+
+See: https://github.com/raspberrypi/linux/issues/2990
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile             |   1 +
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts | 117 +++++++++++++++++++++++++
+ 2 files changed, 118 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2708-rpi-zero.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2708-rpi-b.dtb \
+       bcm2708-rpi-b-plus.dtb \
+       bcm2708-rpi-cm.dtb \
++      bcm2708-rpi-zero.dtb \
+       bcm2708-rpi-zero-w.dtb \
+       bcm2709-rpi-2-b.dtb \
+       bcm2710-rpi-3-b.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -0,0 +1,117 @@
++/dts-v1/;
++
++#include "bcm2708.dtsi"
++#include "bcm283x-rpi-csi1-2lane.dtsi"
++
++/ {
++      compatible = "raspberrypi,model-zero", "brcm,bcm2835";
++      model = "Raspberry Pi Zero";
++
++      chosen {
++              bootargs = "coherent_pool=1M";
++      };
++};
++
++&gpio {
++      spi0_pins: spi0_pins {
++              brcm,pins = <9 10 11>;
++              brcm,function = <4>; /* alt0 */
++      };
++
++      spi0_cs_pins: spi0_cs_pins {
++              brcm,pins = <8 7>;
++              brcm,function = <1>; /* output */
++      };
++
++      i2c0_pins: i2c0 {
++              brcm,pins = <0 1>;
++              brcm,function = <4>;
++      };
++
++      i2c1_pins: i2c1 {
++              brcm,pins = <2 3>;
++              brcm,function = <4>;
++      };
++
++      i2s_pins: i2s {
++              brcm,pins = <18 19 20 21>;
++              brcm,function = <4>; /* alt0 */
++      };
++
++      audio_pins: audio_pins {
++              brcm,pins = <>;
++              brcm,function = <>;
++      };
++};
++
++&uart0 {
++      status = "okay";
++};
++
++&spi0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
++      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
++
++      spidev0: spidev@0{
++              compatible = "spidev";
++              reg = <0>;      /* CE0 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++
++      spidev1: spidev@1{
++              compatible = "spidev";
++              reg = <1>;      /* CE1 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++};
++
++&i2c0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c0_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c1_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c2 {
++      clock-frequency = <100000>;
++};
++
++&i2s {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2s_pins>;
++};
++
++&leds {
++      act_led: act {
++              label = "led0";
++              linux,default-trigger = "mmc0";
++              gpios = <&gpio 47 0>;
++      };
++};
++
++&hdmi {
++      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++};
++
++&audio {
++      pinctrl-names = "default";
++      pinctrl-0 = <&audio_pins>;
++};
++
++/ {
++      __overrides__ {
++              act_led_gpio = <&act_led>,"gpios:4";
++              act_led_activelow = <&act_led>,"gpios:8";
++              act_led_trigger = <&act_led>,"linux,default-trigger";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0438-w1-ds2408-Fix-typo-after-49695ac46861-reset-on-outpu.patch b/target/linux/brcm2708/patches-4.19/950-0438-w1-ds2408-Fix-typo-after-49695ac46861-reset-on-outpu.patch
deleted file mode 100644 (file)
index c3d32ee..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From f74fe07cab3e8816c029de25029b71c80004619c Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Thu, 16 May 2019 14:39:21 +0200
-Subject: [PATCH] w1: ds2408: Fix typo after 49695ac46861 (reset on
- output_write retry with readback)
-
-commit 6660a04feb7ef648e50c792e19084d675fa6f3a2 upstream.
-
-Fix a typo in commit:
-49695ac46861 w1: ds2408: reset on output_write retry with readback
-
-Fixes: 49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
-Reported-by: Phil Elwell <phil@raspberrypi.org>
-Cc: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2408.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/w1/slaves/w1_ds2408.c
-+++ b/drivers/w1/slaves/w1_ds2408.c
-@@ -138,7 +138,7 @@ static ssize_t status_control_read(struc
-               W1_F29_REG_CONTROL_AND_STATUS, buf);
- }
--#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
-+#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
- static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
- {
-       u8 w1_buf[3];
diff --git a/target/linux/brcm2708/patches-4.19/950-0439-BCM270X_DT-Rename-Pi-Zero-W-DT-files.patch b/target/linux/brcm2708/patches-4.19/950-0439-BCM270X_DT-Rename-Pi-Zero-W-DT-files.patch
deleted file mode 100644 (file)
index 37bb4fd..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-From 9542646d9211ab4305beb75da97f61cc1968ae6c Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 28 May 2019 16:36:04 +0100
-Subject: [PATCH] BCM270X_DT: Rename Pi Zero W DT files
-
-The downtream Pi Zero W dts file uses the digit 0, whereas upstream
-chose to spell it out - "zero-w". The firmware has, for a long time,
-looked for bcm2708-rpi-zero-w.dtb first before falling back to the
-numerical version. Therefore it is better to follow upstream and
-make the switch to "bcm2708-rpi-zero-w".
-
-At the same time, remove some overrides that duplicate values
-inherited from the shared .dtsi files.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile                                   | 2 +-
- .../boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} | 5 -----
- 2 files changed, 1 insertion(+), 6 deletions(-)
- rename arch/arm/boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} (97%)
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -4,7 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
-       bcm2708-rpi-b.dtb \
-       bcm2708-rpi-b-plus.dtb \
-       bcm2708-rpi-cm.dtb \
--      bcm2708-rpi-0-w.dtb \
-+      bcm2708-rpi-zero-w.dtb \
-       bcm2709-rpi-2-b.dtb \
-       bcm2710-rpi-3-b.dtb \
-       bcm2710-rpi-3-b-plus.dtb \
---- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-+++ /dev/null
-@@ -1,167 +0,0 @@
--/dts-v1/;
--
--#include "bcm2708.dtsi"
--#include "bcm283x-rpi-csi1-2lane.dtsi"
--
--/ {
--      compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
--      model = "Raspberry Pi Zero W";
--
--      chosen {
--              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
--      };
--
--      aliases {
--              serial0 = &uart1;
--              serial1 = &uart0;
--              mmc1 = &mmcnr;
--      };
--};
--
--&gpio {
--      spi0_pins: spi0_pins {
--              brcm,pins = <9 10 11>;
--              brcm,function = <4>; /* alt0 */
--      };
--
--      spi0_cs_pins: spi0_cs_pins {
--              brcm,pins = <8 7>;
--              brcm,function = <1>; /* output */
--      };
--
--      i2c0_pins: i2c0 {
--              brcm,pins = <0 1>;
--              brcm,function = <4>;
--      };
--
--      i2c1_pins: i2c1 {
--              brcm,pins = <2 3>;
--              brcm,function = <4>;
--      };
--
--      i2s_pins: i2s {
--              brcm,pins = <18 19 20 21>;
--              brcm,function = <4>; /* alt0 */
--      };
--
--      sdio_pins: sdio_pins {
--              brcm,pins = <34 35 36 37 38 39>;
--              brcm,function = <7>; /* ALT3 = SD1 */
--              brcm,pull = <0 2 2 2 2 2>;
--      };
--
--      bt_pins: bt_pins {
--              brcm,pins = <43>;
--              brcm,function = <4>; /* alt0:GPCLK2 */
--              brcm,pull = <0>; /* none */
--      };
--
--      uart0_pins: uart0_pins {
--              brcm,pins = <30 31 32 33>;
--              brcm,function = <7>; /* alt3=UART0 */
--              brcm,pull = <2 0 0 2>; /* up none none up */
--      };
--
--      uart1_pins: uart1_pins {
--              brcm,pins;
--              brcm,function;
--              brcm,pull;
--      };
--
--      audio_pins: audio_pins {
--              brcm,pins = <>;
--              brcm,function = <>;
--      };
--};
--
--&mmcnr {
--      pinctrl-names = "default";
--      pinctrl-0 = <&sdio_pins>;
--      bus-width = <4>;
--      status = "okay";
--};
--
--&uart0 {
--      pinctrl-names = "default";
--      pinctrl-0 = <&uart0_pins &bt_pins>;
--      status = "okay";
--};
--
--&uart1 {
--      pinctrl-names = "default";
--      pinctrl-0 = <&uart1_pins>;
--      status = "okay";
--};
--
--&spi0 {
--      pinctrl-names = "default";
--      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
--      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
--
--      spidev0: spidev@0{
--              compatible = "spidev";
--              reg = <0>;      /* CE0 */
--              #address-cells = <1>;
--              #size-cells = <0>;
--              spi-max-frequency = <125000000>;
--      };
--
--      spidev1: spidev@1{
--              compatible = "spidev";
--              reg = <1>;      /* CE1 */
--              #address-cells = <1>;
--              #size-cells = <0>;
--              spi-max-frequency = <125000000>;
--      };
--};
--
--&i2c0 {
--      pinctrl-names = "default";
--      pinctrl-0 = <&i2c0_pins>;
--      clock-frequency = <100000>;
--};
--
--&i2c1 {
--      pinctrl-names = "default";
--      pinctrl-0 = <&i2c1_pins>;
--      clock-frequency = <100000>;
--};
--
--&i2c2 {
--      clock-frequency = <100000>;
--};
--
--&i2s {
--      #sound-dai-cells = <0>;
--      pinctrl-names = "default";
--      pinctrl-0 = <&i2s_pins>;
--};
--
--&random {
--      status = "okay";
--};
--
--&leds {
--      act_led: act {
--              label = "led0";
--              linux,default-trigger = "mmc0";
--              gpios = <&gpio 47 0>;
--      };
--};
--
--&hdmi {
--      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
--};
--
--&audio {
--      pinctrl-names = "default";
--      pinctrl-0 = <&audio_pins>;
--};
--
--/ {
--      __overrides__ {
--              act_led_gpio = <&act_led>,"gpios:4";
--              act_led_activelow = <&act_led>,"gpios:8";
--              act_led_trigger = <&act_led>,"linux,default-trigger";
--      };
--};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
-@@ -0,0 +1,162 @@
-+/dts-v1/;
-+
-+#include "bcm2708.dtsi"
-+#include "bcm283x-rpi-csi1-2lane.dtsi"
-+
-+/ {
-+      compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
-+      model = "Raspberry Pi Zero W";
-+
-+      chosen {
-+              bootargs = "coherent_pool=1M 8250.nr_uarts=1";
-+      };
-+
-+      aliases {
-+              serial0 = &uart1;
-+              serial1 = &uart0;
-+              mmc1 = &mmcnr;
-+      };
-+};
-+
-+&gpio {
-+      spi0_pins: spi0_pins {
-+              brcm,pins = <9 10 11>;
-+              brcm,function = <4>; /* alt0 */
-+      };
-+
-+      spi0_cs_pins: spi0_cs_pins {
-+              brcm,pins = <8 7>;
-+              brcm,function = <1>; /* output */
-+      };
-+
-+      i2c0_pins: i2c0 {
-+              brcm,pins = <0 1>;
-+              brcm,function = <4>;
-+      };
-+
-+      i2c1_pins: i2c1 {
-+              brcm,pins = <2 3>;
-+              brcm,function = <4>;
-+      };
-+
-+      i2s_pins: i2s {
-+              brcm,pins = <18 19 20 21>;
-+              brcm,function = <4>; /* alt0 */
-+      };
-+
-+      sdio_pins: sdio_pins {
-+              brcm,pins = <34 35 36 37 38 39>;
-+              brcm,function = <7>; /* ALT3 = SD1 */
-+              brcm,pull = <0 2 2 2 2 2>;
-+      };
-+
-+      bt_pins: bt_pins {
-+              brcm,pins = <43>;
-+              brcm,function = <4>; /* alt0:GPCLK2 */
-+              brcm,pull = <0>; /* none */
-+      };
-+
-+      uart0_pins: uart0_pins {
-+              brcm,pins = <30 31 32 33>;
-+              brcm,function = <7>; /* alt3=UART0 */
-+              brcm,pull = <2 0 0 2>; /* up none none up */
-+      };
-+
-+      uart1_pins: uart1_pins {
-+              brcm,pins;
-+              brcm,function;
-+              brcm,pull;
-+      };
-+
-+      audio_pins: audio_pins {
-+              brcm,pins = <>;
-+              brcm,function = <>;
-+      };
-+};
-+
-+&mmcnr {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdio_pins>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
-+&uart0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart0_pins &bt_pins>;
-+      status = "okay";
-+};
-+
-+&uart1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart1_pins>;
-+      status = "okay";
-+};
-+
-+&spi0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
-+      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
-+
-+      spidev0: spidev@0{
-+              compatible = "spidev";
-+              reg = <0>;      /* CE0 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+
-+      spidev1: spidev@1{
-+              compatible = "spidev";
-+              reg = <1>;      /* CE1 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+};
-+
-+&i2c0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c0_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c1_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c2 {
-+      clock-frequency = <100000>;
-+};
-+
-+&i2s {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2s_pins>;
-+};
-+
-+&leds {
-+      act_led: act {
-+              label = "led0";
-+              linux,default-trigger = "mmc0";
-+              gpios = <&gpio 47 0>;
-+      };
-+};
-+
-+&hdmi {
-+      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+};
-+
-+&audio {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&audio_pins>;
-+};
-+
-+/ {
-+      __overrides__ {
-+              act_led_gpio = <&act_led>,"gpios:4";
-+              act_led_activelow = <&act_led>,"gpios:8";
-+              act_led_trigger = <&act_led>,"linux,default-trigger";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0439-overlays-Fix-mmc-related-overlays-after-refactor.patch b/target/linux/brcm2708/patches-4.19/950-0439-overlays-Fix-mmc-related-overlays-after-refactor.patch
new file mode 100644 (file)
index 0000000..468aa30
--- /dev/null
@@ -0,0 +1,73 @@
+From dadcb33e1f4ee70bc77da7fa7054b8571a22d5ea Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 30 May 2019 12:25:29 +0100
+Subject: [PATCH] overlays: Fix mmc-related overlays after refactor
+
+The addition of the mmcnr node to the base dtbs caused some overlays to
+not work as they should. Patch up pi3-disable-wifi, balena-fin and
+sdhost.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/balena-fin-overlay.dts       | 7 ++++---
+ arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 7 +++++++
+ arch/arm/boot/dts/overlays/sdhost-overlay.dts           | 7 +++++++
+ 3 files changed, 18 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -5,13 +5,12 @@
+       compatible = "brcm,bcm2835";
+       fragment@0 {
+-              target = <&mmc>;
+-              sdio_wifi: __overlay__ {
++              target = <&mmcnr>;
++              __overlay__ {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&sdio_pins>;
+                       bus-width = <4>;
+                       brcm,overclock-50 = <35>;
+-                      non-removable;
+                       status = "okay";
+               };
+       };
+@@ -43,6 +42,8 @@
+                               compatible = "gpio-poweroff";
+                               gpios = <&gpio 40 1>;
+                               force;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&power_ctrl_pins>;
+                       };
+                       i2c_soft: i2c@0 {
+--- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
+@@ -10,4 +10,11 @@
+                       status = "disabled";
+               };
+       };
++
++      fragment@1 {
++              target = <&mmcnr>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
+ };
+--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
+@@ -22,6 +22,13 @@
+               };
+       };
++      fragment@2 {
++              target = <&mmcnr>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
+       __overrides__ {
+               overclock_50     = <&frag0>,"brcm,overclock-50:0";
+               force_pio        = <&frag0>,"brcm,force-pio?";
diff --git a/target/linux/brcm2708/patches-4.19/950-0440-BCM270X_DT-Create-bcm2708-rpi-zero.dts.patch b/target/linux/brcm2708/patches-4.19/950-0440-BCM270X_DT-Create-bcm2708-rpi-zero.dts.patch
deleted file mode 100644 (file)
index fa60926..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-From e819b50b0c384f11f4eaf6e1ea76030c320f4511 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 28 May 2019 16:23:51 +0100
-Subject: [PATCH] BCM270X_DT: Create bcm2708-rpi-zero.dts
-
-The Pi Zero deserves a dedicated .dtb file - sharing the b-plus .dtb
-has been observed to cause an issue with the MAC address of some
-Ethernet dongles.
-
-See: https://github.com/raspberrypi/linux/issues/2990
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile             |   1 +
- arch/arm/boot/dts/bcm2708-rpi-zero.dts | 117 +++++++++++++++++++++++++
- 2 files changed, 118 insertions(+)
- create mode 100644 arch/arm/boot/dts/bcm2708-rpi-zero.dts
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
-       bcm2708-rpi-b.dtb \
-       bcm2708-rpi-b-plus.dtb \
-       bcm2708-rpi-cm.dtb \
-+      bcm2708-rpi-zero.dtb \
-       bcm2708-rpi-zero-w.dtb \
-       bcm2709-rpi-2-b.dtb \
-       bcm2710-rpi-3-b.dtb \
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
-@@ -0,0 +1,117 @@
-+/dts-v1/;
-+
-+#include "bcm2708.dtsi"
-+#include "bcm283x-rpi-csi1-2lane.dtsi"
-+
-+/ {
-+      compatible = "raspberrypi,model-zero", "brcm,bcm2835";
-+      model = "Raspberry Pi Zero";
-+
-+      chosen {
-+              bootargs = "coherent_pool=1M";
-+      };
-+};
-+
-+&gpio {
-+      spi0_pins: spi0_pins {
-+              brcm,pins = <9 10 11>;
-+              brcm,function = <4>; /* alt0 */
-+      };
-+
-+      spi0_cs_pins: spi0_cs_pins {
-+              brcm,pins = <8 7>;
-+              brcm,function = <1>; /* output */
-+      };
-+
-+      i2c0_pins: i2c0 {
-+              brcm,pins = <0 1>;
-+              brcm,function = <4>;
-+      };
-+
-+      i2c1_pins: i2c1 {
-+              brcm,pins = <2 3>;
-+              brcm,function = <4>;
-+      };
-+
-+      i2s_pins: i2s {
-+              brcm,pins = <18 19 20 21>;
-+              brcm,function = <4>; /* alt0 */
-+      };
-+
-+      audio_pins: audio_pins {
-+              brcm,pins = <>;
-+              brcm,function = <>;
-+      };
-+};
-+
-+&uart0 {
-+      status = "okay";
-+};
-+
-+&spi0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
-+      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
-+
-+      spidev0: spidev@0{
-+              compatible = "spidev";
-+              reg = <0>;      /* CE0 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+
-+      spidev1: spidev@1{
-+              compatible = "spidev";
-+              reg = <1>;      /* CE1 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+};
-+
-+&i2c0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c0_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c1_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c2 {
-+      clock-frequency = <100000>;
-+};
-+
-+&i2s {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2s_pins>;
-+};
-+
-+&leds {
-+      act_led: act {
-+              label = "led0";
-+              linux,default-trigger = "mmc0";
-+              gpios = <&gpio 47 0>;
-+      };
-+};
-+
-+&hdmi {
-+      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+};
-+
-+&audio {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&audio_pins>;
-+};
-+
-+/ {
-+      __overrides__ {
-+              act_led_gpio = <&act_led>,"gpios:4";
-+              act_led_activelow = <&act_led>,"gpios:8";
-+              act_led_trigger = <&act_led>,"linux,default-trigger";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0440-Fixed-48k-timing-issue.patch b/target/linux/brcm2708/patches-4.19/950-0440-Fixed-48k-timing-issue.patch
new file mode 100644 (file)
index 0000000..541e18a
--- /dev/null
@@ -0,0 +1,95 @@
+From 539e2eef7dbfb58ab028a5530430611973dd4c84 Mon Sep 17 00:00:00 2001
+From: IQaudIO <gordon@iqaudio.com>
+Date: Thu, 6 Jun 2019 10:20:55 +0100
+Subject: [PATCH] Fixed 48k timing issue
+
+---
+ sound/soc/bcm/iqaudio-codec.c | 33 ++++++++++++++++++++++++++++-----
+ 1 file changed, 28 insertions(+), 5 deletions(-)
+
+--- a/sound/soc/bcm/iqaudio-codec.c
++++ b/sound/soc/bcm/iqaudio-codec.c
+@@ -45,11 +45,15 @@ static int snd_rpi_iqaudio_pll_control(s
+                                         0);
+               if (ret)
+                       dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
++              /* Allow PLL time to bypass */
++              msleep(100);
+       } else if (SND_SOC_DAPM_EVENT_ON(event)) {
+               ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
+                                         pll_out);
+               if (ret)
+                       dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
++              /* Allow PLL time to lock */
++              msleep(100);
+       }
+       return ret;
+@@ -71,6 +75,13 @@ static int snd_rpi_iqaudio_post_dapm_eve
+      return 0;
+ }
++static const struct snd_kcontrol_new dapm_controls[] = {
++      SOC_DAPM_PIN_SWITCH("HP Jack"),
++      SOC_DAPM_PIN_SWITCH("MIC Jack"),
++      SOC_DAPM_PIN_SWITCH("Onboard MIC"),
++      SOC_DAPM_PIN_SWITCH("AUX Jack"),
++};
++
+ static const struct snd_soc_dapm_widget dapm_widgets[] = {
+       SND_SOC_DAPM_HP("HP Jack", NULL),
+       SND_SOC_DAPM_MIC("MIC Jack", NULL),
+@@ -87,14 +98,14 @@ static const struct snd_soc_dapm_route a
+       {"HP Jack", NULL, "HPR"},
+       {"HP Jack", NULL, "PLL Control"},
+-      {"AUX Jack", NULL, "AUXR"},
+-      {"AUX Jack", NULL, "AUXL"},
++      {"AUXR", NULL, "AUX Jack"},
++      {"AUXL", NULL, "AUX Jack"},
+       {"AUX Jack", NULL, "PLL Control"},
+       /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
+-      {"MIC Jack", NULL, "MIC1"},
++      {"MIC1", NULL, "MIC Jack"},
+       {"MIC Jack", NULL, "PLL Control"},
+-      {"Onboard MIC", NULL, "MIC2"},
++      {"MIC2", NULL, "Onboard MIC"},
+       {"Onboard MIC", NULL, "PLL Control"},
+ };
+@@ -106,6 +117,16 @@ static int snd_rpi_iqaudio_codec_init(st
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       int ret;
++      /*
++       * Disable AUX Jack Pin by default to prevent PLL being enabled at
++       * startup. This avoids holding the PLL to a fixed SR config for
++       * subsequent streams.
++       *
++       * This pin can still be enabled later, as required by user-space.
++       */
++      snd_soc_dapm_disable_pin(&rtd->card->dapm, "AUX Jack");
++      snd_soc_dapm_sync(&rtd->card->dapm);
++
+       /* Set bclk ratio to align with codec's BCLK rate */
+       ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
+       if (ret) {
+@@ -168,6 +189,8 @@ static struct snd_soc_card snd_rpi_iqaud
+       .owner                  = THIS_MODULE,
+       .dai_link               = snd_rpi_iqaudio_codec_dai,
+       .num_links              = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
++      .controls               = dapm_controls,
++      .num_controls           = ARRAY_SIZE(dapm_controls),
+       .dapm_widgets           = dapm_widgets,
+       .num_dapm_widgets       = ARRAY_SIZE(dapm_widgets),
+       .dapm_routes            = audio_map,
+@@ -204,7 +227,7 @@ static int snd_rpi_iqaudio_codec_probe(s
+               if (of_property_read_string(pdev->dev.of_node,
+                                       "dai_stream_name", &dai->stream_name))
+-                      dai->stream_name = "IQaudIO CODEC HiFi v1.1";
++                      dai->stream_name = "IQaudIO CODEC HiFi v1.2";
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0441-overlays-Fix-mmc-related-overlays-after-refactor.patch b/target/linux/brcm2708/patches-4.19/950-0441-overlays-Fix-mmc-related-overlays-after-refactor.patch
deleted file mode 100644 (file)
index 468aa30..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From dadcb33e1f4ee70bc77da7fa7054b8571a22d5ea Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 30 May 2019 12:25:29 +0100
-Subject: [PATCH] overlays: Fix mmc-related overlays after refactor
-
-The addition of the mmcnr node to the base dtbs caused some overlays to
-not work as they should. Patch up pi3-disable-wifi, balena-fin and
-sdhost.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/balena-fin-overlay.dts       | 7 ++++---
- arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 7 +++++++
- arch/arm/boot/dts/overlays/sdhost-overlay.dts           | 7 +++++++
- 3 files changed, 18 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -5,13 +5,12 @@
-       compatible = "brcm,bcm2835";
-       fragment@0 {
--              target = <&mmc>;
--              sdio_wifi: __overlay__ {
-+              target = <&mmcnr>;
-+              __overlay__ {
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&sdio_pins>;
-                       bus-width = <4>;
-                       brcm,overclock-50 = <35>;
--                      non-removable;
-                       status = "okay";
-               };
-       };
-@@ -43,6 +42,8 @@
-                               compatible = "gpio-poweroff";
-                               gpios = <&gpio 40 1>;
-                               force;
-+                              pinctrl-names = "default";
-+                              pinctrl-0 = <&power_ctrl_pins>;
-                       };
-                       i2c_soft: i2c@0 {
---- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-@@ -10,4 +10,11 @@
-                       status = "disabled";
-               };
-       };
-+
-+      fragment@1 {
-+              target = <&mmcnr>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
- };
---- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-@@ -22,6 +22,13 @@
-               };
-       };
-+      fragment@2 {
-+              target = <&mmcnr>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
-+
-       __overrides__ {
-               overclock_50     = <&frag0>,"brcm,overclock-50:0";
-               force_pio        = <&frag0>,"brcm,force-pio?";
diff --git a/target/linux/brcm2708/patches-4.19/950-0441-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch b/target/linux/brcm2708/patches-4.19/950-0441-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch
new file mode 100644 (file)
index 0000000..48bb146
--- /dev/null
@@ -0,0 +1,46 @@
+From 3da653227926705fe0dcb7b6057be1ca811f47b8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 10 May 2019 14:11:58 +0100
+Subject: [PATCH] staging: bcm2835-codec: Convert V4L2 nsec timestamps
+ to MMAL usec
+
+V4L2 uses nsecs, whilst MMAL uses usecs, but the code wasn't converting
+between them. This upsets video encode rate control.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c     | 9 +++++++--
+ 1 file changed, 7 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
+@@ -823,7 +823,8 @@ static void op_buffer_cb(struct vchiq_mm
+               vb2->flags |= V4L2_BUF_FLAG_LAST;
+       }
+-      vb2->vb2_buf.timestamp = mmal_buf->pts;
++      /* vb2 timestamps in nsecs, mmal in usecs */
++      vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
+       vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
+       if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+@@ -847,6 +848,7 @@ static void op_buffer_cb(struct vchiq_mm
+ static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
+                              struct vb2_v4l2_buffer *vb2)
+ {
++      u64 pts;
+       buf->mmal.mmal_flags = 0;
+       if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
+               buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
+@@ -869,7 +871,10 @@ static void vb2_to_mmal_buffer(struct m2
+       if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
+               buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
+-      buf->mmal.pts = vb2->vb2_buf.timestamp;
++      /* vb2 timestamps in nsecs, mmal in usecs */
++      pts = vb2->vb2_buf.timestamp;
++      do_div(pts, 1000);
++      buf->mmal.pts = pts;
+       buf->mmal.dts = MMAL_TIME_UNKNOWN;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0442-Fixed-48k-timing-issue.patch b/target/linux/brcm2708/patches-4.19/950-0442-Fixed-48k-timing-issue.patch
deleted file mode 100644 (file)
index 541e18a..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-From 539e2eef7dbfb58ab028a5530430611973dd4c84 Mon Sep 17 00:00:00 2001
-From: IQaudIO <gordon@iqaudio.com>
-Date: Thu, 6 Jun 2019 10:20:55 +0100
-Subject: [PATCH] Fixed 48k timing issue
-
----
- sound/soc/bcm/iqaudio-codec.c | 33 ++++++++++++++++++++++++++++-----
- 1 file changed, 28 insertions(+), 5 deletions(-)
-
---- a/sound/soc/bcm/iqaudio-codec.c
-+++ b/sound/soc/bcm/iqaudio-codec.c
-@@ -45,11 +45,15 @@ static int snd_rpi_iqaudio_pll_control(s
-                                         0);
-               if (ret)
-                       dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
-+              /* Allow PLL time to bypass */
-+              msleep(100);
-       } else if (SND_SOC_DAPM_EVENT_ON(event)) {
-               ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
-                                         pll_out);
-               if (ret)
-                       dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
-+              /* Allow PLL time to lock */
-+              msleep(100);
-       }
-       return ret;
-@@ -71,6 +75,13 @@ static int snd_rpi_iqaudio_post_dapm_eve
-      return 0;
- }
-+static const struct snd_kcontrol_new dapm_controls[] = {
-+      SOC_DAPM_PIN_SWITCH("HP Jack"),
-+      SOC_DAPM_PIN_SWITCH("MIC Jack"),
-+      SOC_DAPM_PIN_SWITCH("Onboard MIC"),
-+      SOC_DAPM_PIN_SWITCH("AUX Jack"),
-+};
-+
- static const struct snd_soc_dapm_widget dapm_widgets[] = {
-       SND_SOC_DAPM_HP("HP Jack", NULL),
-       SND_SOC_DAPM_MIC("MIC Jack", NULL),
-@@ -87,14 +98,14 @@ static const struct snd_soc_dapm_route a
-       {"HP Jack", NULL, "HPR"},
-       {"HP Jack", NULL, "PLL Control"},
--      {"AUX Jack", NULL, "AUXR"},
--      {"AUX Jack", NULL, "AUXL"},
-+      {"AUXR", NULL, "AUX Jack"},
-+      {"AUXL", NULL, "AUX Jack"},
-       {"AUX Jack", NULL, "PLL Control"},
-       /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
--      {"MIC Jack", NULL, "MIC1"},
-+      {"MIC1", NULL, "MIC Jack"},
-       {"MIC Jack", NULL, "PLL Control"},
--      {"Onboard MIC", NULL, "MIC2"},
-+      {"MIC2", NULL, "Onboard MIC"},
-       {"Onboard MIC", NULL, "PLL Control"},
- };
-@@ -106,6 +117,16 @@ static int snd_rpi_iqaudio_codec_init(st
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int ret;
-+      /*
-+       * Disable AUX Jack Pin by default to prevent PLL being enabled at
-+       * startup. This avoids holding the PLL to a fixed SR config for
-+       * subsequent streams.
-+       *
-+       * This pin can still be enabled later, as required by user-space.
-+       */
-+      snd_soc_dapm_disable_pin(&rtd->card->dapm, "AUX Jack");
-+      snd_soc_dapm_sync(&rtd->card->dapm);
-+
-       /* Set bclk ratio to align with codec's BCLK rate */
-       ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
-       if (ret) {
-@@ -168,6 +189,8 @@ static struct snd_soc_card snd_rpi_iqaud
-       .owner                  = THIS_MODULE,
-       .dai_link               = snd_rpi_iqaudio_codec_dai,
-       .num_links              = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
-+      .controls               = dapm_controls,
-+      .num_controls           = ARRAY_SIZE(dapm_controls),
-       .dapm_widgets           = dapm_widgets,
-       .num_dapm_widgets       = ARRAY_SIZE(dapm_widgets),
-       .dapm_routes            = audio_map,
-@@ -204,7 +227,7 @@ static int snd_rpi_iqaudio_codec_probe(s
-               if (of_property_read_string(pdev->dev.of_node,
-                                       "dai_stream_name", &dai->stream_name))
--                      dai->stream_name = "IQaudIO CODEC HiFi v1.1";
-+                      dai->stream_name = "IQaudIO CODEC HiFi v1.2";
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0442-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch b/target/linux/brcm2708/patches-4.19/950-0442-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch
new file mode 100644 (file)
index 0000000..ac75d47
--- /dev/null
@@ -0,0 +1,118 @@
+From 67c1f9dd0253a1175f77e801b19bd9d923225f9c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 10 May 2019 14:13:11 +0100
+Subject: [PATCH] staging: bcm2835-codec: Add support for setting
+ S_PARM and G_PARM
+
+Video encode can use the frame rate for rate control calculations,
+therefore plumb it through from V4L2's [S|G]_PARM ioctl.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 52 +++++++++++++++++--
+ 1 file changed, 48 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
+@@ -447,6 +447,8 @@ struct bcm2835_codec_ctx {
+       /* Source and destination queue data */
+       struct bcm2835_codec_q_data   q_data[2];
+       s32  bitrate;
++      unsigned int    framerate_num;
++      unsigned int    framerate_denom;
+       bool aborting;
+       int num_ip_buffers;
+@@ -610,8 +612,8 @@ static void setup_mmal_port_format(struc
+               port->es.video.height = q_data->height;
+               port->es.video.crop.width = q_data->crop_width;
+               port->es.video.crop.height = q_data->crop_height;
+-              port->es.video.frame_rate.num = 0;
+-              port->es.video.frame_rate.den = 1;
++              port->es.video.frame_rate.num = ctx->framerate_num;
++              port->es.video.frame_rate.den = ctx->framerate_denom;
+       } else {
+               /* Compressed format - leave resolution as 0 for decode */
+               if (ctx->dev->role == DECODE) {
+@@ -625,9 +627,9 @@ static void setup_mmal_port_format(struc
+                       port->es.video.crop.width = q_data->crop_width;
+                       port->es.video.crop.height = q_data->crop_height;
+                       port->format.bitrate = ctx->bitrate;
++                      port->es.video.frame_rate.num = ctx->framerate_num;
++                      port->es.video.frame_rate.den = ctx->framerate_denom;
+               }
+-              port->es.video.frame_rate.num = 0;
+-              port->es.video.frame_rate.den = 1;
+       }
+       port->es.video.crop.x = 0;
+       port->es.video.crop.y = 0;
+@@ -1361,6 +1363,41 @@ static int vidioc_s_selection(struct fil
+       return 0;
+ }
++static int vidioc_s_parm(struct file *file, void *priv,
++                       struct v4l2_streamparm *parm)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++              return -EINVAL;
++
++      ctx->framerate_num =
++                      parm->parm.output.timeperframe.denominator;
++      ctx->framerate_denom =
++                      parm->parm.output.timeperframe.numerator;
++
++      parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
++
++      return 0;
++}
++
++static int vidioc_g_parm(struct file *file, void *priv,
++                       struct v4l2_streamparm *parm)
++{
++      struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++              return -EINVAL;
++
++      parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
++      parm->parm.output.timeperframe.denominator =
++                      ctx->framerate_num;
++      parm->parm.output.timeperframe.numerator =
++                      ctx->framerate_denom;
++
++      return 0;
++}
++
+ static int vidioc_subscribe_evt(struct v4l2_fh *fh,
+                               const struct v4l2_event_subscription *sub)
+ {
+@@ -1725,6 +1762,9 @@ static const struct v4l2_ioctl_ops bcm28
+       .vidioc_g_selection     = vidioc_g_selection,
+       .vidioc_s_selection     = vidioc_s_selection,
++      .vidioc_g_parm          = vidioc_g_parm,
++      .vidioc_s_parm          = vidioc_s_parm,
++
+       .vidioc_subscribe_event = vidioc_subscribe_evt,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+@@ -2546,6 +2586,8 @@ static int bcm2835_codec_create(struct p
+       case DECODE:
+               v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
++              v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
++              v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
+               video_nr = decode_video_nr;
+               break;
+       case ENCODE:
+@@ -2558,6 +2600,8 @@ static int bcm2835_codec_create(struct p
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
++              v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
++              v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
+               video_nr = isp_video_nr;
+               break;
+       default:
diff --git a/target/linux/brcm2708/patches-4.19/950-0443-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch b/target/linux/brcm2708/patches-4.19/950-0443-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch
deleted file mode 100644 (file)
index 48bb146..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From 3da653227926705fe0dcb7b6057be1ca811f47b8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 10 May 2019 14:11:58 +0100
-Subject: [PATCH] staging: bcm2835-codec: Convert V4L2 nsec timestamps
- to MMAL usec
-
-V4L2 uses nsecs, whilst MMAL uses usecs, but the code wasn't converting
-between them. This upsets video encode rate control.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c     | 9 +++++++--
- 1 file changed, 7 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
-@@ -823,7 +823,8 @@ static void op_buffer_cb(struct vchiq_mm
-               vb2->flags |= V4L2_BUF_FLAG_LAST;
-       }
--      vb2->vb2_buf.timestamp = mmal_buf->pts;
-+      /* vb2 timestamps in nsecs, mmal in usecs */
-+      vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
-       vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
-       if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-@@ -847,6 +848,7 @@ static void op_buffer_cb(struct vchiq_mm
- static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
-                              struct vb2_v4l2_buffer *vb2)
- {
-+      u64 pts;
-       buf->mmal.mmal_flags = 0;
-       if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
-               buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
-@@ -869,7 +871,10 @@ static void vb2_to_mmal_buffer(struct m2
-       if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
-               buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
--      buf->mmal.pts = vb2->vb2_buf.timestamp;
-+      /* vb2 timestamps in nsecs, mmal in usecs */
-+      pts = vb2->vb2_buf.timestamp;
-+      do_div(pts, 1000);
-+      buf->mmal.pts = pts;
-       buf->mmal.dts = MMAL_TIME_UNKNOWN;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0443-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch b/target/linux/brcm2708/patches-4.19/950-0443-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch
new file mode 100644 (file)
index 0000000..6229fdc
--- /dev/null
@@ -0,0 +1,27 @@
+From afea1f84cbda94c47ba4a8f84d16c4330e145a0a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:15:05 +0100
+Subject: [PATCH] w1: w1-gpio: Make GPIO an output for strong pullup
+
+The logic to drive the data line high to implement a strong pullup
+assumed that the pin was already an output - setting a value does
+not change an input.
+
+See: https://github.com/raspberrypi/firmware/issues/1143
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/w1/masters/w1-gpio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -33,7 +33,7 @@ static u8 w1_gpio_set_pullup(void *data,
+                        * This will OVERRIDE open drain emulation and force-pull
+                        * the line high for some time.
+                        */
+-                      gpiod_set_raw_value(pdata->gpiod, 1);
++                      gpiod_direction_output_raw(pdata->gpiod, 1);
+                       msleep(pdata->pullup_duration);
+                       /*
+                        * This will simply set the line as input since we are doing
diff --git a/target/linux/brcm2708/patches-4.19/950-0444-overlays-Update-w1-gpio-and-w1-gpio-pullup.patch b/target/linux/brcm2708/patches-4.19/950-0444-overlays-Update-w1-gpio-and-w1-gpio-pullup.patch
new file mode 100644 (file)
index 0000000..f19a638
--- /dev/null
@@ -0,0 +1,78 @@
+From 531ae7af75b2be2867814693f069fb51e3155341 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:32:11 +0100
+Subject: [PATCH] overlays: Update w1-gpio and w1-gpio-pullup
+
+The parasitic power (power on data) feature is now enabled by
+default in the w1-gpio driver, so update the README and make the
+"pullup" parameter a no-op.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README                     | 9 ++-------
+ arch/arm/boot/dts/overlays/w1-gpio-overlay.dts        | 3 +--
+ arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts | 3 +--
+ 3 files changed, 4 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2261,9 +2261,7 @@ Info:   Configures the w1-gpio Onewire i
+         Use this overlay if you *don't* need a GPIO to drive an external pullup.
+ Load:   dtoverlay=w1-gpio,<param>=<val>
+ Params: gpiopin                 GPIO for I/O (default "4")
+-
+-        pullup                  Non-zero, "on", or "y" to enable the parasitic
+-                                power (2-wire, power-on-data) feature
++        pullup                  Now enabled by default (ignored)
+ Name:   w1-gpio-pullup
+@@ -2271,11 +2269,8 @@ Info:   Configures the w1-gpio Onewire i
+         Use this overlay if you *do* need a GPIO to drive an external pullup.
+ Load:   dtoverlay=w1-gpio-pullup,<param>=<val>
+ Params: gpiopin                 GPIO for I/O (default "4")
+-
+-        pullup                  Non-zero, "on", or "y" to enable the parasitic
+-                                power (2-wire, power-on-data) feature
+-
+         extpullup               GPIO for external pullup (default "5")
++        pullup                  Now enabled by default (ignored)
+ Name:   wittypi
+--- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
+@@ -14,7 +14,6 @@
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&w1_pins>;
+                               gpios = <&gpio 4 0>;
+-                              rpi,parasitic-power = <0>;
+                               status = "okay";
+                       };
+               };
+@@ -36,6 +35,6 @@
+                               <&w1>,"reg:0",
+                               <&w1_pins>,"brcm,pins:0",
+                               <&w1_pins>,"reg:0";
+-              pullup =        <&w1>,"rpi,parasitic-power:0";
++              pullup;         // Silently ignore unneeded parameter
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
+@@ -14,7 +14,6 @@
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&w1_pins>;
+                               gpios = <&gpio 4 0>, <&gpio 5 1>;
+-                              rpi,parasitic-power = <0>;
+                               status = "okay";
+                       };
+               };
+@@ -38,6 +37,6 @@
+                               <&w1_pins>,"reg:0";
+               extpullup =     <&w1>,"gpios:16",
+                               <&w1_pins>,"brcm,pins:4";
+-              pullup =        <&w1>,"rpi,parasitic-power:0";
++              pullup;         // Silently ignore unneeded parameter
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0444-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch b/target/linux/brcm2708/patches-4.19/950-0444-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch
deleted file mode 100644 (file)
index ac75d47..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-From 67c1f9dd0253a1175f77e801b19bd9d923225f9c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 10 May 2019 14:13:11 +0100
-Subject: [PATCH] staging: bcm2835-codec: Add support for setting
- S_PARM and G_PARM
-
-Video encode can use the frame rate for rate control calculations,
-therefore plumb it through from V4L2's [S|G]_PARM ioctl.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 52 +++++++++++++++++--
- 1 file changed, 48 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
-@@ -447,6 +447,8 @@ struct bcm2835_codec_ctx {
-       /* Source and destination queue data */
-       struct bcm2835_codec_q_data   q_data[2];
-       s32  bitrate;
-+      unsigned int    framerate_num;
-+      unsigned int    framerate_denom;
-       bool aborting;
-       int num_ip_buffers;
-@@ -610,8 +612,8 @@ static void setup_mmal_port_format(struc
-               port->es.video.height = q_data->height;
-               port->es.video.crop.width = q_data->crop_width;
-               port->es.video.crop.height = q_data->crop_height;
--              port->es.video.frame_rate.num = 0;
--              port->es.video.frame_rate.den = 1;
-+              port->es.video.frame_rate.num = ctx->framerate_num;
-+              port->es.video.frame_rate.den = ctx->framerate_denom;
-       } else {
-               /* Compressed format - leave resolution as 0 for decode */
-               if (ctx->dev->role == DECODE) {
-@@ -625,9 +627,9 @@ static void setup_mmal_port_format(struc
-                       port->es.video.crop.width = q_data->crop_width;
-                       port->es.video.crop.height = q_data->crop_height;
-                       port->format.bitrate = ctx->bitrate;
-+                      port->es.video.frame_rate.num = ctx->framerate_num;
-+                      port->es.video.frame_rate.den = ctx->framerate_denom;
-               }
--              port->es.video.frame_rate.num = 0;
--              port->es.video.frame_rate.den = 1;
-       }
-       port->es.video.crop.x = 0;
-       port->es.video.crop.y = 0;
-@@ -1361,6 +1363,41 @@ static int vidioc_s_selection(struct fil
-       return 0;
- }
-+static int vidioc_s_parm(struct file *file, void *priv,
-+                       struct v4l2_streamparm *parm)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+              return -EINVAL;
-+
-+      ctx->framerate_num =
-+                      parm->parm.output.timeperframe.denominator;
-+      ctx->framerate_denom =
-+                      parm->parm.output.timeperframe.numerator;
-+
-+      parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
-+
-+      return 0;
-+}
-+
-+static int vidioc_g_parm(struct file *file, void *priv,
-+                       struct v4l2_streamparm *parm)
-+{
-+      struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+              return -EINVAL;
-+
-+      parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
-+      parm->parm.output.timeperframe.denominator =
-+                      ctx->framerate_num;
-+      parm->parm.output.timeperframe.numerator =
-+                      ctx->framerate_denom;
-+
-+      return 0;
-+}
-+
- static int vidioc_subscribe_evt(struct v4l2_fh *fh,
-                               const struct v4l2_event_subscription *sub)
- {
-@@ -1725,6 +1762,9 @@ static const struct v4l2_ioctl_ops bcm28
-       .vidioc_g_selection     = vidioc_g_selection,
-       .vidioc_s_selection     = vidioc_s_selection,
-+      .vidioc_g_parm          = vidioc_g_parm,
-+      .vidioc_s_parm          = vidioc_s_parm,
-+
-       .vidioc_subscribe_event = vidioc_subscribe_evt,
-       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-@@ -2546,6 +2586,8 @@ static int bcm2835_codec_create(struct p
-       case DECODE:
-               v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-+              v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-+              v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
-               video_nr = decode_video_nr;
-               break;
-       case ENCODE:
-@@ -2558,6 +2600,8 @@ static int bcm2835_codec_create(struct p
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-+              v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-+              v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
-               video_nr = isp_video_nr;
-               break;
-       default:
diff --git a/target/linux/brcm2708/patches-4.19/950-0445-bcm2835-sdhost-Fix-DMA-channel-leak-on-error-remove.patch b/target/linux/brcm2708/patches-4.19/950-0445-bcm2835-sdhost-Fix-DMA-channel-leak-on-error-remove.patch
new file mode 100644 (file)
index 0000000..13ea94a
--- /dev/null
@@ -0,0 +1,31 @@
+From 73623c76c8bc8c41a4afefc1eee84dfc5979d652 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 20:45:17 +0100
+Subject: [PATCH] bcm2835-sdhost: Fix DMA channel leak on error/remove
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/bcm2835-sdhost.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-sdhost.c
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -2154,6 +2154,8 @@ static int bcm2835_sdhost_probe(struct p
+ err:
+       pr_debug("bcm2835_sdhost_probe -> err %d\n", ret);
++      if (host->dma_chan_rxtx)
++              dma_release_channel(host->dma_chan_rxtx);
+       mmc_free_host(mmc);
+       return ret;
+@@ -2174,7 +2176,8 @@ static int bcm2835_sdhost_remove(struct
+       del_timer_sync(&host->timer);
+       tasklet_kill(&host->finish_tasklet);
+-
++      if (host->dma_chan_rxtx)
++              dma_release_channel(host->dma_chan_rxtx);
+       mmc_free_host(host->mmc);
+       platform_set_drvdata(pdev, NULL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0445-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch b/target/linux/brcm2708/patches-4.19/950-0445-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch
deleted file mode 100644 (file)
index 6229fdc..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From afea1f84cbda94c47ba4a8f84d16c4330e145a0a Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 12 Jun 2019 17:15:05 +0100
-Subject: [PATCH] w1: w1-gpio: Make GPIO an output for strong pullup
-
-The logic to drive the data line high to implement a strong pullup
-assumed that the pin was already an output - setting a value does
-not change an input.
-
-See: https://github.com/raspberrypi/firmware/issues/1143
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/w1/masters/w1-gpio.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/w1/masters/w1-gpio.c
-+++ b/drivers/w1/masters/w1-gpio.c
-@@ -33,7 +33,7 @@ static u8 w1_gpio_set_pullup(void *data,
-                        * This will OVERRIDE open drain emulation and force-pull
-                        * the line high for some time.
-                        */
--                      gpiod_set_raw_value(pdata->gpiod, 1);
-+                      gpiod_direction_output_raw(pdata->gpiod, 1);
-                       msleep(pdata->pullup_duration);
-                       /*
-                        * This will simply set the line as input since we are doing
diff --git a/target/linux/brcm2708/patches-4.19/950-0446-i2c-bcm2835-Model-Divider-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0446-i2c-bcm2835-Model-Divider-in-CCF.patch
new file mode 100644 (file)
index 0000000..dc251a6
--- /dev/null
@@ -0,0 +1,270 @@
+From ffbb6cc14b8fb1876b249048284a5fe30f48c693 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Sat, 8 Jun 2019 10:14:43 -0700
+Subject: [PATCH] i2c: bcm2835: Model Divider in CCF
+
+Commit bebff81fb8b9216eb4fba22cf910553621ae3477 upstream.
+
+Model the I2C bus clock divider as a part of the Core Clock Framework.
+Primarily this removes the clk_get_rate() call from each transfer.
+This call causes problems for slave drivers that themselves have
+internal clock components that are controlled by an I2C interface.
+When the slave's internal clock component is prepared, the prepare
+lock is obtained, and it makes calls to the I2C subsystem to
+command the hardware to activate the clock.  In order to perform
+the I2C transfer, this driver sets the divider, which requires
+it to get the parent clock rate, which it does with clk_get_rate().
+Unfortunately, this function will try to take the clock prepare
+lock, which is already held by the slave's internal clock calls
+creating a deadlock.
+
+Modeling the divider in the CCF natively removes this dependency
+and the divider value is only set upon changing the bus clock
+frequency or changes in the parent clock that cascade down to this
+divisor.  This obviates the need to set the divider with every
+transfer and avoids the deadlock described above.  It also should
+provide better clock debugging and save a few cycles on each
+transfer due to not having to recalcuate the divider value.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 145 ++++++++++++++++++++++++-------
+ 1 file changed, 114 insertions(+), 31 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -12,6 +12,8 @@
+  */
+ #include <linux/clk.h>
++#include <linux/clkdev.h>
++#include <linux/clk-provider.h>
+ #include <linux/completion.h>
+ #include <linux/err.h>
+ #include <linux/i2c.h>
+@@ -71,9 +73,7 @@ struct bcm2835_debug {
+ struct bcm2835_i2c_dev {
+       struct device *dev;
+       void __iomem *regs;
+-      struct clk *clk;
+       int irq;
+-      u32 bus_clk_rate;
+       struct i2c_adapter adapter;
+       struct completion completion;
+       struct i2c_msg *curr_msg;
+@@ -164,12 +164,17 @@ static inline u32 bcm2835_i2c_readl(stru
+       return readl(i2c_dev->regs + reg);
+ }
+-static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
++#define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw)
++struct clk_bcm2835_i2c {
++      struct clk_hw hw;
++      struct bcm2835_i2c_dev *i2c_dev;
++};
++
++static int clk_bcm2835_i2c_calc_divider(unsigned long rate,
++                              unsigned long parent_rate)
+ {
+-      u32 divider, redl, fedl;
++      u32 divider = DIV_ROUND_UP(parent_rate, rate);
+-      divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
+-                             i2c_dev->bus_clk_rate);
+       /*
+        * Per the datasheet, the register is always interpreted as an even
+        * number, by rounding down. In other words, the LSB is ignored. So,
+@@ -178,12 +183,23 @@ static int bcm2835_i2c_set_divider(struc
+       if (divider & 1)
+               divider++;
+       if ((divider < BCM2835_I2C_CDIV_MIN) ||
+-          (divider > BCM2835_I2C_CDIV_MAX)) {
+-              dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
++          (divider > BCM2835_I2C_CDIV_MAX))
+               return -EINVAL;
+-      }
+-      bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
++      return divider;
++}
++
++static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate,
++                              unsigned long parent_rate)
++{
++      struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
++      u32 redl, fedl;
++      u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
++
++      if (divider == -EINVAL)
++              return -EINVAL;
++
++      bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider);
+       /*
+        * Number of core clocks to wait after falling edge before
+@@ -198,12 +214,62 @@ static int bcm2835_i2c_set_divider(struc
+        */
+       redl = max(divider / 4, 1u);
+-      bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL,
++      bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
+                          (fedl << BCM2835_I2C_FEDL_SHIFT) |
+                          (redl << BCM2835_I2C_REDL_SHIFT));
+       return 0;
+ }
++static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate,
++                              unsigned long *parent_rate)
++{
++      u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate);
++
++      return DIV_ROUND_UP(*parent_rate, divider);
++}
++
++static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
++                                              unsigned long parent_rate)
++{
++      struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
++      u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV);
++
++      return DIV_ROUND_UP(parent_rate, divider);
++}
++
++static const struct clk_ops clk_bcm2835_i2c_ops = {
++      .set_rate = clk_bcm2835_i2c_set_rate,
++      .round_rate = clk_bcm2835_i2c_round_rate,
++      .recalc_rate = clk_bcm2835_i2c_recalc_rate,
++};
++
++static struct clk *bcm2835_i2c_register_div(struct device *dev,
++                                      const char *mclk_name,
++                                      struct bcm2835_i2c_dev *i2c_dev)
++{
++      struct clk_init_data init;
++      struct clk_bcm2835_i2c *priv;
++      char name[32];
++
++      snprintf(name, sizeof(name), "%s_div", dev_name(dev));
++
++      init.ops = &clk_bcm2835_i2c_ops;
++      init.name = name;
++      init.parent_names = (const char* []) { mclk_name };
++      init.num_parents = 1;
++      init.flags = 0;
++
++      priv = devm_kzalloc(dev, sizeof(struct clk_bcm2835_i2c), GFP_KERNEL);
++      if (priv == NULL)
++              return ERR_PTR(-ENOMEM);
++
++      priv->hw.init = &init;
++      priv->i2c_dev = i2c_dev;
++
++      clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev));
++      return devm_clk_register(dev, &priv->hw);
++}
++
+ static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
+ {
+       u32 val;
+@@ -363,7 +429,7 @@ static int bcm2835_i2c_xfer(struct i2c_a
+ {
+       struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+       unsigned long time_left;
+-      int i, ret;
++      int i;
+       if (debug)
+               i2c_dev->debug_num_msgs = num;
+@@ -379,10 +445,6 @@ static int bcm2835_i2c_xfer(struct i2c_a
+                       return -EOPNOTSUPP;
+               }
+-      ret = bcm2835_i2c_set_divider(i2c_dev);
+-      if (ret)
+-              return ret;
+-
+       i2c_dev->curr_msg = msgs;
+       i2c_dev->num_msgs = num;
+       reinit_completion(&i2c_dev->completion);
+@@ -443,6 +505,9 @@ static int bcm2835_i2c_probe(struct plat
+       struct resource *mem, *irq;
+       int ret;
+       struct i2c_adapter *adap;
++      const char *mclk_name;
++      struct clk *bus_clk;
++      u32 bus_clk_rate;
+       i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+       if (!i2c_dev)
+@@ -456,21 +521,6 @@ static int bcm2835_i2c_probe(struct plat
+       if (IS_ERR(i2c_dev->regs))
+               return PTR_ERR(i2c_dev->regs);
+-      i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+-      if (IS_ERR(i2c_dev->clk)) {
+-              if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Could not get clock\n");
+-              return PTR_ERR(i2c_dev->clk);
+-      }
+-
+-      ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+-                                 &i2c_dev->bus_clk_rate);
+-      if (ret < 0) {
+-              dev_warn(&pdev->dev,
+-                       "Could not read clock-frequency property\n");
+-              i2c_dev->bus_clk_rate = 100000;
+-      }
+-
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "No IRQ resource\n");
+@@ -485,6 +535,35 @@ static int bcm2835_i2c_probe(struct plat
+               return -ENODEV;
+       }
++      mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
++
++      bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
++
++      if (IS_ERR(bus_clk)) {
++              dev_err(&pdev->dev, "Could not register clock\n");
++              return PTR_ERR(bus_clk);
++      }
++
++      ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
++                                 &bus_clk_rate);
++      if (ret < 0) {
++              dev_warn(&pdev->dev,
++                       "Could not read clock-frequency property\n");
++              bus_clk_rate = 100000;
++      }
++
++      ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
++      if (ret < 0) {
++              dev_err(&pdev->dev, "Could not set clock frequency\n");
++              return ret;
++      }
++
++      ret = clk_prepare_enable(bus_clk);
++      if (ret) {
++              dev_err(&pdev->dev, "Couldn't prepare clock");
++              return ret;
++      }
++
+       adap = &i2c_dev->adapter;
+       i2c_set_adapdata(adap, i2c_dev);
+       adap->owner = THIS_MODULE;
+@@ -507,6 +586,10 @@ static int bcm2835_i2c_probe(struct plat
+ static int bcm2835_i2c_remove(struct platform_device *pdev)
+ {
+       struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
++      struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
++
++      clk_rate_exclusive_put(bus_clk);
++      clk_disable_unprepare(bus_clk);
+       free_irq(i2c_dev->irq, i2c_dev);
+       i2c_del_adapter(&i2c_dev->adapter);
diff --git a/target/linux/brcm2708/patches-4.19/950-0446-overlays-Update-w1-gpio-and-w1-gpio-pullup.patch b/target/linux/brcm2708/patches-4.19/950-0446-overlays-Update-w1-gpio-and-w1-gpio-pullup.patch
deleted file mode 100644 (file)
index f19a638..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From 531ae7af75b2be2867814693f069fb51e3155341 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 12 Jun 2019 17:32:11 +0100
-Subject: [PATCH] overlays: Update w1-gpio and w1-gpio-pullup
-
-The parasitic power (power on data) feature is now enabled by
-default in the w1-gpio driver, so update the README and make the
-"pullup" parameter a no-op.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README                     | 9 ++-------
- arch/arm/boot/dts/overlays/w1-gpio-overlay.dts        | 3 +--
- arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts | 3 +--
- 3 files changed, 4 insertions(+), 11 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2261,9 +2261,7 @@ Info:   Configures the w1-gpio Onewire i
-         Use this overlay if you *don't* need a GPIO to drive an external pullup.
- Load:   dtoverlay=w1-gpio,<param>=<val>
- Params: gpiopin                 GPIO for I/O (default "4")
--
--        pullup                  Non-zero, "on", or "y" to enable the parasitic
--                                power (2-wire, power-on-data) feature
-+        pullup                  Now enabled by default (ignored)
- Name:   w1-gpio-pullup
-@@ -2271,11 +2269,8 @@ Info:   Configures the w1-gpio Onewire i
-         Use this overlay if you *do* need a GPIO to drive an external pullup.
- Load:   dtoverlay=w1-gpio-pullup,<param>=<val>
- Params: gpiopin                 GPIO for I/O (default "4")
--
--        pullup                  Non-zero, "on", or "y" to enable the parasitic
--                                power (2-wire, power-on-data) feature
--
-         extpullup               GPIO for external pullup (default "5")
-+        pullup                  Now enabled by default (ignored)
- Name:   wittypi
---- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-@@ -14,7 +14,6 @@
-                               pinctrl-names = "default";
-                               pinctrl-0 = <&w1_pins>;
-                               gpios = <&gpio 4 0>;
--                              rpi,parasitic-power = <0>;
-                               status = "okay";
-                       };
-               };
-@@ -36,6 +35,6 @@
-                               <&w1>,"reg:0",
-                               <&w1_pins>,"brcm,pins:0",
-                               <&w1_pins>,"reg:0";
--              pullup =        <&w1>,"rpi,parasitic-power:0";
-+              pullup;         // Silently ignore unneeded parameter
-       };
- };
---- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-@@ -14,7 +14,6 @@
-                               pinctrl-names = "default";
-                               pinctrl-0 = <&w1_pins>;
-                               gpios = <&gpio 4 0>, <&gpio 5 1>;
--                              rpi,parasitic-power = <0>;
-                               status = "okay";
-                       };
-               };
-@@ -38,6 +37,6 @@
-                               <&w1_pins>,"reg:0";
-               extpullup =     <&w1>,"gpios:16",
-                               <&w1_pins>,"brcm,pins:4";
--              pullup =        <&w1>,"rpi,parasitic-power:0";
-+              pullup;         // Silently ignore unneeded parameter
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0447-bcm2835-sdhost-Fix-DMA-channel-leak-on-error-remove.patch b/target/linux/brcm2708/patches-4.19/950-0447-bcm2835-sdhost-Fix-DMA-channel-leak-on-error-remove.patch
deleted file mode 100644 (file)
index 13ea94a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 73623c76c8bc8c41a4afefc1eee84dfc5979d652 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 12 Jun 2019 20:45:17 +0100
-Subject: [PATCH] bcm2835-sdhost: Fix DMA channel leak on error/remove
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/bcm2835-sdhost.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-sdhost.c
-+++ b/drivers/mmc/host/bcm2835-sdhost.c
-@@ -2154,6 +2154,8 @@ static int bcm2835_sdhost_probe(struct p
- err:
-       pr_debug("bcm2835_sdhost_probe -> err %d\n", ret);
-+      if (host->dma_chan_rxtx)
-+              dma_release_channel(host->dma_chan_rxtx);
-       mmc_free_host(mmc);
-       return ret;
-@@ -2174,7 +2176,8 @@ static int bcm2835_sdhost_remove(struct
-       del_timer_sync(&host->timer);
-       tasklet_kill(&host->finish_tasklet);
--
-+      if (host->dma_chan_rxtx)
-+              dma_release_channel(host->dma_chan_rxtx);
-       mmc_free_host(host->mmc);
-       platform_set_drvdata(pdev, NULL);
diff --git a/target/linux/brcm2708/patches-4.19/950-0447-staging-vc04_services-Use-correct-cache-line-size.patch b/target/linux/brcm2708/patches-4.19/950-0447-staging-vc04_services-Use-correct-cache-line-size.patch
new file mode 100644 (file)
index 0000000..c6b0606
--- /dev/null
@@ -0,0 +1,135 @@
+From 63079fbe20c954140f8eb61f858b0774890f301c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Sep 2018 09:22:21 +0100
+Subject: [PATCH] staging/vc04_services: Use correct cache line size
+
+Use the compatible string in the DTB to select the correct cache line
+size for the SoC - 32 for BCM2835, and 64 for BCM2836 and BCM2837.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../interface/vchiq_arm/vchiq_2835_arm.c      | 15 ++------
+ .../interface/vchiq_arm/vchiq_arm.c           | 35 +++++++++++++------
+ .../interface/vchiq_arm/vchiq_arm.h           |  5 +++
+ 3 files changed, 33 insertions(+), 22 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+@@ -117,7 +117,8 @@ free_pagelist(struct vchiq_pagelist_info
+ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
+ {
+       struct device *dev = &pdev->dev;
+-      struct rpi_firmware *fw = platform_get_drvdata(pdev);
++      struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
++      struct rpi_firmware *fw = drvdata->fw;
+       VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
+       struct resource *res;
+       void *slot_mem;
+@@ -135,17 +136,7 @@ int vchiq_platform_init(struct platform_
+       if (err < 0)
+               return err;
+-      /*
+-       * The tempting L1_CACHE_BYTES macro doesn't work in the case of
+-       * a kernel built with bcm2835_defconfig running on a BCM2836/7
+-       * processor, hence the need for a runtime check. The dcache line size
+-       * is encoded in one of the coprocessor registers, but there is no
+-       * convenient way to access it short of embedded assembler, hence
+-       * the use of read_cpuid_id(). The following test evaluates to true
+-       * on a BCM2835 showing that it is ARMv6-ish, whereas
+-       * cpu_architecture() will indicate that it is an ARMv7.
+-       */
+-      g_cache_line_size = ((read_cpuid_id() & 0x7f000) == 0x7b000) ? 32 : 64;
++      g_cache_line_size = drvdata->cache_line_size;
+       g_fragments_size = 2 * g_cache_line_size;
+       /* Allocate space for the channels in coherent memory */
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -173,6 +173,14 @@ static struct platform_device *bcm2835_c
+ static struct platform_device *bcm2835_codec;
+ static struct platform_device *vcsm_cma;
++static struct vchiq_drvdata bcm2835_drvdata = {
++      .cache_line_size = 32,
++};
++
++static struct vchiq_drvdata bcm2836_drvdata = {
++      .cache_line_size = 64,
++};
++
+ static const char *const ioctl_names[] = {
+       "CONNECT",
+       "SHUTDOWN",
+@@ -3607,12 +3615,25 @@ vchiq_register_child(struct platform_dev
+       return new_dev;
+ }
++static const struct of_device_id vchiq_of_match[] = {
++      { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
++      { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
++      {},
++};
++MODULE_DEVICE_TABLE(of, vchiq_of_match);
++
+ static int vchiq_probe(struct platform_device *pdev)
+ {
+       struct device_node *fw_node;
+-      struct rpi_firmware *fw;
++      const struct of_device_id *of_id;
++      struct vchiq_drvdata *drvdata;
+       int err;
++      of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
++      drvdata = (struct vchiq_drvdata *)of_id->data;
++      if (!drvdata)
++              return -EINVAL;
++
+       fw_node = of_find_compatible_node(NULL, NULL,
+                                         "raspberrypi,bcm2835-firmware");
+       if (!fw_node) {
+@@ -3620,12 +3641,12 @@ static int vchiq_probe(struct platform_d
+               return -ENOENT;
+       }
+-      fw = rpi_firmware_get(fw_node);
++      drvdata->fw = rpi_firmware_get(fw_node);
+       of_node_put(fw_node);
+-      if (!fw)
++      if (!drvdata->fw)
+               return -EPROBE_DEFER;
+-      platform_set_drvdata(pdev, fw);
++      platform_set_drvdata(pdev, drvdata);
+       err = vchiq_platform_init(pdev, &g_state);
+       if (err != 0)
+@@ -3703,12 +3724,6 @@ static int vchiq_remove(struct platform_
+       return 0;
+ }
+-static const struct of_device_id vchiq_of_match[] = {
+-      { .compatible = "brcm,bcm2835-vchiq", },
+-      {},
+-};
+-MODULE_DEVICE_TABLE(of, vchiq_of_match);
+-
+ static struct platform_driver vchiq_driver = {
+       .driver = {
+               .name = "bcm2835_vchiq",
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+@@ -123,6 +123,11 @@ typedef struct vchiq_arm_state_struct {
+ } VCHIQ_ARM_STATE_T;
++struct vchiq_drvdata {
++      const unsigned int cache_line_size;
++      struct rpi_firmware *fw;
++};
++
+ extern int vchiq_arm_log_level;
+ extern int vchiq_susp_log_level;
diff --git a/target/linux/brcm2708/patches-4.19/950-0448-i2c-bcm2835-Model-Divider-in-CCF.patch b/target/linux/brcm2708/patches-4.19/950-0448-i2c-bcm2835-Model-Divider-in-CCF.patch
deleted file mode 100644 (file)
index dc251a6..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-From ffbb6cc14b8fb1876b249048284a5fe30f48c693 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Sat, 8 Jun 2019 10:14:43 -0700
-Subject: [PATCH] i2c: bcm2835: Model Divider in CCF
-
-Commit bebff81fb8b9216eb4fba22cf910553621ae3477 upstream.
-
-Model the I2C bus clock divider as a part of the Core Clock Framework.
-Primarily this removes the clk_get_rate() call from each transfer.
-This call causes problems for slave drivers that themselves have
-internal clock components that are controlled by an I2C interface.
-When the slave's internal clock component is prepared, the prepare
-lock is obtained, and it makes calls to the I2C subsystem to
-command the hardware to activate the clock.  In order to perform
-the I2C transfer, this driver sets the divider, which requires
-it to get the parent clock rate, which it does with clk_get_rate().
-Unfortunately, this function will try to take the clock prepare
-lock, which is already held by the slave's internal clock calls
-creating a deadlock.
-
-Modeling the divider in the CCF natively removes this dependency
-and the divider value is only set upon changing the bus clock
-frequency or changes in the parent clock that cascade down to this
-divisor.  This obviates the need to set the divider with every
-transfer and avoids the deadlock described above.  It also should
-provide better clock debugging and save a few cycles on each
-transfer due to not having to recalcuate the divider value.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
----
- drivers/i2c/busses/i2c-bcm2835.c | 145 ++++++++++++++++++++++++-------
- 1 file changed, 114 insertions(+), 31 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -12,6 +12,8 @@
-  */
- #include <linux/clk.h>
-+#include <linux/clkdev.h>
-+#include <linux/clk-provider.h>
- #include <linux/completion.h>
- #include <linux/err.h>
- #include <linux/i2c.h>
-@@ -71,9 +73,7 @@ struct bcm2835_debug {
- struct bcm2835_i2c_dev {
-       struct device *dev;
-       void __iomem *regs;
--      struct clk *clk;
-       int irq;
--      u32 bus_clk_rate;
-       struct i2c_adapter adapter;
-       struct completion completion;
-       struct i2c_msg *curr_msg;
-@@ -164,12 +164,17 @@ static inline u32 bcm2835_i2c_readl(stru
-       return readl(i2c_dev->regs + reg);
- }
--static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
-+#define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw)
-+struct clk_bcm2835_i2c {
-+      struct clk_hw hw;
-+      struct bcm2835_i2c_dev *i2c_dev;
-+};
-+
-+static int clk_bcm2835_i2c_calc_divider(unsigned long rate,
-+                              unsigned long parent_rate)
- {
--      u32 divider, redl, fedl;
-+      u32 divider = DIV_ROUND_UP(parent_rate, rate);
--      divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
--                             i2c_dev->bus_clk_rate);
-       /*
-        * Per the datasheet, the register is always interpreted as an even
-        * number, by rounding down. In other words, the LSB is ignored. So,
-@@ -178,12 +183,23 @@ static int bcm2835_i2c_set_divider(struc
-       if (divider & 1)
-               divider++;
-       if ((divider < BCM2835_I2C_CDIV_MIN) ||
--          (divider > BCM2835_I2C_CDIV_MAX)) {
--              dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
-+          (divider > BCM2835_I2C_CDIV_MAX))
-               return -EINVAL;
--      }
--      bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
-+      return divider;
-+}
-+
-+static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate,
-+                              unsigned long parent_rate)
-+{
-+      struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
-+      u32 redl, fedl;
-+      u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
-+
-+      if (divider == -EINVAL)
-+              return -EINVAL;
-+
-+      bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider);
-       /*
-        * Number of core clocks to wait after falling edge before
-@@ -198,12 +214,62 @@ static int bcm2835_i2c_set_divider(struc
-        */
-       redl = max(divider / 4, 1u);
--      bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL,
-+      bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
-                          (fedl << BCM2835_I2C_FEDL_SHIFT) |
-                          (redl << BCM2835_I2C_REDL_SHIFT));
-       return 0;
- }
-+static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate,
-+                              unsigned long *parent_rate)
-+{
-+      u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate);
-+
-+      return DIV_ROUND_UP(*parent_rate, divider);
-+}
-+
-+static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
-+                                              unsigned long parent_rate)
-+{
-+      struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
-+      u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV);
-+
-+      return DIV_ROUND_UP(parent_rate, divider);
-+}
-+
-+static const struct clk_ops clk_bcm2835_i2c_ops = {
-+      .set_rate = clk_bcm2835_i2c_set_rate,
-+      .round_rate = clk_bcm2835_i2c_round_rate,
-+      .recalc_rate = clk_bcm2835_i2c_recalc_rate,
-+};
-+
-+static struct clk *bcm2835_i2c_register_div(struct device *dev,
-+                                      const char *mclk_name,
-+                                      struct bcm2835_i2c_dev *i2c_dev)
-+{
-+      struct clk_init_data init;
-+      struct clk_bcm2835_i2c *priv;
-+      char name[32];
-+
-+      snprintf(name, sizeof(name), "%s_div", dev_name(dev));
-+
-+      init.ops = &clk_bcm2835_i2c_ops;
-+      init.name = name;
-+      init.parent_names = (const char* []) { mclk_name };
-+      init.num_parents = 1;
-+      init.flags = 0;
-+
-+      priv = devm_kzalloc(dev, sizeof(struct clk_bcm2835_i2c), GFP_KERNEL);
-+      if (priv == NULL)
-+              return ERR_PTR(-ENOMEM);
-+
-+      priv->hw.init = &init;
-+      priv->i2c_dev = i2c_dev;
-+
-+      clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev));
-+      return devm_clk_register(dev, &priv->hw);
-+}
-+
- static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
- {
-       u32 val;
-@@ -363,7 +429,7 @@ static int bcm2835_i2c_xfer(struct i2c_a
- {
-       struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
-       unsigned long time_left;
--      int i, ret;
-+      int i;
-       if (debug)
-               i2c_dev->debug_num_msgs = num;
-@@ -379,10 +445,6 @@ static int bcm2835_i2c_xfer(struct i2c_a
-                       return -EOPNOTSUPP;
-               }
--      ret = bcm2835_i2c_set_divider(i2c_dev);
--      if (ret)
--              return ret;
--
-       i2c_dev->curr_msg = msgs;
-       i2c_dev->num_msgs = num;
-       reinit_completion(&i2c_dev->completion);
-@@ -443,6 +505,9 @@ static int bcm2835_i2c_probe(struct plat
-       struct resource *mem, *irq;
-       int ret;
-       struct i2c_adapter *adap;
-+      const char *mclk_name;
-+      struct clk *bus_clk;
-+      u32 bus_clk_rate;
-       i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
-       if (!i2c_dev)
-@@ -456,21 +521,6 @@ static int bcm2835_i2c_probe(struct plat
-       if (IS_ERR(i2c_dev->regs))
-               return PTR_ERR(i2c_dev->regs);
--      i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
--      if (IS_ERR(i2c_dev->clk)) {
--              if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER)
--                      dev_err(&pdev->dev, "Could not get clock\n");
--              return PTR_ERR(i2c_dev->clk);
--      }
--
--      ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
--                                 &i2c_dev->bus_clk_rate);
--      if (ret < 0) {
--              dev_warn(&pdev->dev,
--                       "Could not read clock-frequency property\n");
--              i2c_dev->bus_clk_rate = 100000;
--      }
--
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!irq) {
-               dev_err(&pdev->dev, "No IRQ resource\n");
-@@ -485,6 +535,35 @@ static int bcm2835_i2c_probe(struct plat
-               return -ENODEV;
-       }
-+      mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
-+
-+      bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
-+
-+      if (IS_ERR(bus_clk)) {
-+              dev_err(&pdev->dev, "Could not register clock\n");
-+              return PTR_ERR(bus_clk);
-+      }
-+
-+      ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-+                                 &bus_clk_rate);
-+      if (ret < 0) {
-+              dev_warn(&pdev->dev,
-+                       "Could not read clock-frequency property\n");
-+              bus_clk_rate = 100000;
-+      }
-+
-+      ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
-+      if (ret < 0) {
-+              dev_err(&pdev->dev, "Could not set clock frequency\n");
-+              return ret;
-+      }
-+
-+      ret = clk_prepare_enable(bus_clk);
-+      if (ret) {
-+              dev_err(&pdev->dev, "Couldn't prepare clock");
-+              return ret;
-+      }
-+
-       adap = &i2c_dev->adapter;
-       i2c_set_adapdata(adap, i2c_dev);
-       adap->owner = THIS_MODULE;
-@@ -507,6 +586,10 @@ static int bcm2835_i2c_probe(struct plat
- static int bcm2835_i2c_remove(struct platform_device *pdev)
- {
-       struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
-+      struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
-+
-+      clk_rate_exclusive_put(bus_clk);
-+      clk_disable_unprepare(bus_clk);
-       free_irq(i2c_dev->irq, i2c_dev);
-       i2c_del_adapter(&i2c_dev->adapter);
diff --git a/target/linux/brcm2708/patches-4.19/950-0448-tty-amba-pl011-allow-shared-interrupt.patch b/target/linux/brcm2708/patches-4.19/950-0448-tty-amba-pl011-allow-shared-interrupt.patch
new file mode 100644 (file)
index 0000000..5d316bd
--- /dev/null
@@ -0,0 +1,28 @@
+From ea75a716955e85ad076dd2861ca9e41def406a1b Mon Sep 17 00:00:00 2001
+From: Doug Berger <opendmb@gmail.com>
+Date: Mon, 13 May 2019 20:59:45 +0200
+Subject: [PATCH] tty: amba-pl011: allow shared interrupt
+
+The PL011 register space includes all necessary status bits to
+determine whether a device instance requires handling in response
+to an interrupt. Therefore, multiple instances of the device could
+be serviced by a single shared interrupt, which is the case on BCM7211.
+
+Signed-off-by: Doug Berger <opendmb@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/tty/serial/amba-pl011.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -1733,7 +1733,8 @@ static int pl011_allocate_irq(struct uar
+ {
+       pl011_write(uap->im, uap, REG_IMSC);
+-      return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
++      return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011",
++                         uap);
+ }
+ /*
diff --git a/target/linux/brcm2708/patches-4.19/950-0449-ARM-bcm283x-Reduce-register-ranges-for-UART-SPI-and-.patch b/target/linux/brcm2708/patches-4.19/950-0449-ARM-bcm283x-Reduce-register-ranges-for-UART-SPI-and-.patch
new file mode 100644 (file)
index 0000000..53fc19c
--- /dev/null
@@ -0,0 +1,44 @@
+From 3f6fe9da303fc01fb754a0a639ec3cdb813e8780 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 19 May 2019 12:20:00 +0200
+Subject: [PATCH] ARM: bcm283x: Reduce register ranges for UART, SPI
+ and I2C
+
+The assigned register ranges for UART, SPI and I2C were too wasteful.
+In order to avoid overlapping with the new functions on BCM2838
+reduce the ranges.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -387,7 +387,7 @@
+               uart0: serial@7e201000 {
+                       compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
+-                      reg = <0x7e201000 0x1000>;
++                      reg = <0x7e201000 0x200>;
+                       interrupts = <2 25>;
+                       clocks = <&clocks BCM2835_CLOCK_UART>,
+                                <&clocks BCM2835_CLOCK_VPU>;
+@@ -418,7 +418,7 @@
+               spi: spi@7e204000 {
+                       compatible = "brcm,bcm2835-spi";
+-                      reg = <0x7e204000 0x1000>;
++                      reg = <0x7e204000 0x200>;
+                       interrupts = <2 22>;
+                       clocks = <&clocks BCM2835_CLOCK_VPU>;
+                       #address-cells = <1>;
+@@ -428,7 +428,7 @@
+               i2c0: i2c@7e205000 {
+                       compatible = "brcm,bcm2835-i2c";
+-                      reg = <0x7e205000 0x1000>;
++                      reg = <0x7e205000 0x200>;
+                       interrupts = <2 21>;
+                       clocks = <&clocks BCM2835_CLOCK_VPU>;
+                       #address-cells = <1>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0449-staging-vc04_services-Use-correct-cache-line-size.patch b/target/linux/brcm2708/patches-4.19/950-0449-staging-vc04_services-Use-correct-cache-line-size.patch
deleted file mode 100644 (file)
index c6b0606..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-From 63079fbe20c954140f8eb61f858b0774890f301c Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 17 Sep 2018 09:22:21 +0100
-Subject: [PATCH] staging/vc04_services: Use correct cache line size
-
-Use the compatible string in the DTB to select the correct cache line
-size for the SoC - 32 for BCM2835, and 64 for BCM2836 and BCM2837.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../interface/vchiq_arm/vchiq_2835_arm.c      | 15 ++------
- .../interface/vchiq_arm/vchiq_arm.c           | 35 +++++++++++++------
- .../interface/vchiq_arm/vchiq_arm.h           |  5 +++
- 3 files changed, 33 insertions(+), 22 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-@@ -117,7 +117,8 @@ free_pagelist(struct vchiq_pagelist_info
- int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
- {
-       struct device *dev = &pdev->dev;
--      struct rpi_firmware *fw = platform_get_drvdata(pdev);
-+      struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
-+      struct rpi_firmware *fw = drvdata->fw;
-       VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
-       struct resource *res;
-       void *slot_mem;
-@@ -135,17 +136,7 @@ int vchiq_platform_init(struct platform_
-       if (err < 0)
-               return err;
--      /*
--       * The tempting L1_CACHE_BYTES macro doesn't work in the case of
--       * a kernel built with bcm2835_defconfig running on a BCM2836/7
--       * processor, hence the need for a runtime check. The dcache line size
--       * is encoded in one of the coprocessor registers, but there is no
--       * convenient way to access it short of embedded assembler, hence
--       * the use of read_cpuid_id(). The following test evaluates to true
--       * on a BCM2835 showing that it is ARMv6-ish, whereas
--       * cpu_architecture() will indicate that it is an ARMv7.
--       */
--      g_cache_line_size = ((read_cpuid_id() & 0x7f000) == 0x7b000) ? 32 : 64;
-+      g_cache_line_size = drvdata->cache_line_size;
-       g_fragments_size = 2 * g_cache_line_size;
-       /* Allocate space for the channels in coherent memory */
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -173,6 +173,14 @@ static struct platform_device *bcm2835_c
- static struct platform_device *bcm2835_codec;
- static struct platform_device *vcsm_cma;
-+static struct vchiq_drvdata bcm2835_drvdata = {
-+      .cache_line_size = 32,
-+};
-+
-+static struct vchiq_drvdata bcm2836_drvdata = {
-+      .cache_line_size = 64,
-+};
-+
- static const char *const ioctl_names[] = {
-       "CONNECT",
-       "SHUTDOWN",
-@@ -3607,12 +3615,25 @@ vchiq_register_child(struct platform_dev
-       return new_dev;
- }
-+static const struct of_device_id vchiq_of_match[] = {
-+      { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
-+      { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, vchiq_of_match);
-+
- static int vchiq_probe(struct platform_device *pdev)
- {
-       struct device_node *fw_node;
--      struct rpi_firmware *fw;
-+      const struct of_device_id *of_id;
-+      struct vchiq_drvdata *drvdata;
-       int err;
-+      of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
-+      drvdata = (struct vchiq_drvdata *)of_id->data;
-+      if (!drvdata)
-+              return -EINVAL;
-+
-       fw_node = of_find_compatible_node(NULL, NULL,
-                                         "raspberrypi,bcm2835-firmware");
-       if (!fw_node) {
-@@ -3620,12 +3641,12 @@ static int vchiq_probe(struct platform_d
-               return -ENOENT;
-       }
--      fw = rpi_firmware_get(fw_node);
-+      drvdata->fw = rpi_firmware_get(fw_node);
-       of_node_put(fw_node);
--      if (!fw)
-+      if (!drvdata->fw)
-               return -EPROBE_DEFER;
--      platform_set_drvdata(pdev, fw);
-+      platform_set_drvdata(pdev, drvdata);
-       err = vchiq_platform_init(pdev, &g_state);
-       if (err != 0)
-@@ -3703,12 +3724,6 @@ static int vchiq_remove(struct platform_
-       return 0;
- }
--static const struct of_device_id vchiq_of_match[] = {
--      { .compatible = "brcm,bcm2835-vchiq", },
--      {},
--};
--MODULE_DEVICE_TABLE(of, vchiq_of_match);
--
- static struct platform_driver vchiq_driver = {
-       .driver = {
-               .name = "bcm2835_vchiq",
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-@@ -123,6 +123,11 @@ typedef struct vchiq_arm_state_struct {
- } VCHIQ_ARM_STATE_T;
-+struct vchiq_drvdata {
-+      const unsigned int cache_line_size;
-+      struct rpi_firmware *fw;
-+};
-+
- extern int vchiq_arm_log_level;
- extern int vchiq_susp_log_level;
diff --git a/target/linux/brcm2708/patches-4.19/950-0450-ARM-bcm283x-Extend-the-WDT-DT-node-out-to-cover-the-.patch b/target/linux/brcm2708/patches-4.19/950-0450-ARM-bcm283x-Extend-the-WDT-DT-node-out-to-cover-the-.patch
new file mode 100644 (file)
index 0000000..84a6913
--- /dev/null
@@ -0,0 +1,45 @@
+From 9f889edf282d1d9a21c921e6cd33cebe22bcc4d4 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:49 -0800
+Subject: [PATCH] ARM: bcm283x: Extend the WDT DT node out to cover the
+ whole PM block. (v4)
+
+It was covering part of the PM block's range, up to the WDT regs.  To
+support the rest of the PM block's functionality, we need the full
+register range plus the AXI Async Bridge regs for PM sequencing.
+
+This doesn't convert any of the consumers over to the new binding yet,
+since we will need to be careful in coordinating our usage of firmware
+services that might power domains on and off versus the bcm2835-pm
+driver's access of those same domains.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+(cherry picked from commit 29abc92c1d93e28a8f4d55e6343eec4faf44025a)
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -121,8 +121,17 @@
+               };
+               watchdog@7e100000 {
+-                      compatible = "brcm,bcm2835-pm-wdt";
+-                      reg = <0x7e100000 0x28>;
++                      compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
++                      #power-domain-cells = <1>;
++                      #reset-cells = <1>;
++                      reg = <0x7e100000 0x114>,
++                            <0x7e00a000 0x24>;
++                      clocks = <&clocks BCM2835_CLOCK_V3D>,
++                               <&clocks BCM2835_CLOCK_PERI_IMAGE>,
++                               <&clocks BCM2835_CLOCK_H264>,
++                               <&clocks BCM2835_CLOCK_ISP>;
++                      clock-names = "v3d", "peri_image", "h264", "isp";
++                      system-power-controller;
+               };
+               clocks: cprman@7e101000 {
diff --git a/target/linux/brcm2708/patches-4.19/950-0450-tty-amba-pl011-allow-shared-interrupt.patch b/target/linux/brcm2708/patches-4.19/950-0450-tty-amba-pl011-allow-shared-interrupt.patch
deleted file mode 100644 (file)
index 5d316bd..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From ea75a716955e85ad076dd2861ca9e41def406a1b Mon Sep 17 00:00:00 2001
-From: Doug Berger <opendmb@gmail.com>
-Date: Mon, 13 May 2019 20:59:45 +0200
-Subject: [PATCH] tty: amba-pl011: allow shared interrupt
-
-The PL011 register space includes all necessary status bits to
-determine whether a device instance requires handling in response
-to an interrupt. Therefore, multiple instances of the device could
-be serviced by a single shared interrupt, which is the case on BCM7211.
-
-Signed-off-by: Doug Berger <opendmb@gmail.com>
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/tty/serial/amba-pl011.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/tty/serial/amba-pl011.c
-+++ b/drivers/tty/serial/amba-pl011.c
-@@ -1733,7 +1733,8 @@ static int pl011_allocate_irq(struct uar
- {
-       pl011_write(uap->im, uap, REG_IMSC);
--      return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
-+      return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011",
-+                         uap);
- }
- /*
diff --git a/target/linux/brcm2708/patches-4.19/950-0451-ARM-bcm283x-Reduce-register-ranges-for-UART-SPI-and-.patch b/target/linux/brcm2708/patches-4.19/950-0451-ARM-bcm283x-Reduce-register-ranges-for-UART-SPI-and-.patch
deleted file mode 100644 (file)
index 53fc19c..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 3f6fe9da303fc01fb754a0a639ec3cdb813e8780 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sun, 19 May 2019 12:20:00 +0200
-Subject: [PATCH] ARM: bcm283x: Reduce register ranges for UART, SPI
- and I2C
-
-The assigned register ranges for UART, SPI and I2C were too wasteful.
-In order to avoid overlapping with the new functions on BCM2838
-reduce the ranges.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm283x.dtsi | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -387,7 +387,7 @@
-               uart0: serial@7e201000 {
-                       compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
--                      reg = <0x7e201000 0x1000>;
-+                      reg = <0x7e201000 0x200>;
-                       interrupts = <2 25>;
-                       clocks = <&clocks BCM2835_CLOCK_UART>,
-                                <&clocks BCM2835_CLOCK_VPU>;
-@@ -418,7 +418,7 @@
-               spi: spi@7e204000 {
-                       compatible = "brcm,bcm2835-spi";
--                      reg = <0x7e204000 0x1000>;
-+                      reg = <0x7e204000 0x200>;
-                       interrupts = <2 22>;
-                       clocks = <&clocks BCM2835_CLOCK_VPU>;
-                       #address-cells = <1>;
-@@ -428,7 +428,7 @@
-               i2c0: i2c@7e205000 {
-                       compatible = "brcm,bcm2835-i2c";
--                      reg = <0x7e205000 0x1000>;
-+                      reg = <0x7e205000 0x200>;
-                       interrupts = <2 21>;
-                       clocks = <&clocks BCM2835_CLOCK_VPU>;
-                       #address-cells = <1>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0451-ARM-dts-Add-label-to-bcm2835-RNG.patch b/target/linux/brcm2708/patches-4.19/950-0451-ARM-dts-Add-label-to-bcm2835-RNG.patch
new file mode 100644 (file)
index 0000000..3d35540
--- /dev/null
@@ -0,0 +1,20 @@
+From 1297aac31942e596e6888d772ba49393a9f59417 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 4 May 2019 17:06:54 +0200
+Subject: [PATCH] ARM: dts: Add label to bcm2835 RNG
+
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -148,7 +148,7 @@
+                               <&dsi1 0>, <&dsi1 1>, <&dsi1 2>;
+               };
+-              rng@7e104000 {
++              rng: rng@7e104000 {
+                       compatible = "brcm,bcm2835-rng";
+                       reg = <0x7e104000 0x10>;
+                       interrupts = <2 29>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0452-ARM-bcm283x-Extend-the-WDT-DT-node-out-to-cover-the-.patch b/target/linux/brcm2708/patches-4.19/950-0452-ARM-bcm283x-Extend-the-WDT-DT-node-out-to-cover-the-.patch
deleted file mode 100644 (file)
index 84a6913..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From 9f889edf282d1d9a21c921e6cd33cebe22bcc4d4 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 12 Dec 2018 15:51:49 -0800
-Subject: [PATCH] ARM: bcm283x: Extend the WDT DT node out to cover the
- whole PM block. (v4)
-
-It was covering part of the PM block's range, up to the WDT regs.  To
-support the rest of the PM block's functionality, we need the full
-register range plus the AXI Async Bridge regs for PM sequencing.
-
-This doesn't convert any of the consumers over to the new binding yet,
-since we will need to be careful in coordinating our usage of firmware
-services that might power domains on and off versus the bcm2835-pm
-driver's access of those same domains.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-(cherry picked from commit 29abc92c1d93e28a8f4d55e6343eec4faf44025a)
----
- arch/arm/boot/dts/bcm283x.dtsi | 13 +++++++++++--
- 1 file changed, 11 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -121,8 +121,17 @@
-               };
-               watchdog@7e100000 {
--                      compatible = "brcm,bcm2835-pm-wdt";
--                      reg = <0x7e100000 0x28>;
-+                      compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
-+                      #power-domain-cells = <1>;
-+                      #reset-cells = <1>;
-+                      reg = <0x7e100000 0x114>,
-+                            <0x7e00a000 0x24>;
-+                      clocks = <&clocks BCM2835_CLOCK_V3D>,
-+                               <&clocks BCM2835_CLOCK_PERI_IMAGE>,
-+                               <&clocks BCM2835_CLOCK_H264>,
-+                               <&clocks BCM2835_CLOCK_ISP>;
-+                      clock-names = "v3d", "peri_image", "h264", "isp";
-+                      system-power-controller;
-               };
-               clocks: cprman@7e101000 {
diff --git a/target/linux/brcm2708/patches-4.19/950-0452-dts-Use-fb-rather-than-leds-for-dpi-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0452-dts-Use-fb-rather-than-leds-for-dpi-overlay.patch
new file mode 100644 (file)
index 0000000..9c7d073
--- /dev/null
@@ -0,0 +1,32 @@
+From 4a09c51bc328b2b83ffa20a6db02ac18139a963d Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 12 Oct 2017 18:11:32 +0100
+Subject: [PATCH] dts: Use fb rather than leds for dpi overlay
+
+---
+ arch/arm/boot/dts/overlays/dpi18-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dpi24-overlay.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
+@@ -9,7 +9,7 @@
+       // reference on - leds will do
+       fragment@0 {
+-              target = <&leds>;
++              target = <&fb>;
+               __overlay__ {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&dpi18_pins>;
+--- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
+@@ -9,7 +9,7 @@
+       // reference on - leds will do
+       fragment@0 {
+-              target = <&leds>;
++              target = <&fb>;
+               __overlay__ {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&dpi24_pins>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0453-ARM-dts-Add-label-to-bcm2835-RNG.patch b/target/linux/brcm2708/patches-4.19/950-0453-ARM-dts-Add-label-to-bcm2835-RNG.patch
deleted file mode 100644 (file)
index 3d35540..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From 1297aac31942e596e6888d772ba49393a9f59417 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 4 May 2019 17:06:54 +0200
-Subject: [PATCH] ARM: dts: Add label to bcm2835 RNG
-
----
- arch/arm/boot/dts/bcm283x.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -148,7 +148,7 @@
-                               <&dsi1 0>, <&dsi1 1>, <&dsi1 2>;
-               };
--              rng@7e104000 {
-+              rng: rng@7e104000 {
-                       compatible = "brcm,bcm2835-rng";
-                       reg = <0x7e104000 0x10>;
-                       interrupts = <2 29>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0453-BCM270X_DT-Minor-tidy-up.patch b/target/linux/brcm2708/patches-4.19/950-0453-BCM270X_DT-Minor-tidy-up.patch
new file mode 100644 (file)
index 0000000..70325f7
--- /dev/null
@@ -0,0 +1,95 @@
+From 021d54e3ae67e2b02310b9e3e871876a2c3b7eee Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:19:21 +0100
+Subject: [PATCH] BCM270X_DT: Minor tidy up
+
+Move arm_pmu out of soc on bcm2710, and labels aren't aliases.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm270x.dtsi | 14 +++++++-------
+ arch/arm/boot/dts/bcm2710.dtsi | 13 +++++--------
+ 2 files changed, 12 insertions(+), 15 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -10,11 +10,11 @@
+       soc: soc {
+               watchdog: watchdog@7e100000 {
+-                      /* Add alias */
++                      /* Add label */
+               };
+               random: rng@7e104000 {
+-                      /* Add alias */
++                      /* Add label */
+               };
+               gpio@7e200000 { /* gpio */
+@@ -40,18 +40,18 @@
+               };
+               spi0: spi@7e204000 {
+-                      /* Add alias */
++                      /* Add label */
+                       dmas = <&dma 6>, <&dma 7>;
+                       dma-names = "tx", "rx";
+               };
+               pixelvalve0: pixelvalve@7e206000 {
+-                      /* Add alias */
++                      /* Add label */
+                       status = "disabled";
+               };
+               pixelvalve1: pixelvalve@7e207000 {
+-                      /* Add alias */
++                      /* Add label */
+                       status = "disabled";
+               };
+@@ -93,7 +93,7 @@
+               };
+               hvs: hvs@7e400000 {
+-                      /* Add alias */
++                      /* Add label */
+                       status = "disabled";
+               };
+@@ -119,7 +119,7 @@
+               };
+               pixelvalve2: pixelvalve@7e807000 {
+-                      /* Add alias */
++                      /* Add label */
+                       status = "disabled";
+               };
+--- a/arch/arm/boot/dts/bcm2710.dtsi
++++ b/arch/arm/boot/dts/bcm2710.dtsi
+@@ -5,18 +5,15 @@
+ / {
+       compatible = "brcm,bcm2837", "brcm,bcm2836";
+-      soc {
+-
+-              arm-pmu {
++      arm-pmu {
+ #ifdef RPI364
+-                      compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
++              compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
+ #else
+-                      compatible = "arm,cortex-a7-pmu";
++              compatible = "arm,cortex-a7-pmu";
+ #endif
+-                      interrupt-parent = <&local_intc>;
+-                      interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
+-              };
++      };
++      soc {
+               /delete-node/ timer@7e003000;
+       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0454-arm-bcm2835-Fix-FIQ-early-ioremap.patch b/target/linux/brcm2708/patches-4.19/950-0454-arm-bcm2835-Fix-FIQ-early-ioremap.patch
new file mode 100644 (file)
index 0000000..d320e40
--- /dev/null
@@ -0,0 +1,73 @@
+From 51d6e1924fd0e9d075bcef61bea5a475a0ad6634 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 20 Feb 2019 08:49:39 +0000
+Subject: [PATCH] arm: bcm2835: Fix FIQ early ioremap
+
+The ioremapping creates mappings within the vmalloc area. The
+equivalent early function, create_mapping, now checks that the
+requested explicit virtual address is between VMALLOC_START and
+VMALLOC_END. As there is no reason to have any correlation between
+the physical and virtual addresses, put the required mappings at
+VMALLOC_START and above.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -14,17 +14,20 @@
+ #include <linux/init.h>
+ #include <linux/irqchip.h>
++#include <linux/mm.h>
+ #include <linux/of_address.h>
+ #include <linux/of_fdt.h>
+ #include <asm/system_info.h>
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
++#include <asm/memory.h>
++#include <asm/pgtable.h>
+ #include "platsmp.h"
+-#define BCM2835_USB_VIRT_BASE   0xf0980000
+-#define BCM2835_USB_VIRT_MPHI   0xf0006000
++#define BCM2835_USB_VIRT_BASE   (VMALLOC_START)
++#define BCM2835_USB_VIRT_MPHI   (VMALLOC_START + 0x10000)
+ static void __init bcm2835_init(void)
+ {
+@@ -83,20 +86,26 @@ static int __init bcm2835_map_usb(unsign
+ static void __init bcm2835_map_io(void)
+ {
+-      const __be32 *ranges;
++      const __be32 *ranges, *address_cells;
++      unsigned long root, addr_cells;
+       int soc, len;
+       unsigned long p2b_offset;
+       debug_ll_io_init();
++      root = of_get_flat_dt_root();
+       /* Find out how to map bus to physical address first from soc/ranges */
+-      soc = of_get_flat_dt_subnode_by_name(of_get_flat_dt_root(), "soc");
++      soc = of_get_flat_dt_subnode_by_name(root, "soc");
+       if (soc < 0)
+               return;
++      address_cells = of_get_flat_dt_prop(root, "#address-cells", &len);
++      if (!address_cells || len < (sizeof(unsigned long)))
++              return;
++      addr_cells = be32_to_cpu(address_cells[0]);
+       ranges = of_get_flat_dt_prop(soc, "ranges", &len);
+-      if (!ranges || len < (sizeof(unsigned long) * 3))
++      if (!ranges || len < (sizeof(unsigned long) * (2 + addr_cells)))
+               return;
+-      p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[1]);
++      p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[addr_cells]);
+       /* Now search for bcm2708-usb node in device tree */
+       of_scan_flat_dt(bcm2835_map_usb, &p2b_offset);
diff --git a/target/linux/brcm2708/patches-4.19/950-0454-dts-Use-fb-rather-than-leds-for-dpi-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0454-dts-Use-fb-rather-than-leds-for-dpi-overlay.patch
deleted file mode 100644 (file)
index 9c7d073..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From 4a09c51bc328b2b83ffa20a6db02ac18139a963d Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Thu, 12 Oct 2017 18:11:32 +0100
-Subject: [PATCH] dts: Use fb rather than leds for dpi overlay
-
----
- arch/arm/boot/dts/overlays/dpi18-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dpi24-overlay.dts | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-@@ -9,7 +9,7 @@
-       // reference on - leds will do
-       fragment@0 {
--              target = <&leds>;
-+              target = <&fb>;
-               __overlay__ {
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&dpi18_pins>;
---- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-@@ -9,7 +9,7 @@
-       // reference on - leds will do
-       fragment@0 {
--              target = <&leds>;
-+              target = <&fb>;
-               __overlay__ {
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&dpi24_pins>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0455-BCM270X_DT-Minor-tidy-up.patch b/target/linux/brcm2708/patches-4.19/950-0455-BCM270X_DT-Minor-tidy-up.patch
deleted file mode 100644 (file)
index 70325f7..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-From 021d54e3ae67e2b02310b9e3e871876a2c3b7eee Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 May 2019 15:19:21 +0100
-Subject: [PATCH] BCM270X_DT: Minor tidy up
-
-Move arm_pmu out of soc on bcm2710, and labels aren't aliases.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm270x.dtsi | 14 +++++++-------
- arch/arm/boot/dts/bcm2710.dtsi | 13 +++++--------
- 2 files changed, 12 insertions(+), 15 deletions(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -10,11 +10,11 @@
-       soc: soc {
-               watchdog: watchdog@7e100000 {
--                      /* Add alias */
-+                      /* Add label */
-               };
-               random: rng@7e104000 {
--                      /* Add alias */
-+                      /* Add label */
-               };
-               gpio@7e200000 { /* gpio */
-@@ -40,18 +40,18 @@
-               };
-               spi0: spi@7e204000 {
--                      /* Add alias */
-+                      /* Add label */
-                       dmas = <&dma 6>, <&dma 7>;
-                       dma-names = "tx", "rx";
-               };
-               pixelvalve0: pixelvalve@7e206000 {
--                      /* Add alias */
-+                      /* Add label */
-                       status = "disabled";
-               };
-               pixelvalve1: pixelvalve@7e207000 {
--                      /* Add alias */
-+                      /* Add label */
-                       status = "disabled";
-               };
-@@ -93,7 +93,7 @@
-               };
-               hvs: hvs@7e400000 {
--                      /* Add alias */
-+                      /* Add label */
-                       status = "disabled";
-               };
-@@ -119,7 +119,7 @@
-               };
-               pixelvalve2: pixelvalve@7e807000 {
--                      /* Add alias */
-+                      /* Add label */
-                       status = "disabled";
-               };
---- a/arch/arm/boot/dts/bcm2710.dtsi
-+++ b/arch/arm/boot/dts/bcm2710.dtsi
-@@ -5,18 +5,15 @@
- / {
-       compatible = "brcm,bcm2837", "brcm,bcm2836";
--      soc {
--
--              arm-pmu {
-+      arm-pmu {
- #ifdef RPI364
--                      compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
-+              compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
- #else
--                      compatible = "arm,cortex-a7-pmu";
-+              compatible = "arm,cortex-a7-pmu";
- #endif
--                      interrupt-parent = <&local_intc>;
--                      interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
--              };
-+      };
-+      soc {
-               /delete-node/ timer@7e003000;
-       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0455-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch b/target/linux/brcm2708/patches-4.19/950-0455-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch
new file mode 100644 (file)
index 0000000..b06b214
--- /dev/null
@@ -0,0 +1,39 @@
+From ab2695d38f4ffadde05c2275ac68f4aad68ef336 Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Thu, 14 Mar 2019 10:16:02 +0000
+Subject: [PATCH] Fix copy_from_user if BCM2835_FAST_MEMCPY=n
+
+The change which introduced CONFIG_BCM2835_FAST_MEMCPY unconditionally
+changed the behaviour of arm_copy_from_user. The page pinning code
+is not safe on ARMv7 if LPAE & high memory is enabled and causes
+crashes which look like PTE corruption.
+
+Make __copy_from_user_memcpy conditional on CONFIG_2835_FAST_MEMCPY=y
+which is really an ARMv6 / Pi1 optimization and not necessary on newer
+ARM processors.
+---
+ arch/arm/lib/uaccess_with_memcpy.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/arm/lib/uaccess_with_memcpy.c
++++ b/arch/arm/lib/uaccess_with_memcpy.c
+@@ -257,6 +257,7 @@ arm_copy_to_user(void __user *to, const
+ unsigned long __must_check
+ arm_copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
++#ifdef CONFIG_BCM2835_FAST_MEMCPY
+       /*
+        * This test is stubbed out of the main function above to keep
+        * the overhead for small copies low by avoiding a large
+@@ -271,6 +272,11 @@ arm_copy_from_user(void *to, const void
+       } else {
+               n = __copy_from_user_memcpy(to, from, n);
+       }
++#else
++      unsigned long ua_flags = uaccess_save_and_enable();
++      n = __copy_from_user_std(to, from, n);
++      uaccess_restore(ua_flags);
++#endif
+       return n;
+ }
+       
diff --git a/target/linux/brcm2708/patches-4.19/950-0456-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch b/target/linux/brcm2708/patches-4.19/950-0456-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch
new file mode 100644 (file)
index 0000000..88431e2
--- /dev/null
@@ -0,0 +1,1187 @@
+From ac1212c0f8b611be6df28f252ebbad80b775ee0f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH] PCI: brcmstb: Add Broadcom STB PCIe host controller
+ driver
+
+This commit adds the basic Broadcom STB PCIe controller.  Missing is
+the ability to process MSI and also handle dma-ranges for inbound
+memory accesses.  These two functionalities are added in subsequent
+commits.
+
+The PCIe block contains an MDIO interface.  This is a local interface
+only accessible by the PCIe controller.  It cannot be used or shared
+by any other HW.  As such, the small amount of code for this
+controller is included in this driver as there is little upside to put
+it elsewhere.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ drivers/pci/controller/Kconfig        |    9 +
+ drivers/pci/controller/Makefile       |    2 +-
+ drivers/pci/controller/pcie-brcmstb.c | 1097 +++++++++++++++++++++++++
+ include/soc/brcmstb/memory_api.h      |   25 +
+ 4 files changed, 1132 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/pci/controller/pcie-brcmstb.c
+ create mode 100644 include/soc/brcmstb/memory_api.h
+
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -278,5 +278,14 @@ config VMD
+         To compile this driver as a module, choose M here: the
+         module will be called vmd.
++config PCIE_BRCMSTB
++      tristate "Broadcom Brcmstb PCIe platform host driver"
++      depends on ARCH_BRCMSTB || BMIPS_GENERIC
++      depends on OF
++      depends on SOC_BRCMSTB
++      default ARCH_BRCMSTB || BMIPS_GENERIC
++      help
++        Adds support for Broadcom Settop Box PCIe host controller.
++
+ source "drivers/pci/controller/dwc/Kconfig"
+ endmenu
+--- a/drivers/pci/controller/Makefile
++++ b/drivers/pci/controller/Makefile
+@@ -28,11 +28,11 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie
+ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
+ obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
+ obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
++obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
+ obj-$(CONFIG_VMD) += vmd.o
+ # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+ obj-y                         += dwc/
+-
+ # The following drivers are for devices that use the generic ACPI
+ # pci_root.c driver but don't support standard ECAM config access.
+ # They contain MCFG quirks to replace the generic ECAM accessors with
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -0,0 +1,1097 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright (C) 2009 - 2017 Broadcom */
++
++#include <linux/clk.h>
++#include <linux/compiler.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/irqdomain.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/log2.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++#include <linux/of_platform.h>
++#include <linux/pci.h>
++#include <linux/printk.h>
++#include <linux/sizes.h>
++#include <linux/slab.h>
++#include <soc/brcmstb/memory_api.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include "../pci.h"
++
++/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
++#define BRCM_PCIE_CAP_REGS                            0x00ac
++
++/*
++ * Broadcom Settop Box PCIe Register Offsets. The names are from
++ * the chip's RDB and we use them here so that a script can correlate
++ * this code and the RDB to prevent discrepancies.
++ */
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1               0x0188
++#define PCIE_RC_CFG_PRIV1_ID_VAL3                     0x043c
++#define PCIE_RC_DL_MDIO_ADDR                          0x1100
++#define PCIE_RC_DL_MDIO_WR_DATA                               0x1104
++#define PCIE_RC_DL_MDIO_RD_DATA                               0x1108
++#define PCIE_MISC_MISC_CTRL                           0x4008
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO              0x400c
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI              0x4010
++#define PCIE_MISC_RC_BAR1_CONFIG_LO                   0x402c
++#define PCIE_MISC_RC_BAR2_CONFIG_LO                   0x4034
++#define PCIE_MISC_RC_BAR2_CONFIG_HI                   0x4038
++#define PCIE_MISC_RC_BAR3_CONFIG_LO                   0x403c
++#define PCIE_MISC_PCIE_CTRL                           0x4064
++#define PCIE_MISC_PCIE_STATUS                         0x4068
++#define PCIE_MISC_REVISION                            0x406c
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT      0x4070
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI         0x4080
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI                0x4084
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG                        0x4204
++#define PCIE_INTR2_CPU_BASE                           0x4300
++
++/*
++ * Broadcom Settop Box PCIe Register Field shift and mask info. The
++ * names are from the chip's RDB and we use them here so that a script
++ * can correlate this code and the RDB to prevent discrepancies.
++ */
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_SHIFT        0x2
++#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK             0xffffff
++#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_SHIFT            0x0
++#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK                        0x1000
++#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_SHIFT                       0xc
++#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK             0x2000
++#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_SHIFT            0xd
++#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK                       0x300000
++#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_SHIFT              0x14
++#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK                    0xf8000000
++#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_SHIFT                   0x1b
++#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK                    0x7c00000
++#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_SHIFT                   0x16
++#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK                    0x1f
++#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_SHIFT                   0x0
++#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK                 0x1f
++#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_SHIFT                        0x0
++#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK                 0x1f
++#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_SHIFT                        0x0
++#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK                 0x1f
++#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_SHIFT                        0x0
++#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK                  0x4
++#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_SHIFT                 0x2
++#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK             0x1
++#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_SHIFT            0x0
++#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK                  0x80
++#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_SHIFT                 0x7
++#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK             0x20
++#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_SHIFT            0x5
++#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK             0x10
++#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_SHIFT            0x4
++#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK           0x40
++#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_SHIFT          0x6
++#define PCIE_MISC_REVISION_MAJMIN_MASK                                0xffff
++#define PCIE_MISC_REVISION_MAJMIN_SHIFT                               0
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK   0xfff00000
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_SHIFT  0x14
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK    0xfff0
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_SHIFT   0x4
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS        0xc
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK               0xff
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_SHIFT      0x0
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK     0xff
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_SHIFT    0x0
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK       0x2
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_SHIFT 0x1
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK               0x08000000
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_SHIFT      0x1b
++#define PCIE_RGR1_SW_INIT_1_PERST_MASK                                0x1
++#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT                               0x0
++
++#define BRCM_NUM_PCIE_OUT_WINS                0x4
++#define BRCM_MAX_SCB                  0x4
++
++#define BRCM_MSI_TARGET_ADDR_LT_4GB   0x0fffffffcULL
++#define BRCM_MSI_TARGET_ADDR_GT_4GB   0xffffffffcULL
++
++#define BURST_SIZE_128                        0
++#define BURST_SIZE_256                        1
++#define BURST_SIZE_512                        2
++
++/* Offsets from PCIE_INTR2_CPU_BASE */
++#define STATUS                                0x0
++#define SET                           0x4
++#define CLR                           0x8
++#define MASK_STATUS                   0xc
++#define MASK_SET                      0x10
++#define MASK_CLR                      0x14
++
++#define PCIE_BUSNUM_SHIFT             20
++#define PCIE_SLOT_SHIFT                       15
++#define PCIE_FUNC_SHIFT                       12
++
++#if defined(__BIG_ENDIAN)
++#define       DATA_ENDIAN                     2       /* PCIe->DDR inbound traffic */
++#define MMIO_ENDIAN                   2       /* CPU->PCIe outbound traffic */
++#else
++#define       DATA_ENDIAN                     0
++#define MMIO_ENDIAN                   0
++#endif
++
++#define MDIO_PORT0                    0x0
++#define MDIO_DATA_MASK                        0x7fffffff
++#define MDIO_DATA_SHIFT                       0x0
++#define MDIO_PORT_MASK                        0xf0000
++#define MDIO_PORT_SHIFT                       0x16
++#define MDIO_REGAD_MASK                       0xffff
++#define MDIO_REGAD_SHIFT              0x0
++#define MDIO_CMD_MASK                 0xfff00000
++#define MDIO_CMD_SHIFT                        0x14
++#define MDIO_CMD_READ                 0x1
++#define MDIO_CMD_WRITE                        0x0
++#define MDIO_DATA_DONE_MASK           0x80000000
++#define MDIO_RD_DONE(x)                       (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
++#define MDIO_WT_DONE(x)                       (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
++#define SSC_REGS_ADDR                 0x1100
++#define SET_ADDR_OFFSET                       0x1f
++#define SSC_CNTL_OFFSET                       0x2
++#define SSC_CNTL_OVRD_EN_MASK         0x8000
++#define SSC_CNTL_OVRD_EN_SHIFT                0xf
++#define SSC_CNTL_OVRD_VAL_MASK                0x4000
++#define SSC_CNTL_OVRD_VAL_SHIFT               0xe
++#define SSC_STATUS_OFFSET             0x1
++#define SSC_STATUS_SSC_MASK           0x400
++#define SSC_STATUS_SSC_SHIFT          0xa
++#define SSC_STATUS_PLL_LOCK_MASK      0x800
++#define SSC_STATUS_PLL_LOCK_SHIFT     0xb
++
++#define IDX_ADDR(pcie)        \
++      ((pcie)->reg_offsets[EXT_CFG_INDEX])
++#define DATA_ADDR(pcie)       \
++      ((pcie)->reg_offsets[EXT_CFG_DATA])
++#define PCIE_RGR1_SW_INIT_1(pcie) \
++      ((pcie)->reg_offsets[RGR1_SW_INIT_1])
++
++enum {
++      RGR1_SW_INIT_1,
++      EXT_CFG_INDEX,
++      EXT_CFG_DATA,
++};
++
++enum {
++      RGR1_SW_INIT_1_INIT_MASK,
++      RGR1_SW_INIT_1_INIT_SHIFT,
++      RGR1_SW_INIT_1_PERST_MASK,
++      RGR1_SW_INIT_1_PERST_SHIFT,
++};
++
++enum pcie_type {
++      BCM7425,
++      BCM7435,
++      GENERIC,
++      BCM7278,
++};
++
++struct brcm_window {
++      dma_addr_t pcie_addr;
++      phys_addr_t cpu_addr;
++      dma_addr_t size;
++};
++
++/* Internal PCIe Host Controller Information.*/
++struct brcm_pcie {
++      struct device           *dev;
++      void __iomem            *base;
++      struct list_head        resources;
++      int                     irq;
++      struct clk              *clk;
++      struct pci_bus          *root_bus;
++      struct device_node      *dn;
++      int                     id;
++      bool                    suspended;
++      int                     num_out_wins;
++      bool                    ssc;
++      int                     gen;
++      struct brcm_window      out_wins[BRCM_NUM_PCIE_OUT_WINS];
++      unsigned int            rev;
++      const int               *reg_offsets;
++      const int               *reg_field_info;
++      enum pcie_type          type;
++};
++
++struct pcie_cfg_data {
++      const int *reg_field_info;
++      const int *offsets;
++      const enum pcie_type type;
++};
++
++static const int pcie_reg_field_info[] = {
++      [RGR1_SW_INIT_1_INIT_MASK] = 0x2,
++      [RGR1_SW_INIT_1_INIT_SHIFT] = 0x1,
++};
++
++static const int pcie_reg_field_info_bcm7278[] = {
++      [RGR1_SW_INIT_1_INIT_MASK] = 0x1,
++      [RGR1_SW_INIT_1_INIT_SHIFT] = 0x0,
++};
++
++static const int pcie_offset_bcm7425[] = {
++      [RGR1_SW_INIT_1] = 0x8010,
++      [EXT_CFG_INDEX]  = 0x8300,
++      [EXT_CFG_DATA]   = 0x8304,
++};
++
++static const struct pcie_cfg_data bcm7425_cfg = {
++      .reg_field_info = pcie_reg_field_info,
++      .offsets        = pcie_offset_bcm7425,
++      .type           = BCM7425,
++};
++
++static const int pcie_offsets[] = {
++      [RGR1_SW_INIT_1] = 0x9210,
++      [EXT_CFG_INDEX]  = 0x9000,
++      [EXT_CFG_DATA]   = 0x9004,
++};
++
++static const struct pcie_cfg_data bcm7435_cfg = {
++      .reg_field_info = pcie_reg_field_info,
++      .offsets        = pcie_offsets,
++      .type           = BCM7435,
++};
++
++static const struct pcie_cfg_data generic_cfg = {
++      .reg_field_info = pcie_reg_field_info,
++      .offsets        = pcie_offsets,
++      .type           = GENERIC,
++};
++
++static const int pcie_offset_bcm7278[] = {
++      [RGR1_SW_INIT_1] = 0xc010,
++      [EXT_CFG_INDEX] = 0x9000,
++      [EXT_CFG_DATA] = 0x9004,
++};
++
++static const struct pcie_cfg_data bcm7278_cfg = {
++      .reg_field_info = pcie_reg_field_info_bcm7278,
++      .offsets        = pcie_offset_bcm7278,
++      .type           = BCM7278,
++};
++
++static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
++                                      int where);
++
++static struct pci_ops brcm_pcie_ops = {
++      .map_bus = brcm_pcie_map_conf,
++      .read = pci_generic_config_read,
++      .write = pci_generic_config_write,
++};
++
++#if defined(CONFIG_MIPS)
++/* Broadcom MIPs HW implicitly does the swapping if necessary */
++#define bcm_readl(a)          __raw_readl(a)
++#define bcm_writel(d, a)      __raw_writel(d, a)
++#define bcm_readw(a)          __raw_readw(a)
++#define bcm_writew(d, a)      __raw_writew(d, a)
++#else
++#define bcm_readl(a)          readl(a)
++#define bcm_writel(d, a)      writel(d, a)
++#define bcm_readw(a)          readw(a)
++#define bcm_writew(d, a)      writew(d, a)
++#endif
++
++/* These macros extract/insert fields to host controller's register set. */
++#define RD_FLD(base, reg, field) \
++      rd_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT)
++#define WR_FLD(base, reg, field, val) \
++      wr_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
++#define WR_FLD_RB(base, reg, field, val) \
++      wr_fld_rb(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
++#define WR_FLD_WITH_OFFSET(base, off, reg, field, val) \
++      wr_fld(base + reg + off, reg##_##field##_MASK, \
++             reg##_##field##_SHIFT, val)
++#define EXTRACT_FIELD(val, reg, field) \
++      ((val & reg##_##field##_MASK) >> reg##_##field##_SHIFT)
++#define INSERT_FIELD(val, reg, field, field_val) \
++      ((val & ~reg##_##field##_MASK) | \
++       (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
++
++static phys_addr_t scb_size[BRCM_MAX_SCB];
++static int num_memc;
++static int num_pcie;
++static DEFINE_MUTEX(brcm_pcie_lock);
++
++static u32 rd_fld(void __iomem *p, u32 mask, int shift)
++{
++      return (bcm_readl(p) & mask) >> shift;
++}
++
++static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
++{
++      u32 reg = bcm_readl(p);
++
++      reg = (reg & ~mask) | ((val << shift) & mask);
++      bcm_writel(reg, p);
++}
++
++static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
++{
++      wr_fld(p, mask, shift, val);
++      (void)bcm_readl(p);
++}
++
++static const char *link_speed_to_str(int s)
++{
++      switch (s) {
++      case 1:
++              return "2.5";
++      case 2:
++              return "5.0";
++      case 3:
++              return "8.0";
++      default:
++              break;
++      }
++      return "???";
++}
++
++/*
++ * The roundup_pow_of_two() from log2.h invokes
++ * __roundup_pow_of_two(unsigned long), but we really need a
++ * such a function to take a native u64 since unsigned long
++ * is 32 bits on some configurations.  So we provide this helper
++ * function below.
++ */
++static u64 roundup_pow_of_two_64(u64 n)
++{
++      return 1ULL << fls64(n - 1);
++}
++
++/*
++ * This is to convert the size of the inbound "BAR" region to the
++ * non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
++ */
++int encode_ibar_size(u64 size)
++{
++      int log2_in = ilog2(size);
++
++      if (log2_in >= 12 && log2_in <= 15)
++              /* Covers 4KB to 32KB (inclusive) */
++              return (log2_in - 12) + 0x1c;
++      else if (log2_in >= 16 && log2_in <= 37)
++              /* Covers 64KB to 32GB, (inclusive) */
++              return log2_in - 15;
++      /* Something is awry so disable */
++      return 0;
++}
++
++static u32 mdio_form_pkt(int port, int regad, int cmd)
++{
++      u32 pkt = 0;
++
++      pkt |= (port << MDIO_PORT_SHIFT) & MDIO_PORT_MASK;
++      pkt |= (regad << MDIO_REGAD_SHIFT) & MDIO_REGAD_MASK;
++      pkt |= (cmd << MDIO_CMD_SHIFT) & MDIO_CMD_MASK;
++
++      return pkt;
++}
++
++/* negative return value indicates error */
++static int mdio_read(void __iomem *base, u8 port, u8 regad)
++{
++      int tries;
++      u32 data;
++
++      bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_READ),
++                 base + PCIE_RC_DL_MDIO_ADDR);
++      bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
++
++      data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
++      for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
++              udelay(10);
++              data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
++      }
++
++      return MDIO_RD_DONE(data)
++              ? (data & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT
++              : -EIO;
++}
++
++/* negative return value indicates error */
++static int mdio_write(void __iomem *base, u8 port, u8 regad, u16 wrdata)
++{
++      int tries;
++      u32 data;
++
++      bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
++                 base + PCIE_RC_DL_MDIO_ADDR);
++      bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
++      bcm_writel(MDIO_DATA_DONE_MASK | wrdata,
++                 base + PCIE_RC_DL_MDIO_WR_DATA);
++
++      data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
++      for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
++              udelay(10);
++              data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
++      }
++
++      return MDIO_WT_DONE(data) ? 0 : -EIO;
++}
++
++/*
++ * Configures device for Spread Spectrum Clocking (SSC) mode; a negative
++ * return value indicates error.
++ */
++static int set_ssc(void __iomem *base)
++{
++      int tmp;
++      u16 wrdata;
++      int pll, ssc;
++
++      tmp = mdio_write(base, MDIO_PORT0, SET_ADDR_OFFSET, SSC_REGS_ADDR);
++      if (tmp < 0)
++              return tmp;
++
++      tmp = mdio_read(base, MDIO_PORT0, SSC_CNTL_OFFSET);
++      if (tmp < 0)
++              return tmp;
++
++      wrdata = INSERT_FIELD(tmp, SSC_CNTL_OVRD, EN, 1);
++      wrdata = INSERT_FIELD(wrdata, SSC_CNTL_OVRD, VAL, 1);
++      tmp = mdio_write(base, MDIO_PORT0, SSC_CNTL_OFFSET, wrdata);
++      if (tmp < 0)
++              return tmp;
++
++      usleep_range(1000, 2000);
++      tmp = mdio_read(base, MDIO_PORT0, SSC_STATUS_OFFSET);
++      if (tmp < 0)
++              return tmp;
++
++      ssc = EXTRACT_FIELD(tmp, SSC_STATUS, SSC);
++      pll = EXTRACT_FIELD(tmp, SSC_STATUS, PLL_LOCK);
++
++      return (ssc && pll) ? 0 : -EIO;
++}
++
++/* Limits operation to a specific generation (1, 2, or 3) */
++static void set_gen(void __iomem *base, int gen)
++{
++      u32 lnkcap = bcm_readl(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
++      u16 lnkctl2 = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
++
++      lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
++      bcm_writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
++
++      lnkctl2 = (lnkctl2 & ~0xf) | gen;
++      bcm_writew(lnkctl2, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
++}
++
++static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
++                                     unsigned int win, phys_addr_t cpu_addr,
++                                     dma_addr_t  pcie_addr, dma_addr_t size)
++{
++      void __iomem *base = pcie->base;
++      phys_addr_t cpu_addr_mb, limit_addr_mb;
++      u32 tmp;
++
++      /* Set the base of the pcie_addr window */
++      bcm_writel(lower_32_bits(pcie_addr) + MMIO_ENDIAN,
++                 base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
++      bcm_writel(upper_32_bits(pcie_addr),
++                 base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
++
++      cpu_addr_mb = cpu_addr >> 20;
++      limit_addr_mb = (cpu_addr + size - 1) >> 20;
++
++      /* Write the addr base low register */
++      WR_FLD_WITH_OFFSET(base, (win * 4),
++                         PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
++                         BASE, cpu_addr_mb);
++      /* Write the addr limit low register */
++      WR_FLD_WITH_OFFSET(base, (win * 4),
++                         PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
++                         LIMIT, limit_addr_mb);
++
++      if (pcie->type != BCM7435 && pcie->type != BCM7425) {
++              /* Write the cpu addr high register */
++              tmp = (u32)(cpu_addr_mb >>
++                      PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
++              WR_FLD_WITH_OFFSET(base, (win * 8),
++                                 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI,
++                                 BASE, tmp);
++              /* Write the cpu limit high register */
++              tmp = (u32)(limit_addr_mb >>
++                      PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
++              WR_FLD_WITH_OFFSET(base, (win * 8),
++                                 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI,
++                                 LIMIT, tmp);
++      }
++}
++
++/* Configuration space read/write support */
++static int cfg_index(int busnr, int devfn, int reg)
++{
++      return ((PCI_SLOT(devfn) & 0x1f) << PCIE_SLOT_SHIFT)
++              | ((PCI_FUNC(devfn) & 0x07) << PCIE_FUNC_SHIFT)
++              | (busnr << PCIE_BUSNUM_SHIFT)
++              | (reg & ~3);
++}
++
++/* The controller is capable of serving in both RC and EP roles */
++static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
++{
++      void __iomem *base = pcie->base;
++      u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
++
++      return !!EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PORT);
++}
++
++static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
++{
++      void __iomem *base = pcie->base;
++      u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
++      u32 dla = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_DL_ACTIVE);
++      u32 plu = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PHYLINKUP);
++
++      return  (dla && plu) ? true : false;
++}
++
++static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
++                                      int where)
++{
++      struct brcm_pcie *pcie = bus->sysdata;
++      void __iomem *base = pcie->base;
++      int idx;
++
++      /* Accesses to the RC go right to the RC registers if slot==0 */
++      if (pci_is_root_bus(bus))
++              return PCI_SLOT(devfn) ? NULL : base + where;
++
++      /* For devices, write to the config space index register */
++      idx = cfg_index(bus->number, devfn, where);
++      bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
++      return base + DATA_ADDR(pcie) + (where & 0x3);
++}
++
++static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
++                                              unsigned int val)
++{
++      unsigned int shift = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_SHIFT];
++      u32 mask =  pcie->reg_field_info[RGR1_SW_INIT_1_INIT_MASK];
++
++      wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie), mask, shift, val);
++}
++
++static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
++                                     unsigned int val)
++{
++      if (pcie->type != BCM7278)
++              wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie),
++                        PCIE_RGR1_SW_INIT_1_PERST_MASK,
++                        PCIE_RGR1_SW_INIT_1_PERST_SHIFT, val);
++      else
++              /* Assert = 0, de-assert = 1 on 7278 */
++              WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
++}
++
++static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
++{
++      int i, ret = 0;
++
++      mutex_lock(&brcm_pcie_lock);
++      if (num_pcie > 0) {
++              num_pcie++;
++              goto done;
++      }
++
++      /* Determine num_memc and their sizes */
++      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
++              u64 size = brcmstb_memory_memc_size(i);
++
++              if (size == (u64)-1) {
++                      dev_err(pcie->dev, "cannot get memc%d size\n", i);
++                      ret = -EINVAL;
++                      goto done;
++              } else if (size) {
++                      scb_size[i] = roundup_pow_of_two_64(size);
++                      num_memc++;
++              } else {
++                      break;
++              }
++      }
++      if (!ret && num_memc == 0) {
++              ret = -EINVAL;
++              goto done;
++      }
++
++      num_pcie++;
++done:
++      mutex_unlock(&brcm_pcie_lock);
++      return ret;
++}
++
++static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
++{
++      mutex_lock(&brcm_pcie_lock);
++      if (--num_pcie == 0)
++              num_memc = 0;
++      mutex_unlock(&brcm_pcie_lock);
++}
++
++static int brcm_pcie_parse_request_of_pci_ranges(struct brcm_pcie *pcie)
++{
++      struct resource_entry *win;
++      int ret;
++
++      ret = devm_of_pci_get_host_bridge_resources(pcie->dev, 0, 0xff,
++                                                  &pcie->resources, NULL);
++      if (ret) {
++              dev_err(pcie->dev, "failed to get host resources\n");
++              return ret;
++      }
++
++      resource_list_for_each_entry(win, &pcie->resources) {
++              struct resource *parent, *res = win->res;
++              dma_addr_t offset = (dma_addr_t)win->offset;
++
++              if (resource_type(res) == IORESOURCE_IO) {
++                      parent = &ioport_resource;
++              } else if (resource_type(res) == IORESOURCE_MEM) {
++                      if (pcie->num_out_wins >= BRCM_NUM_PCIE_OUT_WINS) {
++                              dev_err(pcie->dev, "too many outbound wins\n");
++                              return -EINVAL;
++                      }
++                      pcie->out_wins[pcie->num_out_wins].cpu_addr
++                              = (phys_addr_t)res->start;
++                      pcie->out_wins[pcie->num_out_wins].pcie_addr
++                              = (dma_addr_t)(res->start
++                                             - (phys_addr_t)offset);
++                      pcie->out_wins[pcie->num_out_wins].size
++                              = (dma_addr_t)(res->end - res->start + 1);
++                      pcie->num_out_wins++;
++                      parent = &iomem_resource;
++              } else {
++                      continue;
++              }
++
++              ret = devm_request_resource(pcie->dev, parent, res);
++              if (ret) {
++                      dev_err(pcie->dev, "failed to get res %pR\n", res);
++                      return ret;
++              }
++      }
++      return 0;
++}
++
++static int brcm_pcie_setup(struct brcm_pcie *pcie)
++{
++      void __iomem *base = pcie->base;
++      unsigned int scb_size_val;
++      u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
++      u32 tmp, burst;
++      int i, j, ret, limit;
++      u16 nlw, cls, lnksta;
++      bool ssc_good = false;
++      struct device *dev = pcie->dev;
++
++      /* Reset the bridge */
++      brcm_pcie_bridge_sw_init_set(pcie, 1);
++
++      /*
++       * Ensure that the fundamental reset is asserted, except for 7278,
++       * which fails if we do this.
++       */
++      if (pcie->type != BCM7278)
++              brcm_pcie_perst_set(pcie, 1);
++
++      usleep_range(100, 200);
++
++      /* Take the bridge out of reset */
++      brcm_pcie_bridge_sw_init_set(pcie, 0);
++
++      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
++      /* Wait for SerDes to be stable */
++      usleep_range(100, 200);
++
++      /* Grab the PCIe hw revision number */
++      tmp = bcm_readl(base + PCIE_MISC_REVISION);
++      pcie->rev = EXTRACT_FIELD(tmp, PCIE_MISC_REVISION, MAJMIN);
++
++      /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
++      tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
++      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
++      burst = (pcie->type == GENERIC || pcie->type == BCM7278)
++              ? BURST_SIZE_512 : BURST_SIZE_256;
++      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
++      bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
++
++      /*
++       * Set up inbound memory view for the EP (called RC_BAR2,
++       * not to be confused with the BARs that are advertised by
++       * the EP).
++       */
++      for (i = 0; i < num_memc; i++)
++              total_mem_size += scb_size[i];
++
++      /*
++       * The PCIe host controller by design must set the inbound
++       * viewport to be a contiguous arrangement of all of the
++       * system's memory.  In addition, its size mut be a power of
++       * two.  To further complicate matters, the viewport must
++       * start on a pcie-address that is aligned on a multiple of its
++       * size.  If a portion of the viewport does not represent
++       * system memory -- e.g. 3GB of memory requires a 4GB viewport
++       * -- we can map the outbound memory in or after 3GB and even
++       * though the viewport will overlap the outbound memory the
++       * controller will know to send outbound memory downstream and
++       * everything else upstream.
++       */
++      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
++
++      /*
++       * Set simple configuration based on memory sizes
++       * only.  We always start the viewport at address 0.
++       */
++      rc_bar2_offset = 0;
++
++      tmp = lower_32_bits(rc_bar2_offset);
++      tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
++                         encode_ibar_size(rc_bar2_size));
++      bcm_writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
++      bcm_writel(upper_32_bits(rc_bar2_offset),
++                 base + PCIE_MISC_RC_BAR2_CONFIG_HI);
++
++      scb_size_val = scb_size[0]
++              ? ilog2(scb_size[0]) - 15 : 0xf; /* 0xf is 1GB */
++      WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_size_val);
++
++      if (num_memc > 1) {
++              scb_size_val = scb_size[1]
++                      ? ilog2(scb_size[1]) - 15 : 0xf; /* 0xf is 1GB */
++              WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB1_SIZE, scb_size_val);
++      }
++
++      if (num_memc > 2) {
++              scb_size_val = scb_size[2]
++                      ? ilog2(scb_size[2]) - 15 : 0xf; /* 0xf is 1GB */
++              WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB2_SIZE, scb_size_val);
++      }
++
++      /* disable the PCIe->GISB memory window (RC_BAR1) */
++      WR_FLD(base, PCIE_MISC_RC_BAR1_CONFIG_LO, SIZE, 0);
++
++      /* disable the PCIe->SCB memory window (RC_BAR3) */
++      WR_FLD(base, PCIE_MISC_RC_BAR3_CONFIG_LO, SIZE, 0);
++
++      if (!pcie->suspended) {
++              /* clear any interrupts we find on boot */
++              bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
++              (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + CLR);
++      }
++
++      /* Mask all interrupts since we are not handling any yet */
++      bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
++      (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
++
++      if (pcie->gen)
++              set_gen(base, pcie->gen);
++
++      /* Unassert the fundamental reset */
++      brcm_pcie_perst_set(pcie, 0);
++
++      /*
++       * Give the RC/EP time to wake up, before trying to configure RC.
++       * Intermittently check status for link-up, up to a total of 100ms
++       * when we don't know if the device is there, and up to 1000ms if
++       * we do know the device is there.
++       */
++      limit = pcie->suspended ? 1000 : 100;
++      for (i = 1, j = 0; j < limit && !brcm_pcie_link_up(pcie);
++           j += i, i = i * 2)
++              msleep(i + j > limit ? limit - j : i);
++
++      if (!brcm_pcie_link_up(pcie)) {
++              dev_info(dev, "link down\n");
++              return -ENODEV;
++      }
++
++      if (!brcm_pcie_rc_mode(pcie)) {
++              dev_err(dev, "PCIe misconfigured; is in EP mode\n");
++              return -EINVAL;
++      }
++
++      for (i = 0; i < pcie->num_out_wins; i++)
++              brcm_pcie_set_outbound_win(pcie, i, pcie->out_wins[i].cpu_addr,
++                                         pcie->out_wins[i].pcie_addr,
++                                         pcie->out_wins[i].size);
++
++      /*
++       * For config space accesses on the RC, show the right class for
++       * a PCIe-PCIe bridge (the default setting is to be EP mode).
++       */
++      WR_FLD_RB(base, PCIE_RC_CFG_PRIV1_ID_VAL3, CLASS_CODE, 0x060400);
++
++      if (pcie->ssc) {
++              ret = set_ssc(base);
++              if (ret == 0)
++                      ssc_good = true;
++              else
++                      dev_err(dev, "failed attempt to enter ssc mode\n");
++      }
++
++      lnksta = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA);
++      cls = lnksta & PCI_EXP_LNKSTA_CLS;
++      nlw = (lnksta & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
++      dev_info(dev, "link up, %s Gbps x%u %s\n", link_speed_to_str(cls),
++               nlw, ssc_good ? "(SSC)" : "(!SSC)");
++
++      /* PCIe->SCB endian mode for BAR */
++      /* field ENDIAN_MODE_BAR2 = DATA_ENDIAN */
++      WR_FLD_RB(base, PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1,
++                ENDIAN_MODE_BAR2, DATA_ENDIAN);
++
++      /*
++       * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
++       * is enabled =>  setting the CLKREQ_DEBUG_ENABLE field to 1.
++       */
++      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, CLKREQ_DEBUG_ENABLE, 1);
++
++      return 0;
++}
++
++/* L23 is a low-power PCIe link state */
++static void enter_l23(struct brcm_pcie *pcie)
++{
++      void __iomem *base = pcie->base;
++      int tries, l23;
++
++      /* assert request for L23 */
++      WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 1);
++      /* poll L23 status */
++      for (tries = 0, l23 = 0; tries < 1000 && !l23; tries++)
++              l23 = RD_FLD(base, PCIE_MISC_PCIE_STATUS, PCIE_LINK_IN_L23);
++      if (!l23)
++              dev_err(pcie->dev, "failed to enter L23\n");
++}
++
++static void turn_off(struct brcm_pcie *pcie)
++{
++      void __iomem *base = pcie->base;
++
++      if (brcm_pcie_link_up(pcie))
++              enter_l23(pcie);
++      /* Assert fundamental reset */
++      brcm_pcie_perst_set(pcie, 1);
++      /* Deassert request for L23 in case it was asserted */
++      WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 0);
++      /* Turn off SerDes */
++      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 1);
++      /* Shutdown PCIe bridge */
++      brcm_pcie_bridge_sw_init_set(pcie, 1);
++}
++
++static int brcm_pcie_suspend(struct device *dev)
++{
++      struct brcm_pcie *pcie = dev_get_drvdata(dev);
++
++      turn_off(pcie);
++      clk_disable_unprepare(pcie->clk);
++      pcie->suspended = true;
++
++      return 0;
++}
++
++static int brcm_pcie_resume(struct device *dev)
++{
++      struct brcm_pcie *pcie = dev_get_drvdata(dev);
++      void __iomem *base;
++      int ret;
++
++      base = pcie->base;
++      clk_prepare_enable(pcie->clk);
++
++      /* Take bridge out of reset so we can access the SerDes reg */
++      brcm_pcie_bridge_sw_init_set(pcie, 0);
++
++      /* Turn on SerDes */
++      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
++      /* Wait for SerDes to be stable */
++      usleep_range(100, 200);
++
++      ret = brcm_pcie_setup(pcie);
++      if (ret)
++              return ret;
++
++      pcie->suspended = false;
++
++      return 0;
++}
++
++static void _brcm_pcie_remove(struct brcm_pcie *pcie)
++{
++      turn_off(pcie);
++      clk_disable_unprepare(pcie->clk);
++      clk_put(pcie->clk);
++      brcm_pcie_remove_controller(pcie);
++}
++
++static int brcm_pcie_remove(struct platform_device *pdev)
++{
++      struct brcm_pcie *pcie = platform_get_drvdata(pdev);
++
++      pci_stop_root_bus(pcie->root_bus);
++      pci_remove_root_bus(pcie->root_bus);
++      _brcm_pcie_remove(pcie);
++
++      return 0;
++}
++
++static const struct of_device_id brcm_pcie_match[] = {
++      { .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
++      { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
++      { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
++      { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
++      {},
++};
++MODULE_DEVICE_TABLE(of, brcm_pcie_match);
++
++static int brcm_pcie_probe(struct platform_device *pdev)
++{
++      struct device_node *dn = pdev->dev.of_node;
++      const struct of_device_id *of_id;
++      const struct pcie_cfg_data *data;
++      int ret;
++      struct brcm_pcie *pcie;
++      struct resource *res;
++      void __iomem *base;
++      u32 tmp;
++      struct pci_host_bridge *bridge;
++      struct pci_bus *child;
++
++      bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
++      if (!bridge)
++              return -ENOMEM;
++
++      pcie = pci_host_bridge_priv(bridge);
++      INIT_LIST_HEAD(&pcie->resources);
++
++      of_id = of_match_node(brcm_pcie_match, dn);
++      if (!of_id) {
++              dev_err(&pdev->dev, "failed to look up compatible string\n");
++              return -EINVAL;
++      }
++
++      if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
++              dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
++              return -EINVAL;
++      }
++
++      data = of_id->data;
++      pcie->reg_offsets = data->offsets;
++      pcie->reg_field_info = data->reg_field_info;
++      pcie->type = data->type;
++      pcie->dn = dn;
++      pcie->dev = &pdev->dev;
++
++      /* We use the domain number as our controller number */
++      pcie->id = of_get_pci_domain_nr(dn);
++      if (pcie->id < 0)
++              return pcie->id;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!res)
++              return -EINVAL;
++
++      base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(base))
++              return PTR_ERR(base);
++
++      pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
++      if (IS_ERR(pcie->clk)) {
++              dev_err(&pdev->dev, "could not get clock\n");
++              pcie->clk = NULL;
++      }
++      pcie->base = base;
++
++      ret = of_pci_get_max_link_speed(dn);
++      pcie->gen = (ret < 0) ? 0 : ret;
++
++      pcie->ssc = of_property_read_bool(dn, "brcm,enable-ssc");
++
++      ret = irq_of_parse_and_map(pdev->dev.of_node, 0);
++      if (ret == 0)
++              /* keep going, as we don't use this intr yet */
++              dev_warn(pcie->dev, "cannot get PCIe interrupt\n");
++      else
++              pcie->irq = ret;
++
++      ret = brcm_pcie_parse_request_of_pci_ranges(pcie);
++      if (ret)
++              return ret;
++
++      ret = clk_prepare_enable(pcie->clk);
++      if (ret) {
++              dev_err(&pdev->dev, "could not enable clock\n");
++              return ret;
++      }
++
++      ret = brcm_pcie_add_controller(pcie);
++      if (ret)
++              return ret;
++
++      ret = brcm_pcie_setup(pcie);
++      if (ret)
++              goto fail;
++
++      list_splice_init(&pcie->resources, &bridge->windows);
++      bridge->dev.parent = &pdev->dev;
++      bridge->busnr = 0;
++      bridge->ops = &brcm_pcie_ops;
++      bridge->sysdata = pcie;
++      bridge->map_irq = of_irq_parse_and_map_pci;
++      bridge->swizzle_irq = pci_common_swizzle;
++
++      ret = pci_scan_root_bus_bridge(bridge);
++      if (ret < 0) {
++              dev_err(pcie->dev, "Scanning root bridge failed\n");
++              goto fail;
++      }
++
++      pci_assign_unassigned_bus_resources(bridge->bus);
++      list_for_each_entry(child, &bridge->bus->children, node)
++              pcie_bus_configure_settings(child);
++      pci_bus_add_devices(bridge->bus);
++      platform_set_drvdata(pdev, pcie);
++      pcie->root_bus = bridge->bus;
++
++      return 0;
++
++fail:
++      _brcm_pcie_remove(pcie);
++      return ret;
++}
++
++static const struct dev_pm_ops brcm_pcie_pm_ops = {
++      .suspend_noirq = brcm_pcie_suspend,
++      .resume_noirq = brcm_pcie_resume,
++};
++
++static struct platform_driver brcm_pcie_driver = {
++      .probe = brcm_pcie_probe,
++      .remove = brcm_pcie_remove,
++      .driver = {
++              .name = "brcm-pcie",
++              .owner = THIS_MODULE,
++              .of_match_table = brcm_pcie_match,
++              .pm = &brcm_pcie_pm_ops,
++      },
++};
++
++module_platform_driver(brcm_pcie_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("Broadcom STB PCIe RC driver");
++MODULE_AUTHOR("Broadcom");
+--- /dev/null
++++ b/include/soc/brcmstb/memory_api.h
+@@ -0,0 +1,25 @@
++#ifndef __MEMORY_API_H
++#define __MEMORY_API_H
++
++/*
++ * Bus Interface Unit control register setup, must happen early during boot,
++ * before SMP is brought up, called by machine entry point.
++ */
++void brcmstb_biuctrl_init(void);
++
++#ifdef CONFIG_SOC_BRCMSTB
++int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa);
++u64 brcmstb_memory_memc_size(int memc);
++#else
++static inline int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
++{
++      return -EINVAL;
++}
++
++static inline u64 brcmstb_memory_memc_size(int memc)
++{
++      return -1;
++}
++#endif
++
++#endif /* __MEMORY_API_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0456-arm-bcm2835-Fix-FIQ-early-ioremap.patch b/target/linux/brcm2708/patches-4.19/950-0456-arm-bcm2835-Fix-FIQ-early-ioremap.patch
deleted file mode 100644 (file)
index d320e40..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From 51d6e1924fd0e9d075bcef61bea5a475a0ad6634 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 20 Feb 2019 08:49:39 +0000
-Subject: [PATCH] arm: bcm2835: Fix FIQ early ioremap
-
-The ioremapping creates mappings within the vmalloc area. The
-equivalent early function, create_mapping, now checks that the
-requested explicit virtual address is between VMALLOC_START and
-VMALLOC_END. As there is no reason to have any correlation between
-the physical and virtual addresses, put the required mappings at
-VMALLOC_START and above.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/mach-bcm/board_bcm2835.c | 21 +++++++++++++++------
- 1 file changed, 15 insertions(+), 6 deletions(-)
-
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -14,17 +14,20 @@
- #include <linux/init.h>
- #include <linux/irqchip.h>
-+#include <linux/mm.h>
- #include <linux/of_address.h>
- #include <linux/of_fdt.h>
- #include <asm/system_info.h>
- #include <asm/mach/arch.h>
- #include <asm/mach/map.h>
-+#include <asm/memory.h>
-+#include <asm/pgtable.h>
- #include "platsmp.h"
--#define BCM2835_USB_VIRT_BASE   0xf0980000
--#define BCM2835_USB_VIRT_MPHI   0xf0006000
-+#define BCM2835_USB_VIRT_BASE   (VMALLOC_START)
-+#define BCM2835_USB_VIRT_MPHI   (VMALLOC_START + 0x10000)
- static void __init bcm2835_init(void)
- {
-@@ -83,20 +86,26 @@ static int __init bcm2835_map_usb(unsign
- static void __init bcm2835_map_io(void)
- {
--      const __be32 *ranges;
-+      const __be32 *ranges, *address_cells;
-+      unsigned long root, addr_cells;
-       int soc, len;
-       unsigned long p2b_offset;
-       debug_ll_io_init();
-+      root = of_get_flat_dt_root();
-       /* Find out how to map bus to physical address first from soc/ranges */
--      soc = of_get_flat_dt_subnode_by_name(of_get_flat_dt_root(), "soc");
-+      soc = of_get_flat_dt_subnode_by_name(root, "soc");
-       if (soc < 0)
-               return;
-+      address_cells = of_get_flat_dt_prop(root, "#address-cells", &len);
-+      if (!address_cells || len < (sizeof(unsigned long)))
-+              return;
-+      addr_cells = be32_to_cpu(address_cells[0]);
-       ranges = of_get_flat_dt_prop(soc, "ranges", &len);
--      if (!ranges || len < (sizeof(unsigned long) * 3))
-+      if (!ranges || len < (sizeof(unsigned long) * (2 + addr_cells)))
-               return;
--      p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[1]);
-+      p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[addr_cells]);
-       /* Now search for bcm2708-usb node in device tree */
-       of_scan_flat_dt(bcm2835_map_usb, &p2b_offset);
diff --git a/target/linux/brcm2708/patches-4.19/950-0457-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch b/target/linux/brcm2708/patches-4.19/950-0457-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch
deleted file mode 100644 (file)
index b06b214..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From ab2695d38f4ffadde05c2275ac68f4aad68ef336 Mon Sep 17 00:00:00 2001
-From: Tim Gover <tim.gover@raspberrypi.org>
-Date: Thu, 14 Mar 2019 10:16:02 +0000
-Subject: [PATCH] Fix copy_from_user if BCM2835_FAST_MEMCPY=n
-
-The change which introduced CONFIG_BCM2835_FAST_MEMCPY unconditionally
-changed the behaviour of arm_copy_from_user. The page pinning code
-is not safe on ARMv7 if LPAE & high memory is enabled and causes
-crashes which look like PTE corruption.
-
-Make __copy_from_user_memcpy conditional on CONFIG_2835_FAST_MEMCPY=y
-which is really an ARMv6 / Pi1 optimization and not necessary on newer
-ARM processors.
----
- arch/arm/lib/uaccess_with_memcpy.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/arch/arm/lib/uaccess_with_memcpy.c
-+++ b/arch/arm/lib/uaccess_with_memcpy.c
-@@ -257,6 +257,7 @@ arm_copy_to_user(void __user *to, const
- unsigned long __must_check
- arm_copy_from_user(void *to, const void __user *from, unsigned long n)
- {
-+#ifdef CONFIG_BCM2835_FAST_MEMCPY
-       /*
-        * This test is stubbed out of the main function above to keep
-        * the overhead for small copies low by avoiding a large
-@@ -271,6 +272,11 @@ arm_copy_from_user(void *to, const void
-       } else {
-               n = __copy_from_user_memcpy(to, from, n);
-       }
-+#else
-+      unsigned long ua_flags = uaccess_save_and_enable();
-+      n = __copy_from_user_std(to, from, n);
-+      uaccess_restore(ua_flags);
-+#endif
-       return n;
- }
-       
diff --git a/target/linux/brcm2708/patches-4.19/950-0457-PCI-brcmstb-Add-dma-range-mapping-for-inbound-traffi.patch b/target/linux/brcm2708/patches-4.19/950-0457-PCI-brcmstb-Add-dma-range-mapping-for-inbound-traffi.patch
new file mode 100644 (file)
index 0000000..75615e3
--- /dev/null
@@ -0,0 +1,569 @@
+From d3cc1c713b9436a7dc72788caa1d8de63ac3a01b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH] PCI: brcmstb: Add dma-range mapping for inbound
+ traffic
+
+The Broadcom STB PCIe host controller is intimately related to the
+memory subsystem.  This close relationship adds complexity to how cpu
+system memory is mapped to PCIe memory.  Ideally, this mapping is an
+identity mapping, or an identity mapping off by a constant.  Not so in
+this case.
+
+Consider the Broadcom reference board BCM97445LCC_4X8 which has 6 GB
+of system memory.  Here is how the PCIe controller maps the
+system memory to PCIe memory:
+
+  memc0-a@[        0....3fffffff] <=> pci@[        0....3fffffff]
+  memc0-b@[100000000...13fffffff] <=> pci@[ 40000000....7fffffff]
+  memc1-a@[ 40000000....7fffffff] <=> pci@[ 80000000....bfffffff]
+  memc1-b@[300000000...33fffffff] <=> pci@[ c0000000....ffffffff]
+  memc2-a@[ 80000000....bfffffff] <=> pci@[100000000...13fffffff]
+  memc2-b@[c00000000...c3fffffff] <=> pci@[140000000...17fffffff]
+
+Although there are some "gaps" that can be added between the
+individual mappings by software, the permutation of memory regions for
+the most part is fixed by HW.  The solution of having something close
+to an identity mapping is not possible.
+
+The idea behind this HW design is that the same PCIe module can
+act as an RC or EP, and if it acts as an EP it concatenates all
+of system memory into a BAR so anything can be accessed.  Unfortunately,
+when the PCIe block is in the role of an RC it also presents this
+"BAR" to downstream PCIe devices, rather than offering an identity map
+between its system memory and PCIe space.
+
+Suppose that an endpoint driver allocs some DMA memory.  Suppose this
+memory is located at 0x6000_0000, which is in the middle of memc1-a.
+The driver wants a dma_addr_t value that it can pass on to the EP to
+use.  Without doing any custom mapping, the EP will use this value for
+DMA: the driver will get a dma_addr_t equal to 0x6000_0000.  But this
+won't work; the device needs a dma_addr_t that reflects the PCIe space
+address, namely 0xa000_0000.
+
+So, essentially the solution to this problem must modify the
+dma_addr_t returned by the DMA routines routines.  There are two
+ways (I know of) of doing this:
+
+(a) overriding/redefining the dma_to_phys() and phys_to_dma() calls
+that are used by the dma_ops routines.  This is the approach of
+
+       arch/mips/cavium-octeon/dma-octeon.c
+
+In ARM and ARM64 these two routines are defiend in asm/dma-mapping.h
+as static inline functions.
+
+(b) Subscribe to a notifier that notifies when a device is added to a
+bus.  When this happens, set_dma_ops() can be called for the device.
+This method is mentioned in:
+
+    http://lxr.free-electrons.com/source/drivers/of/platform.c?v=3.16#L152
+
+where it says as a comment
+
+    "In case if platform code need to use own special DMA
+    configuration, it can use Platform bus notifier and
+    handle BUS_NOTIFY_ADD_DEVICE event to fix up DMA
+    configuration."
+
+Solution (b) is what this commit does.  It uses its own set of
+dma_ops which are wrappers around the arch_dma_ops.  The
+wrappers translate the dma addresses before/after invoking
+the arch_dma_ops, as appropriate.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 420 +++++++++++++++++++++++++-
+ 1 file changed, 411 insertions(+), 9 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -4,6 +4,7 @@
+ #include <linux/clk.h>
+ #include <linux/compiler.h>
+ #include <linux/delay.h>
++#include <linux/dma-mapping.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+@@ -319,11 +320,307 @@ static struct pci_ops brcm_pcie_ops = {
+       ((val & ~reg##_##field##_MASK) | \
+        (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
++static const struct dma_map_ops *arch_dma_ops;
++static const struct dma_map_ops *brcm_dma_ops_ptr;
++static struct of_pci_range *dma_ranges;
++static int num_dma_ranges;
++
+ static phys_addr_t scb_size[BRCM_MAX_SCB];
+ static int num_memc;
+ static int num_pcie;
+ static DEFINE_MUTEX(brcm_pcie_lock);
++static dma_addr_t brcm_to_pci(dma_addr_t addr)
++{
++      struct of_pci_range *p;
++
++      if (!num_dma_ranges)
++              return addr;
++
++      for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
++              if (addr >= p->cpu_addr && addr < (p->cpu_addr + p->size))
++                      return addr - p->cpu_addr + p->pci_addr;
++
++      return addr;
++}
++
++static dma_addr_t brcm_to_cpu(dma_addr_t addr)
++{
++      struct of_pci_range *p;
++
++      if (!num_dma_ranges)
++              return addr;
++
++      for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
++              if (addr >= p->pci_addr && addr < (p->pci_addr + p->size))
++                      return addr - p->pci_addr + p->cpu_addr;
++
++      return addr;
++}
++
++static void *brcm_alloc(struct device *dev, size_t size, dma_addr_t *handle,
++                      gfp_t gfp, unsigned long attrs)
++{
++      void *ret;
++
++      ret = arch_dma_ops->alloc(dev, size, handle, gfp, attrs);
++      if (ret)
++              *handle = brcm_to_pci(*handle);
++      return ret;
++}
++
++static void brcm_free(struct device *dev, size_t size, void *cpu_addr,
++                    dma_addr_t handle, unsigned long attrs)
++{
++      handle = brcm_to_cpu(handle);
++      arch_dma_ops->free(dev, size, cpu_addr, handle, attrs);
++}
++
++static int brcm_mmap(struct device *dev, struct vm_area_struct *vma,
++                   void *cpu_addr, dma_addr_t dma_addr, size_t size,
++                   unsigned long attrs)
++{
++      dma_addr = brcm_to_cpu(dma_addr);
++      return arch_dma_ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
++}
++
++static int brcm_get_sgtable(struct device *dev, struct sg_table *sgt,
++                          void *cpu_addr, dma_addr_t handle, size_t size,
++                          unsigned long attrs)
++{
++      handle = brcm_to_cpu(handle);
++      return arch_dma_ops->get_sgtable(dev, sgt, cpu_addr, handle, size,
++                                     attrs);
++}
++
++static dma_addr_t brcm_map_page(struct device *dev, struct page *page,
++                              unsigned long offset, size_t size,
++                              enum dma_data_direction dir,
++                              unsigned long attrs)
++{
++      return brcm_to_pci(arch_dma_ops->map_page(dev, page, offset, size,
++                                                dir, attrs));
++}
++
++static void brcm_unmap_page(struct device *dev, dma_addr_t handle,
++                          size_t size, enum dma_data_direction dir,
++                          unsigned long attrs)
++{
++      handle = brcm_to_cpu(handle);
++      arch_dma_ops->unmap_page(dev, handle, size, dir, attrs);
++}
++
++static int brcm_map_sg(struct device *dev, struct scatterlist *sgl,
++                     int nents, enum dma_data_direction dir,
++                     unsigned long attrs)
++{
++      int i, j;
++      struct scatterlist *sg;
++
++      for_each_sg(sgl, sg, nents, i) {
++#ifdef CONFIG_NEED_SG_DMA_LENGTH
++              sg->dma_length = sg->length;
++#endif
++              sg->dma_address =
++                      brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
++                                                 sg->length, dir, attrs);
++              if (dma_mapping_error(dev, sg->dma_address))
++                      goto bad_mapping;
++      }
++      return nents;
++
++bad_mapping:
++      for_each_sg(sgl, sg, i, j)
++              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
++                                           sg_dma_len(sg), dir, attrs);
++      return 0;
++}
++
++static void brcm_unmap_sg(struct device *dev,
++                        struct scatterlist *sgl, int nents,
++                        enum dma_data_direction dir,
++                        unsigned long attrs)
++{
++      int i;
++      struct scatterlist *sg;
++
++      for_each_sg(sgl, sg, nents, i)
++              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
++                                           sg_dma_len(sg), dir, attrs);
++}
++
++static void brcm_sync_single_for_cpu(struct device *dev,
++                                   dma_addr_t handle, size_t size,
++                                   enum dma_data_direction dir)
++{
++      handle = brcm_to_cpu(handle);
++      arch_dma_ops->sync_single_for_cpu(dev, handle, size, dir);
++}
++
++static void brcm_sync_single_for_device(struct device *dev,
++                                      dma_addr_t handle, size_t size,
++                                      enum dma_data_direction dir)
++{
++      handle = brcm_to_cpu(handle);
++      arch_dma_ops->sync_single_for_device(dev, handle, size, dir);
++}
++
++static dma_addr_t brcm_map_resource(struct device *dev, phys_addr_t phys,
++                                  size_t size,
++                                  enum dma_data_direction dir,
++                                  unsigned long attrs)
++{
++      if (arch_dma_ops->map_resource)
++              return brcm_to_pci(arch_dma_ops->map_resource
++                                 (dev, phys, size, dir, attrs));
++      return brcm_to_pci((dma_addr_t)phys);
++}
++
++static void brcm_unmap_resource(struct device *dev, dma_addr_t handle,
++                              size_t size, enum dma_data_direction dir,
++                              unsigned long attrs)
++{
++      if (arch_dma_ops->unmap_resource)
++              arch_dma_ops->unmap_resource(dev, brcm_to_cpu(handle), size,
++                                           dir, attrs);
++}
++
++void brcm_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
++                        int nents, enum dma_data_direction dir)
++{
++      struct scatterlist *sg;
++      int i;
++
++      for_each_sg(sgl, sg, nents, i)
++              brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
++                                                    sg->length, dir);
++}
++
++void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
++                           int nents, enum dma_data_direction dir)
++{
++      struct scatterlist *sg;
++      int i;
++
++      for_each_sg(sgl, sg, nents, i)
++              brcm_dma_ops_ptr->sync_single_for_device(dev,
++                                                       sg_dma_address(sg),
++                                                       sg->length, dir);
++}
++
++static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++      return arch_dma_ops->mapping_error(dev, dma_addr);
++}
++
++static int brcm_dma_supported(struct device *dev, u64 mask)
++{
++      if (num_dma_ranges) {
++              /*
++               * It is our translated addresses that the EP will "see", so
++               * we check all of the ranges for the largest possible value.
++               */
++              int i;
++
++              for (i = 0; i < num_dma_ranges; i++)
++                      if (dma_ranges[i].pci_addr + dma_ranges[i].size - 1
++                          > mask)
++                              return 0;
++              return 1;
++      }
++
++      return arch_dma_ops->dma_supported(dev, mask);
++}
++
++#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
++u64 brcm_get_required_mask)(struct device *dev)
++{
++      return arch_dma_ops->get_required_mask(dev);
++}
++#endif
++
++static const struct dma_map_ops brcm_dma_ops = {
++      .alloc                  = brcm_alloc,
++      .free                   = brcm_free,
++      .mmap                   = brcm_mmap,
++      .get_sgtable            = brcm_get_sgtable,
++      .map_page               = brcm_map_page,
++      .unmap_page             = brcm_unmap_page,
++      .map_sg                 = brcm_map_sg,
++      .unmap_sg               = brcm_unmap_sg,
++      .map_resource           = brcm_map_resource,
++      .unmap_resource         = brcm_unmap_resource,
++      .sync_single_for_cpu    = brcm_sync_single_for_cpu,
++      .sync_single_for_device = brcm_sync_single_for_device,
++      .sync_sg_for_cpu        = brcm_sync_sg_for_cpu,
++      .sync_sg_for_device     = brcm_sync_sg_for_device,
++      .mapping_error          = brcm_mapping_error,
++      .dma_supported          = brcm_dma_supported,
++#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
++      .get_required_mask      = brcm_get_required_mask,
++#endif
++};
++
++static void brcm_set_dma_ops(struct device *dev)
++{
++      int ret;
++
++      if (IS_ENABLED(CONFIG_ARM64)) {
++              /*
++               * We are going to invoke get_dma_ops().  That
++               * function, at this point in time, invokes
++               * get_arch_dma_ops(), and for ARM64 that function
++               * returns a pointer to dummy_dma_ops.  So then we'd
++               * like to call arch_setup_dma_ops(), but that isn't
++               * exported.  Instead, we call of_dma_configure(),
++               * which is exported, and this calls
++               * arch_setup_dma_ops().  Once we do this the call to
++               * get_dma_ops() will work properly because
++               * dev->dma_ops will be set.
++               */
++              ret = of_dma_configure(dev, dev->of_node, true);
++              if (ret) {
++                      dev_err(dev, "of_dma_configure() failed: %d\n", ret);
++                      return;
++              }
++      }
++
++      arch_dma_ops = get_dma_ops(dev);
++      if (!arch_dma_ops) {
++              dev_err(dev, "failed to get arch_dma_ops\n");
++              return;
++      }
++
++      set_dma_ops(dev, &brcm_dma_ops);
++}
++
++static int brcmstb_platform_notifier(struct notifier_block *nb,
++                                   unsigned long event, void *__dev)
++{
++      struct device *dev = __dev;
++
++      brcm_dma_ops_ptr = &brcm_dma_ops;
++      if (event != BUS_NOTIFY_ADD_DEVICE)
++              return NOTIFY_DONE;
++
++      brcm_set_dma_ops(dev);
++      return NOTIFY_OK;
++}
++
++static struct notifier_block brcmstb_platform_nb = {
++      .notifier_call = brcmstb_platform_notifier,
++};
++
++static int brcm_register_notifier(void)
++{
++      return bus_register_notifier(&pci_bus_type, &brcmstb_platform_nb);
++}
++
++static int brcm_unregister_notifier(void)
++{
++      return bus_unregister_notifier(&pci_bus_type, &brcmstb_platform_nb);
++}
++
+ static u32 rd_fld(void __iomem *p, u32 mask, int shift)
+ {
+       return (bcm_readl(p) & mask) >> shift;
+@@ -597,9 +894,71 @@ static inline void brcm_pcie_perst_set(s
+               WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
+ }
++static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
++                                   struct device_node *node)
++{
++      const int na = 3, ns = 2;
++      int rlen;
++
++      parser->node = node;
++      parser->pna = of_n_addr_cells(node);
++      parser->np = parser->pna + na + ns;
++
++      parser->range = of_get_property(node, "dma-ranges", &rlen);
++      if (!parser->range)
++              return -ENOENT;
++
++      parser->end = parser->range + rlen / sizeof(__be32);
++
++      return 0;
++}
++
++static int brcm_pcie_parse_map_dma_ranges(struct brcm_pcie *pcie)
++{
++      int i;
++      struct of_pci_range_parser parser;
++      struct device_node *dn = pcie->dn;
++
++      /*
++       * Parse dma-ranges property if present.  If there are multiple
++       * PCIe controllers, we only have to parse from one of them since
++       * the others will have an identical mapping.
++       */
++      if (!pci_dma_range_parser_init(&parser, dn)) {
++              unsigned int max_ranges
++                      = (parser.end - parser.range) / parser.np;
++
++              dma_ranges = kcalloc(max_ranges, sizeof(struct of_pci_range),
++                                   GFP_KERNEL);
++              if (!dma_ranges)
++                      return -ENOMEM;
++
++              for (i = 0; of_pci_range_parser_one(&parser, dma_ranges + i);
++                   i++)
++                      num_dma_ranges++;
++      }
++
++      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
++              u64 size = brcmstb_memory_memc_size(i);
++
++              if (size == (u64)-1) {
++                      dev_err(pcie->dev, "cannot get memc%d size", i);
++                      return -EINVAL;
++              } else if (size) {
++                      scb_size[i] = roundup_pow_of_two_64(size);
++                      num_memc++;
++              } else {
++                      break;
++              }
++      }
++
++      return 0;
++}
++
+ static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
+ {
+       int i, ret = 0;
++      struct device *dev = pcie->dev;
+       mutex_lock(&brcm_pcie_lock);
+       if (num_pcie > 0) {
+@@ -607,12 +966,21 @@ static int brcm_pcie_add_controller(stru
+               goto done;
+       }
++      ret = brcm_register_notifier();
++      if (ret) {
++              dev_err(dev, "failed to register pci bus notifier\n");
++              goto done;
++      }
++      ret = brcm_pcie_parse_map_dma_ranges(pcie);
++      if (ret)
++              goto done;
++
+       /* Determine num_memc and their sizes */
+       for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
+               u64 size = brcmstb_memory_memc_size(i);
+               if (size == (u64)-1) {
+-                      dev_err(pcie->dev, "cannot get memc%d size\n", i);
++                      dev_err(dev, "cannot get memc%d size\n", i);
+                       ret = -EINVAL;
+                       goto done;
+               } else if (size) {
+@@ -636,8 +1004,16 @@ done:
+ static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
+ {
+       mutex_lock(&brcm_pcie_lock);
+-      if (--num_pcie == 0)
+-              num_memc = 0;
++      if (--num_pcie > 0)
++              goto out;
++
++      if (brcm_unregister_notifier())
++              dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
++      kfree(dma_ranges);
++      dma_ranges = NULL;
++      num_dma_ranges = 0;
++      num_memc = 0;
++out:
+       mutex_unlock(&brcm_pcie_lock);
+ }
+@@ -757,6 +1133,38 @@ static int brcm_pcie_setup(struct brcm_p
+        */
+       rc_bar2_offset = 0;
++      if (dma_ranges) {
++              /*
++               * The best-case scenario is to place the inbound
++               * region in the first 4GB of pci-space, as some
++               * legacy devices can only address 32bits.
++               * We would also like to put the MSI under 4GB
++               * as well, since some devices require a 32bit
++               * MSI target address.
++               */
++              if (total_mem_size <= 0xc0000000ULL &&
++                  rc_bar2_size <= 0x100000000ULL) {
++                      rc_bar2_offset = 0;
++              } else {
++                      /*
++                       * The system memory is 4GB or larger so we
++                       * cannot start the inbound region at location
++                       * 0 (since we have to allow some space for
++                       * outbound memory @ 3GB).  So instead we
++                       * start it at the 1x multiple of its size
++                       */
++                      rc_bar2_offset = rc_bar2_size;
++              }
++
++      } else {
++              /*
++               * Set simple configuration based on memory sizes
++               * only.  We always start the viewport at address 0,
++               * and set the MSI target address accordingly.
++               */
++              rc_bar2_offset = 0;
++      }
++
+       tmp = lower_32_bits(rc_bar2_offset);
+       tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
+                          encode_ibar_size(rc_bar2_size));
+@@ -967,7 +1375,6 @@ static int brcm_pcie_probe(struct platfo
+       struct brcm_pcie *pcie;
+       struct resource *res;
+       void __iomem *base;
+-      u32 tmp;
+       struct pci_host_bridge *bridge;
+       struct pci_bus *child;
+@@ -984,11 +1391,6 @@ static int brcm_pcie_probe(struct platfo
+               return -EINVAL;
+       }
+-      if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
+-              dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
+-              return -EINVAL;
+-      }
+-
+       data = of_id->data;
+       pcie->reg_offsets = data->offsets;
+       pcie->reg_field_info = data->reg_field_info;
diff --git a/target/linux/brcm2708/patches-4.19/950-0458-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch b/target/linux/brcm2708/patches-4.19/950-0458-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch
deleted file mode 100644 (file)
index 88431e2..0000000
+++ /dev/null
@@ -1,1187 +0,0 @@
-From ac1212c0f8b611be6df28f252ebbad80b775ee0f Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH] PCI: brcmstb: Add Broadcom STB PCIe host controller
- driver
-
-This commit adds the basic Broadcom STB PCIe controller.  Missing is
-the ability to process MSI and also handle dma-ranges for inbound
-memory accesses.  These two functionalities are added in subsequent
-commits.
-
-The PCIe block contains an MDIO interface.  This is a local interface
-only accessible by the PCIe controller.  It cannot be used or shared
-by any other HW.  As such, the small amount of code for this
-controller is included in this driver as there is little upside to put
-it elsewhere.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- drivers/pci/controller/Kconfig        |    9 +
- drivers/pci/controller/Makefile       |    2 +-
- drivers/pci/controller/pcie-brcmstb.c | 1097 +++++++++++++++++++++++++
- include/soc/brcmstb/memory_api.h      |   25 +
- 4 files changed, 1132 insertions(+), 1 deletion(-)
- create mode 100644 drivers/pci/controller/pcie-brcmstb.c
- create mode 100644 include/soc/brcmstb/memory_api.h
-
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -278,5 +278,14 @@ config VMD
-         To compile this driver as a module, choose M here: the
-         module will be called vmd.
-+config PCIE_BRCMSTB
-+      tristate "Broadcom Brcmstb PCIe platform host driver"
-+      depends on ARCH_BRCMSTB || BMIPS_GENERIC
-+      depends on OF
-+      depends on SOC_BRCMSTB
-+      default ARCH_BRCMSTB || BMIPS_GENERIC
-+      help
-+        Adds support for Broadcom Settop Box PCIe host controller.
-+
- source "drivers/pci/controller/dwc/Kconfig"
- endmenu
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -28,11 +28,11 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie
- obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
- obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
- obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
-+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
- obj-$(CONFIG_VMD) += vmd.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y                         += dwc/
--
- # The following drivers are for devices that use the generic ACPI
- # pci_root.c driver but don't support standard ECAM config access.
- # They contain MCFG quirks to replace the generic ECAM accessors with
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -0,0 +1,1097 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* Copyright (C) 2009 - 2017 Broadcom */
-+
-+#include <linux/clk.h>
-+#include <linux/compiler.h>
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/ioport.h>
-+#include <linux/irqdomain.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/log2.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+#include <linux/of_platform.h>
-+#include <linux/pci.h>
-+#include <linux/printk.h>
-+#include <linux/sizes.h>
-+#include <linux/slab.h>
-+#include <soc/brcmstb/memory_api.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include "../pci.h"
-+
-+/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
-+#define BRCM_PCIE_CAP_REGS                            0x00ac
-+
-+/*
-+ * Broadcom Settop Box PCIe Register Offsets. The names are from
-+ * the chip's RDB and we use them here so that a script can correlate
-+ * this code and the RDB to prevent discrepancies.
-+ */
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1               0x0188
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3                     0x043c
-+#define PCIE_RC_DL_MDIO_ADDR                          0x1100
-+#define PCIE_RC_DL_MDIO_WR_DATA                               0x1104
-+#define PCIE_RC_DL_MDIO_RD_DATA                               0x1108
-+#define PCIE_MISC_MISC_CTRL                           0x4008
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO              0x400c
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI              0x4010
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO                   0x402c
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO                   0x4034
-+#define PCIE_MISC_RC_BAR2_CONFIG_HI                   0x4038
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO                   0x403c
-+#define PCIE_MISC_PCIE_CTRL                           0x4064
-+#define PCIE_MISC_PCIE_STATUS                         0x4068
-+#define PCIE_MISC_REVISION                            0x406c
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT      0x4070
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI         0x4080
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI                0x4084
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG                        0x4204
-+#define PCIE_INTR2_CPU_BASE                           0x4300
-+
-+/*
-+ * Broadcom Settop Box PCIe Register Field shift and mask info. The
-+ * names are from the chip's RDB and we use them here so that a script
-+ * can correlate this code and the RDB to prevent discrepancies.
-+ */
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_SHIFT        0x2
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK             0xffffff
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_SHIFT            0x0
-+#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK                        0x1000
-+#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_SHIFT                       0xc
-+#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK             0x2000
-+#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_SHIFT            0xd
-+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK                       0x300000
-+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_SHIFT              0x14
-+#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK                    0xf8000000
-+#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_SHIFT                   0x1b
-+#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK                    0x7c00000
-+#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_SHIFT                   0x16
-+#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK                    0x1f
-+#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_SHIFT                   0x0
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK                 0x1f
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_SHIFT                        0x0
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK                 0x1f
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_SHIFT                        0x0
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK                 0x1f
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_SHIFT                        0x0
-+#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK                  0x4
-+#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_SHIFT                 0x2
-+#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK             0x1
-+#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_SHIFT            0x0
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK                  0x80
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_SHIFT                 0x7
-+#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK             0x20
-+#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_SHIFT            0x5
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK             0x10
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_SHIFT            0x4
-+#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK           0x40
-+#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_SHIFT          0x6
-+#define PCIE_MISC_REVISION_MAJMIN_MASK                                0xffff
-+#define PCIE_MISC_REVISION_MAJMIN_SHIFT                               0
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK   0xfff00000
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_SHIFT  0x14
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK    0xfff0
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_SHIFT   0x4
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS        0xc
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK               0xff
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_SHIFT      0x0
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK     0xff
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_SHIFT    0x0
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK       0x2
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_SHIFT 0x1
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK               0x08000000
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_SHIFT      0x1b
-+#define PCIE_RGR1_SW_INIT_1_PERST_MASK                                0x1
-+#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT                               0x0
-+
-+#define BRCM_NUM_PCIE_OUT_WINS                0x4
-+#define BRCM_MAX_SCB                  0x4
-+
-+#define BRCM_MSI_TARGET_ADDR_LT_4GB   0x0fffffffcULL
-+#define BRCM_MSI_TARGET_ADDR_GT_4GB   0xffffffffcULL
-+
-+#define BURST_SIZE_128                        0
-+#define BURST_SIZE_256                        1
-+#define BURST_SIZE_512                        2
-+
-+/* Offsets from PCIE_INTR2_CPU_BASE */
-+#define STATUS                                0x0
-+#define SET                           0x4
-+#define CLR                           0x8
-+#define MASK_STATUS                   0xc
-+#define MASK_SET                      0x10
-+#define MASK_CLR                      0x14
-+
-+#define PCIE_BUSNUM_SHIFT             20
-+#define PCIE_SLOT_SHIFT                       15
-+#define PCIE_FUNC_SHIFT                       12
-+
-+#if defined(__BIG_ENDIAN)
-+#define       DATA_ENDIAN                     2       /* PCIe->DDR inbound traffic */
-+#define MMIO_ENDIAN                   2       /* CPU->PCIe outbound traffic */
-+#else
-+#define       DATA_ENDIAN                     0
-+#define MMIO_ENDIAN                   0
-+#endif
-+
-+#define MDIO_PORT0                    0x0
-+#define MDIO_DATA_MASK                        0x7fffffff
-+#define MDIO_DATA_SHIFT                       0x0
-+#define MDIO_PORT_MASK                        0xf0000
-+#define MDIO_PORT_SHIFT                       0x16
-+#define MDIO_REGAD_MASK                       0xffff
-+#define MDIO_REGAD_SHIFT              0x0
-+#define MDIO_CMD_MASK                 0xfff00000
-+#define MDIO_CMD_SHIFT                        0x14
-+#define MDIO_CMD_READ                 0x1
-+#define MDIO_CMD_WRITE                        0x0
-+#define MDIO_DATA_DONE_MASK           0x80000000
-+#define MDIO_RD_DONE(x)                       (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
-+#define MDIO_WT_DONE(x)                       (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
-+#define SSC_REGS_ADDR                 0x1100
-+#define SET_ADDR_OFFSET                       0x1f
-+#define SSC_CNTL_OFFSET                       0x2
-+#define SSC_CNTL_OVRD_EN_MASK         0x8000
-+#define SSC_CNTL_OVRD_EN_SHIFT                0xf
-+#define SSC_CNTL_OVRD_VAL_MASK                0x4000
-+#define SSC_CNTL_OVRD_VAL_SHIFT               0xe
-+#define SSC_STATUS_OFFSET             0x1
-+#define SSC_STATUS_SSC_MASK           0x400
-+#define SSC_STATUS_SSC_SHIFT          0xa
-+#define SSC_STATUS_PLL_LOCK_MASK      0x800
-+#define SSC_STATUS_PLL_LOCK_SHIFT     0xb
-+
-+#define IDX_ADDR(pcie)        \
-+      ((pcie)->reg_offsets[EXT_CFG_INDEX])
-+#define DATA_ADDR(pcie)       \
-+      ((pcie)->reg_offsets[EXT_CFG_DATA])
-+#define PCIE_RGR1_SW_INIT_1(pcie) \
-+      ((pcie)->reg_offsets[RGR1_SW_INIT_1])
-+
-+enum {
-+      RGR1_SW_INIT_1,
-+      EXT_CFG_INDEX,
-+      EXT_CFG_DATA,
-+};
-+
-+enum {
-+      RGR1_SW_INIT_1_INIT_MASK,
-+      RGR1_SW_INIT_1_INIT_SHIFT,
-+      RGR1_SW_INIT_1_PERST_MASK,
-+      RGR1_SW_INIT_1_PERST_SHIFT,
-+};
-+
-+enum pcie_type {
-+      BCM7425,
-+      BCM7435,
-+      GENERIC,
-+      BCM7278,
-+};
-+
-+struct brcm_window {
-+      dma_addr_t pcie_addr;
-+      phys_addr_t cpu_addr;
-+      dma_addr_t size;
-+};
-+
-+/* Internal PCIe Host Controller Information.*/
-+struct brcm_pcie {
-+      struct device           *dev;
-+      void __iomem            *base;
-+      struct list_head        resources;
-+      int                     irq;
-+      struct clk              *clk;
-+      struct pci_bus          *root_bus;
-+      struct device_node      *dn;
-+      int                     id;
-+      bool                    suspended;
-+      int                     num_out_wins;
-+      bool                    ssc;
-+      int                     gen;
-+      struct brcm_window      out_wins[BRCM_NUM_PCIE_OUT_WINS];
-+      unsigned int            rev;
-+      const int               *reg_offsets;
-+      const int               *reg_field_info;
-+      enum pcie_type          type;
-+};
-+
-+struct pcie_cfg_data {
-+      const int *reg_field_info;
-+      const int *offsets;
-+      const enum pcie_type type;
-+};
-+
-+static const int pcie_reg_field_info[] = {
-+      [RGR1_SW_INIT_1_INIT_MASK] = 0x2,
-+      [RGR1_SW_INIT_1_INIT_SHIFT] = 0x1,
-+};
-+
-+static const int pcie_reg_field_info_bcm7278[] = {
-+      [RGR1_SW_INIT_1_INIT_MASK] = 0x1,
-+      [RGR1_SW_INIT_1_INIT_SHIFT] = 0x0,
-+};
-+
-+static const int pcie_offset_bcm7425[] = {
-+      [RGR1_SW_INIT_1] = 0x8010,
-+      [EXT_CFG_INDEX]  = 0x8300,
-+      [EXT_CFG_DATA]   = 0x8304,
-+};
-+
-+static const struct pcie_cfg_data bcm7425_cfg = {
-+      .reg_field_info = pcie_reg_field_info,
-+      .offsets        = pcie_offset_bcm7425,
-+      .type           = BCM7425,
-+};
-+
-+static const int pcie_offsets[] = {
-+      [RGR1_SW_INIT_1] = 0x9210,
-+      [EXT_CFG_INDEX]  = 0x9000,
-+      [EXT_CFG_DATA]   = 0x9004,
-+};
-+
-+static const struct pcie_cfg_data bcm7435_cfg = {
-+      .reg_field_info = pcie_reg_field_info,
-+      .offsets        = pcie_offsets,
-+      .type           = BCM7435,
-+};
-+
-+static const struct pcie_cfg_data generic_cfg = {
-+      .reg_field_info = pcie_reg_field_info,
-+      .offsets        = pcie_offsets,
-+      .type           = GENERIC,
-+};
-+
-+static const int pcie_offset_bcm7278[] = {
-+      [RGR1_SW_INIT_1] = 0xc010,
-+      [EXT_CFG_INDEX] = 0x9000,
-+      [EXT_CFG_DATA] = 0x9004,
-+};
-+
-+static const struct pcie_cfg_data bcm7278_cfg = {
-+      .reg_field_info = pcie_reg_field_info_bcm7278,
-+      .offsets        = pcie_offset_bcm7278,
-+      .type           = BCM7278,
-+};
-+
-+static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
-+                                      int where);
-+
-+static struct pci_ops brcm_pcie_ops = {
-+      .map_bus = brcm_pcie_map_conf,
-+      .read = pci_generic_config_read,
-+      .write = pci_generic_config_write,
-+};
-+
-+#if defined(CONFIG_MIPS)
-+/* Broadcom MIPs HW implicitly does the swapping if necessary */
-+#define bcm_readl(a)          __raw_readl(a)
-+#define bcm_writel(d, a)      __raw_writel(d, a)
-+#define bcm_readw(a)          __raw_readw(a)
-+#define bcm_writew(d, a)      __raw_writew(d, a)
-+#else
-+#define bcm_readl(a)          readl(a)
-+#define bcm_writel(d, a)      writel(d, a)
-+#define bcm_readw(a)          readw(a)
-+#define bcm_writew(d, a)      writew(d, a)
-+#endif
-+
-+/* These macros extract/insert fields to host controller's register set. */
-+#define RD_FLD(base, reg, field) \
-+      rd_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT)
-+#define WR_FLD(base, reg, field, val) \
-+      wr_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
-+#define WR_FLD_RB(base, reg, field, val) \
-+      wr_fld_rb(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
-+#define WR_FLD_WITH_OFFSET(base, off, reg, field, val) \
-+      wr_fld(base + reg + off, reg##_##field##_MASK, \
-+             reg##_##field##_SHIFT, val)
-+#define EXTRACT_FIELD(val, reg, field) \
-+      ((val & reg##_##field##_MASK) >> reg##_##field##_SHIFT)
-+#define INSERT_FIELD(val, reg, field, field_val) \
-+      ((val & ~reg##_##field##_MASK) | \
-+       (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
-+
-+static phys_addr_t scb_size[BRCM_MAX_SCB];
-+static int num_memc;
-+static int num_pcie;
-+static DEFINE_MUTEX(brcm_pcie_lock);
-+
-+static u32 rd_fld(void __iomem *p, u32 mask, int shift)
-+{
-+      return (bcm_readl(p) & mask) >> shift;
-+}
-+
-+static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
-+{
-+      u32 reg = bcm_readl(p);
-+
-+      reg = (reg & ~mask) | ((val << shift) & mask);
-+      bcm_writel(reg, p);
-+}
-+
-+static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
-+{
-+      wr_fld(p, mask, shift, val);
-+      (void)bcm_readl(p);
-+}
-+
-+static const char *link_speed_to_str(int s)
-+{
-+      switch (s) {
-+      case 1:
-+              return "2.5";
-+      case 2:
-+              return "5.0";
-+      case 3:
-+              return "8.0";
-+      default:
-+              break;
-+      }
-+      return "???";
-+}
-+
-+/*
-+ * The roundup_pow_of_two() from log2.h invokes
-+ * __roundup_pow_of_two(unsigned long), but we really need a
-+ * such a function to take a native u64 since unsigned long
-+ * is 32 bits on some configurations.  So we provide this helper
-+ * function below.
-+ */
-+static u64 roundup_pow_of_two_64(u64 n)
-+{
-+      return 1ULL << fls64(n - 1);
-+}
-+
-+/*
-+ * This is to convert the size of the inbound "BAR" region to the
-+ * non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
-+ */
-+int encode_ibar_size(u64 size)
-+{
-+      int log2_in = ilog2(size);
-+
-+      if (log2_in >= 12 && log2_in <= 15)
-+              /* Covers 4KB to 32KB (inclusive) */
-+              return (log2_in - 12) + 0x1c;
-+      else if (log2_in >= 16 && log2_in <= 37)
-+              /* Covers 64KB to 32GB, (inclusive) */
-+              return log2_in - 15;
-+      /* Something is awry so disable */
-+      return 0;
-+}
-+
-+static u32 mdio_form_pkt(int port, int regad, int cmd)
-+{
-+      u32 pkt = 0;
-+
-+      pkt |= (port << MDIO_PORT_SHIFT) & MDIO_PORT_MASK;
-+      pkt |= (regad << MDIO_REGAD_SHIFT) & MDIO_REGAD_MASK;
-+      pkt |= (cmd << MDIO_CMD_SHIFT) & MDIO_CMD_MASK;
-+
-+      return pkt;
-+}
-+
-+/* negative return value indicates error */
-+static int mdio_read(void __iomem *base, u8 port, u8 regad)
-+{
-+      int tries;
-+      u32 data;
-+
-+      bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_READ),
-+                 base + PCIE_RC_DL_MDIO_ADDR);
-+      bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
-+
-+      data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
-+      for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
-+              udelay(10);
-+              data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
-+      }
-+
-+      return MDIO_RD_DONE(data)
-+              ? (data & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT
-+              : -EIO;
-+}
-+
-+/* negative return value indicates error */
-+static int mdio_write(void __iomem *base, u8 port, u8 regad, u16 wrdata)
-+{
-+      int tries;
-+      u32 data;
-+
-+      bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
-+                 base + PCIE_RC_DL_MDIO_ADDR);
-+      bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
-+      bcm_writel(MDIO_DATA_DONE_MASK | wrdata,
-+                 base + PCIE_RC_DL_MDIO_WR_DATA);
-+
-+      data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
-+      for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
-+              udelay(10);
-+              data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
-+      }
-+
-+      return MDIO_WT_DONE(data) ? 0 : -EIO;
-+}
-+
-+/*
-+ * Configures device for Spread Spectrum Clocking (SSC) mode; a negative
-+ * return value indicates error.
-+ */
-+static int set_ssc(void __iomem *base)
-+{
-+      int tmp;
-+      u16 wrdata;
-+      int pll, ssc;
-+
-+      tmp = mdio_write(base, MDIO_PORT0, SET_ADDR_OFFSET, SSC_REGS_ADDR);
-+      if (tmp < 0)
-+              return tmp;
-+
-+      tmp = mdio_read(base, MDIO_PORT0, SSC_CNTL_OFFSET);
-+      if (tmp < 0)
-+              return tmp;
-+
-+      wrdata = INSERT_FIELD(tmp, SSC_CNTL_OVRD, EN, 1);
-+      wrdata = INSERT_FIELD(wrdata, SSC_CNTL_OVRD, VAL, 1);
-+      tmp = mdio_write(base, MDIO_PORT0, SSC_CNTL_OFFSET, wrdata);
-+      if (tmp < 0)
-+              return tmp;
-+
-+      usleep_range(1000, 2000);
-+      tmp = mdio_read(base, MDIO_PORT0, SSC_STATUS_OFFSET);
-+      if (tmp < 0)
-+              return tmp;
-+
-+      ssc = EXTRACT_FIELD(tmp, SSC_STATUS, SSC);
-+      pll = EXTRACT_FIELD(tmp, SSC_STATUS, PLL_LOCK);
-+
-+      return (ssc && pll) ? 0 : -EIO;
-+}
-+
-+/* Limits operation to a specific generation (1, 2, or 3) */
-+static void set_gen(void __iomem *base, int gen)
-+{
-+      u32 lnkcap = bcm_readl(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
-+      u16 lnkctl2 = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
-+
-+      lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
-+      bcm_writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
-+
-+      lnkctl2 = (lnkctl2 & ~0xf) | gen;
-+      bcm_writew(lnkctl2, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
-+}
-+
-+static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
-+                                     unsigned int win, phys_addr_t cpu_addr,
-+                                     dma_addr_t  pcie_addr, dma_addr_t size)
-+{
-+      void __iomem *base = pcie->base;
-+      phys_addr_t cpu_addr_mb, limit_addr_mb;
-+      u32 tmp;
-+
-+      /* Set the base of the pcie_addr window */
-+      bcm_writel(lower_32_bits(pcie_addr) + MMIO_ENDIAN,
-+                 base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
-+      bcm_writel(upper_32_bits(pcie_addr),
-+                 base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
-+
-+      cpu_addr_mb = cpu_addr >> 20;
-+      limit_addr_mb = (cpu_addr + size - 1) >> 20;
-+
-+      /* Write the addr base low register */
-+      WR_FLD_WITH_OFFSET(base, (win * 4),
-+                         PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
-+                         BASE, cpu_addr_mb);
-+      /* Write the addr limit low register */
-+      WR_FLD_WITH_OFFSET(base, (win * 4),
-+                         PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
-+                         LIMIT, limit_addr_mb);
-+
-+      if (pcie->type != BCM7435 && pcie->type != BCM7425) {
-+              /* Write the cpu addr high register */
-+              tmp = (u32)(cpu_addr_mb >>
-+                      PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
-+              WR_FLD_WITH_OFFSET(base, (win * 8),
-+                                 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI,
-+                                 BASE, tmp);
-+              /* Write the cpu limit high register */
-+              tmp = (u32)(limit_addr_mb >>
-+                      PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
-+              WR_FLD_WITH_OFFSET(base, (win * 8),
-+                                 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI,
-+                                 LIMIT, tmp);
-+      }
-+}
-+
-+/* Configuration space read/write support */
-+static int cfg_index(int busnr, int devfn, int reg)
-+{
-+      return ((PCI_SLOT(devfn) & 0x1f) << PCIE_SLOT_SHIFT)
-+              | ((PCI_FUNC(devfn) & 0x07) << PCIE_FUNC_SHIFT)
-+              | (busnr << PCIE_BUSNUM_SHIFT)
-+              | (reg & ~3);
-+}
-+
-+/* The controller is capable of serving in both RC and EP roles */
-+static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
-+{
-+      void __iomem *base = pcie->base;
-+      u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
-+
-+      return !!EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PORT);
-+}
-+
-+static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
-+{
-+      void __iomem *base = pcie->base;
-+      u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
-+      u32 dla = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_DL_ACTIVE);
-+      u32 plu = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PHYLINKUP);
-+
-+      return  (dla && plu) ? true : false;
-+}
-+
-+static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
-+                                      int where)
-+{
-+      struct brcm_pcie *pcie = bus->sysdata;
-+      void __iomem *base = pcie->base;
-+      int idx;
-+
-+      /* Accesses to the RC go right to the RC registers if slot==0 */
-+      if (pci_is_root_bus(bus))
-+              return PCI_SLOT(devfn) ? NULL : base + where;
-+
-+      /* For devices, write to the config space index register */
-+      idx = cfg_index(bus->number, devfn, where);
-+      bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
-+      return base + DATA_ADDR(pcie) + (where & 0x3);
-+}
-+
-+static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
-+                                              unsigned int val)
-+{
-+      unsigned int shift = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_SHIFT];
-+      u32 mask =  pcie->reg_field_info[RGR1_SW_INIT_1_INIT_MASK];
-+
-+      wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie), mask, shift, val);
-+}
-+
-+static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
-+                                     unsigned int val)
-+{
-+      if (pcie->type != BCM7278)
-+              wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie),
-+                        PCIE_RGR1_SW_INIT_1_PERST_MASK,
-+                        PCIE_RGR1_SW_INIT_1_PERST_SHIFT, val);
-+      else
-+              /* Assert = 0, de-assert = 1 on 7278 */
-+              WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
-+}
-+
-+static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
-+{
-+      int i, ret = 0;
-+
-+      mutex_lock(&brcm_pcie_lock);
-+      if (num_pcie > 0) {
-+              num_pcie++;
-+              goto done;
-+      }
-+
-+      /* Determine num_memc and their sizes */
-+      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-+              u64 size = brcmstb_memory_memc_size(i);
-+
-+              if (size == (u64)-1) {
-+                      dev_err(pcie->dev, "cannot get memc%d size\n", i);
-+                      ret = -EINVAL;
-+                      goto done;
-+              } else if (size) {
-+                      scb_size[i] = roundup_pow_of_two_64(size);
-+                      num_memc++;
-+              } else {
-+                      break;
-+              }
-+      }
-+      if (!ret && num_memc == 0) {
-+              ret = -EINVAL;
-+              goto done;
-+      }
-+
-+      num_pcie++;
-+done:
-+      mutex_unlock(&brcm_pcie_lock);
-+      return ret;
-+}
-+
-+static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
-+{
-+      mutex_lock(&brcm_pcie_lock);
-+      if (--num_pcie == 0)
-+              num_memc = 0;
-+      mutex_unlock(&brcm_pcie_lock);
-+}
-+
-+static int brcm_pcie_parse_request_of_pci_ranges(struct brcm_pcie *pcie)
-+{
-+      struct resource_entry *win;
-+      int ret;
-+
-+      ret = devm_of_pci_get_host_bridge_resources(pcie->dev, 0, 0xff,
-+                                                  &pcie->resources, NULL);
-+      if (ret) {
-+              dev_err(pcie->dev, "failed to get host resources\n");
-+              return ret;
-+      }
-+
-+      resource_list_for_each_entry(win, &pcie->resources) {
-+              struct resource *parent, *res = win->res;
-+              dma_addr_t offset = (dma_addr_t)win->offset;
-+
-+              if (resource_type(res) == IORESOURCE_IO) {
-+                      parent = &ioport_resource;
-+              } else if (resource_type(res) == IORESOURCE_MEM) {
-+                      if (pcie->num_out_wins >= BRCM_NUM_PCIE_OUT_WINS) {
-+                              dev_err(pcie->dev, "too many outbound wins\n");
-+                              return -EINVAL;
-+                      }
-+                      pcie->out_wins[pcie->num_out_wins].cpu_addr
-+                              = (phys_addr_t)res->start;
-+                      pcie->out_wins[pcie->num_out_wins].pcie_addr
-+                              = (dma_addr_t)(res->start
-+                                             - (phys_addr_t)offset);
-+                      pcie->out_wins[pcie->num_out_wins].size
-+                              = (dma_addr_t)(res->end - res->start + 1);
-+                      pcie->num_out_wins++;
-+                      parent = &iomem_resource;
-+              } else {
-+                      continue;
-+              }
-+
-+              ret = devm_request_resource(pcie->dev, parent, res);
-+              if (ret) {
-+                      dev_err(pcie->dev, "failed to get res %pR\n", res);
-+                      return ret;
-+              }
-+      }
-+      return 0;
-+}
-+
-+static int brcm_pcie_setup(struct brcm_pcie *pcie)
-+{
-+      void __iomem *base = pcie->base;
-+      unsigned int scb_size_val;
-+      u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
-+      u32 tmp, burst;
-+      int i, j, ret, limit;
-+      u16 nlw, cls, lnksta;
-+      bool ssc_good = false;
-+      struct device *dev = pcie->dev;
-+
-+      /* Reset the bridge */
-+      brcm_pcie_bridge_sw_init_set(pcie, 1);
-+
-+      /*
-+       * Ensure that the fundamental reset is asserted, except for 7278,
-+       * which fails if we do this.
-+       */
-+      if (pcie->type != BCM7278)
-+              brcm_pcie_perst_set(pcie, 1);
-+
-+      usleep_range(100, 200);
-+
-+      /* Take the bridge out of reset */
-+      brcm_pcie_bridge_sw_init_set(pcie, 0);
-+
-+      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
-+      /* Wait for SerDes to be stable */
-+      usleep_range(100, 200);
-+
-+      /* Grab the PCIe hw revision number */
-+      tmp = bcm_readl(base + PCIE_MISC_REVISION);
-+      pcie->rev = EXTRACT_FIELD(tmp, PCIE_MISC_REVISION, MAJMIN);
-+
-+      /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
-+      tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
-+      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
-+      burst = (pcie->type == GENERIC || pcie->type == BCM7278)
-+              ? BURST_SIZE_512 : BURST_SIZE_256;
-+      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
-+      bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
-+
-+      /*
-+       * Set up inbound memory view for the EP (called RC_BAR2,
-+       * not to be confused with the BARs that are advertised by
-+       * the EP).
-+       */
-+      for (i = 0; i < num_memc; i++)
-+              total_mem_size += scb_size[i];
-+
-+      /*
-+       * The PCIe host controller by design must set the inbound
-+       * viewport to be a contiguous arrangement of all of the
-+       * system's memory.  In addition, its size mut be a power of
-+       * two.  To further complicate matters, the viewport must
-+       * start on a pcie-address that is aligned on a multiple of its
-+       * size.  If a portion of the viewport does not represent
-+       * system memory -- e.g. 3GB of memory requires a 4GB viewport
-+       * -- we can map the outbound memory in or after 3GB and even
-+       * though the viewport will overlap the outbound memory the
-+       * controller will know to send outbound memory downstream and
-+       * everything else upstream.
-+       */
-+      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
-+
-+      /*
-+       * Set simple configuration based on memory sizes
-+       * only.  We always start the viewport at address 0.
-+       */
-+      rc_bar2_offset = 0;
-+
-+      tmp = lower_32_bits(rc_bar2_offset);
-+      tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
-+                         encode_ibar_size(rc_bar2_size));
-+      bcm_writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
-+      bcm_writel(upper_32_bits(rc_bar2_offset),
-+                 base + PCIE_MISC_RC_BAR2_CONFIG_HI);
-+
-+      scb_size_val = scb_size[0]
-+              ? ilog2(scb_size[0]) - 15 : 0xf; /* 0xf is 1GB */
-+      WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_size_val);
-+
-+      if (num_memc > 1) {
-+              scb_size_val = scb_size[1]
-+                      ? ilog2(scb_size[1]) - 15 : 0xf; /* 0xf is 1GB */
-+              WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB1_SIZE, scb_size_val);
-+      }
-+
-+      if (num_memc > 2) {
-+              scb_size_val = scb_size[2]
-+                      ? ilog2(scb_size[2]) - 15 : 0xf; /* 0xf is 1GB */
-+              WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB2_SIZE, scb_size_val);
-+      }
-+
-+      /* disable the PCIe->GISB memory window (RC_BAR1) */
-+      WR_FLD(base, PCIE_MISC_RC_BAR1_CONFIG_LO, SIZE, 0);
-+
-+      /* disable the PCIe->SCB memory window (RC_BAR3) */
-+      WR_FLD(base, PCIE_MISC_RC_BAR3_CONFIG_LO, SIZE, 0);
-+
-+      if (!pcie->suspended) {
-+              /* clear any interrupts we find on boot */
-+              bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
-+              (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + CLR);
-+      }
-+
-+      /* Mask all interrupts since we are not handling any yet */
-+      bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
-+      (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
-+
-+      if (pcie->gen)
-+              set_gen(base, pcie->gen);
-+
-+      /* Unassert the fundamental reset */
-+      brcm_pcie_perst_set(pcie, 0);
-+
-+      /*
-+       * Give the RC/EP time to wake up, before trying to configure RC.
-+       * Intermittently check status for link-up, up to a total of 100ms
-+       * when we don't know if the device is there, and up to 1000ms if
-+       * we do know the device is there.
-+       */
-+      limit = pcie->suspended ? 1000 : 100;
-+      for (i = 1, j = 0; j < limit && !brcm_pcie_link_up(pcie);
-+           j += i, i = i * 2)
-+              msleep(i + j > limit ? limit - j : i);
-+
-+      if (!brcm_pcie_link_up(pcie)) {
-+              dev_info(dev, "link down\n");
-+              return -ENODEV;
-+      }
-+
-+      if (!brcm_pcie_rc_mode(pcie)) {
-+              dev_err(dev, "PCIe misconfigured; is in EP mode\n");
-+              return -EINVAL;
-+      }
-+
-+      for (i = 0; i < pcie->num_out_wins; i++)
-+              brcm_pcie_set_outbound_win(pcie, i, pcie->out_wins[i].cpu_addr,
-+                                         pcie->out_wins[i].pcie_addr,
-+                                         pcie->out_wins[i].size);
-+
-+      /*
-+       * For config space accesses on the RC, show the right class for
-+       * a PCIe-PCIe bridge (the default setting is to be EP mode).
-+       */
-+      WR_FLD_RB(base, PCIE_RC_CFG_PRIV1_ID_VAL3, CLASS_CODE, 0x060400);
-+
-+      if (pcie->ssc) {
-+              ret = set_ssc(base);
-+              if (ret == 0)
-+                      ssc_good = true;
-+              else
-+                      dev_err(dev, "failed attempt to enter ssc mode\n");
-+      }
-+
-+      lnksta = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA);
-+      cls = lnksta & PCI_EXP_LNKSTA_CLS;
-+      nlw = (lnksta & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
-+      dev_info(dev, "link up, %s Gbps x%u %s\n", link_speed_to_str(cls),
-+               nlw, ssc_good ? "(SSC)" : "(!SSC)");
-+
-+      /* PCIe->SCB endian mode for BAR */
-+      /* field ENDIAN_MODE_BAR2 = DATA_ENDIAN */
-+      WR_FLD_RB(base, PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1,
-+                ENDIAN_MODE_BAR2, DATA_ENDIAN);
-+
-+      /*
-+       * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
-+       * is enabled =>  setting the CLKREQ_DEBUG_ENABLE field to 1.
-+       */
-+      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, CLKREQ_DEBUG_ENABLE, 1);
-+
-+      return 0;
-+}
-+
-+/* L23 is a low-power PCIe link state */
-+static void enter_l23(struct brcm_pcie *pcie)
-+{
-+      void __iomem *base = pcie->base;
-+      int tries, l23;
-+
-+      /* assert request for L23 */
-+      WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 1);
-+      /* poll L23 status */
-+      for (tries = 0, l23 = 0; tries < 1000 && !l23; tries++)
-+              l23 = RD_FLD(base, PCIE_MISC_PCIE_STATUS, PCIE_LINK_IN_L23);
-+      if (!l23)
-+              dev_err(pcie->dev, "failed to enter L23\n");
-+}
-+
-+static void turn_off(struct brcm_pcie *pcie)
-+{
-+      void __iomem *base = pcie->base;
-+
-+      if (brcm_pcie_link_up(pcie))
-+              enter_l23(pcie);
-+      /* Assert fundamental reset */
-+      brcm_pcie_perst_set(pcie, 1);
-+      /* Deassert request for L23 in case it was asserted */
-+      WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 0);
-+      /* Turn off SerDes */
-+      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 1);
-+      /* Shutdown PCIe bridge */
-+      brcm_pcie_bridge_sw_init_set(pcie, 1);
-+}
-+
-+static int brcm_pcie_suspend(struct device *dev)
-+{
-+      struct brcm_pcie *pcie = dev_get_drvdata(dev);
-+
-+      turn_off(pcie);
-+      clk_disable_unprepare(pcie->clk);
-+      pcie->suspended = true;
-+
-+      return 0;
-+}
-+
-+static int brcm_pcie_resume(struct device *dev)
-+{
-+      struct brcm_pcie *pcie = dev_get_drvdata(dev);
-+      void __iomem *base;
-+      int ret;
-+
-+      base = pcie->base;
-+      clk_prepare_enable(pcie->clk);
-+
-+      /* Take bridge out of reset so we can access the SerDes reg */
-+      brcm_pcie_bridge_sw_init_set(pcie, 0);
-+
-+      /* Turn on SerDes */
-+      WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
-+      /* Wait for SerDes to be stable */
-+      usleep_range(100, 200);
-+
-+      ret = brcm_pcie_setup(pcie);
-+      if (ret)
-+              return ret;
-+
-+      pcie->suspended = false;
-+
-+      return 0;
-+}
-+
-+static void _brcm_pcie_remove(struct brcm_pcie *pcie)
-+{
-+      turn_off(pcie);
-+      clk_disable_unprepare(pcie->clk);
-+      clk_put(pcie->clk);
-+      brcm_pcie_remove_controller(pcie);
-+}
-+
-+static int brcm_pcie_remove(struct platform_device *pdev)
-+{
-+      struct brcm_pcie *pcie = platform_get_drvdata(pdev);
-+
-+      pci_stop_root_bus(pcie->root_bus);
-+      pci_remove_root_bus(pcie->root_bus);
-+      _brcm_pcie_remove(pcie);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id brcm_pcie_match[] = {
-+      { .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
-+      { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
-+      { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
-+      { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, brcm_pcie_match);
-+
-+static int brcm_pcie_probe(struct platform_device *pdev)
-+{
-+      struct device_node *dn = pdev->dev.of_node;
-+      const struct of_device_id *of_id;
-+      const struct pcie_cfg_data *data;
-+      int ret;
-+      struct brcm_pcie *pcie;
-+      struct resource *res;
-+      void __iomem *base;
-+      u32 tmp;
-+      struct pci_host_bridge *bridge;
-+      struct pci_bus *child;
-+
-+      bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
-+      if (!bridge)
-+              return -ENOMEM;
-+
-+      pcie = pci_host_bridge_priv(bridge);
-+      INIT_LIST_HEAD(&pcie->resources);
-+
-+      of_id = of_match_node(brcm_pcie_match, dn);
-+      if (!of_id) {
-+              dev_err(&pdev->dev, "failed to look up compatible string\n");
-+              return -EINVAL;
-+      }
-+
-+      if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
-+              dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
-+              return -EINVAL;
-+      }
-+
-+      data = of_id->data;
-+      pcie->reg_offsets = data->offsets;
-+      pcie->reg_field_info = data->reg_field_info;
-+      pcie->type = data->type;
-+      pcie->dn = dn;
-+      pcie->dev = &pdev->dev;
-+
-+      /* We use the domain number as our controller number */
-+      pcie->id = of_get_pci_domain_nr(dn);
-+      if (pcie->id < 0)
-+              return pcie->id;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (!res)
-+              return -EINVAL;
-+
-+      base = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(base))
-+              return PTR_ERR(base);
-+
-+      pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
-+      if (IS_ERR(pcie->clk)) {
-+              dev_err(&pdev->dev, "could not get clock\n");
-+              pcie->clk = NULL;
-+      }
-+      pcie->base = base;
-+
-+      ret = of_pci_get_max_link_speed(dn);
-+      pcie->gen = (ret < 0) ? 0 : ret;
-+
-+      pcie->ssc = of_property_read_bool(dn, "brcm,enable-ssc");
-+
-+      ret = irq_of_parse_and_map(pdev->dev.of_node, 0);
-+      if (ret == 0)
-+              /* keep going, as we don't use this intr yet */
-+              dev_warn(pcie->dev, "cannot get PCIe interrupt\n");
-+      else
-+              pcie->irq = ret;
-+
-+      ret = brcm_pcie_parse_request_of_pci_ranges(pcie);
-+      if (ret)
-+              return ret;
-+
-+      ret = clk_prepare_enable(pcie->clk);
-+      if (ret) {
-+              dev_err(&pdev->dev, "could not enable clock\n");
-+              return ret;
-+      }
-+
-+      ret = brcm_pcie_add_controller(pcie);
-+      if (ret)
-+              return ret;
-+
-+      ret = brcm_pcie_setup(pcie);
-+      if (ret)
-+              goto fail;
-+
-+      list_splice_init(&pcie->resources, &bridge->windows);
-+      bridge->dev.parent = &pdev->dev;
-+      bridge->busnr = 0;
-+      bridge->ops = &brcm_pcie_ops;
-+      bridge->sysdata = pcie;
-+      bridge->map_irq = of_irq_parse_and_map_pci;
-+      bridge->swizzle_irq = pci_common_swizzle;
-+
-+      ret = pci_scan_root_bus_bridge(bridge);
-+      if (ret < 0) {
-+              dev_err(pcie->dev, "Scanning root bridge failed\n");
-+              goto fail;
-+      }
-+
-+      pci_assign_unassigned_bus_resources(bridge->bus);
-+      list_for_each_entry(child, &bridge->bus->children, node)
-+              pcie_bus_configure_settings(child);
-+      pci_bus_add_devices(bridge->bus);
-+      platform_set_drvdata(pdev, pcie);
-+      pcie->root_bus = bridge->bus;
-+
-+      return 0;
-+
-+fail:
-+      _brcm_pcie_remove(pcie);
-+      return ret;
-+}
-+
-+static const struct dev_pm_ops brcm_pcie_pm_ops = {
-+      .suspend_noirq = brcm_pcie_suspend,
-+      .resume_noirq = brcm_pcie_resume,
-+};
-+
-+static struct platform_driver brcm_pcie_driver = {
-+      .probe = brcm_pcie_probe,
-+      .remove = brcm_pcie_remove,
-+      .driver = {
-+              .name = "brcm-pcie",
-+              .owner = THIS_MODULE,
-+              .of_match_table = brcm_pcie_match,
-+              .pm = &brcm_pcie_pm_ops,
-+      },
-+};
-+
-+module_platform_driver(brcm_pcie_driver);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_DESCRIPTION("Broadcom STB PCIe RC driver");
-+MODULE_AUTHOR("Broadcom");
---- /dev/null
-+++ b/include/soc/brcmstb/memory_api.h
-@@ -0,0 +1,25 @@
-+#ifndef __MEMORY_API_H
-+#define __MEMORY_API_H
-+
-+/*
-+ * Bus Interface Unit control register setup, must happen early during boot,
-+ * before SMP is brought up, called by machine entry point.
-+ */
-+void brcmstb_biuctrl_init(void);
-+
-+#ifdef CONFIG_SOC_BRCMSTB
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa);
-+u64 brcmstb_memory_memc_size(int memc);
-+#else
-+static inline int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+      return -EINVAL;
-+}
-+
-+static inline u64 brcmstb_memory_memc_size(int memc)
-+{
-+      return -1;
-+}
-+#endif
-+
-+#endif /* __MEMORY_API_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0458-PCI-brcmstb-Add-MSI-capability.patch b/target/linux/brcm2708/patches-4.19/950-0458-PCI-brcmstb-Add-MSI-capability.patch
new file mode 100644 (file)
index 0000000..856bf2b
--- /dev/null
@@ -0,0 +1,543 @@
+From cd3af4fa73ab25353f0865ebe8e0d2af1fd2a50b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH] PCI: brcmstb: Add MSI capability
+
+This commit adds MSI to the Broadcom STB PCIe host controller. It does
+not add MSIX since that functionality is not in the HW.  The MSI
+controller is physically located within the PCIe block, however, there
+is no reason why the MSI controller could not be moved elsewhere in
+the future.
+
+Since the internal Brcmstb MSI controller is intertwined with the PCIe
+controller, it is not its own platform device but rather part of the
+PCIe platform device.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 374 ++++++++++++++++++++++++--
+ 1 file changed, 353 insertions(+), 21 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright (C) 2009 - 2017 Broadcom */
++#include <linux/bitops.h>
+ #include <linux/clk.h>
+ #include <linux/compiler.h>
+ #include <linux/delay.h>
+@@ -9,11 +10,13 @@
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+ #include <linux/ioport.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <linux/irqdomain.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+ #include <linux/log2.h>
+ #include <linux/module.h>
++#include <linux/msi.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/of_pci.h>
+@@ -47,6 +50,9 @@
+ #define PCIE_MISC_RC_BAR2_CONFIG_LO                   0x4034
+ #define PCIE_MISC_RC_BAR2_CONFIG_HI                   0x4038
+ #define PCIE_MISC_RC_BAR3_CONFIG_LO                   0x403c
++#define PCIE_MISC_MSI_BAR_CONFIG_LO                   0x4044
++#define PCIE_MISC_MSI_BAR_CONFIG_HI                   0x4048
++#define PCIE_MISC_MSI_DATA_CONFIG                     0x404c
+ #define PCIE_MISC_PCIE_CTRL                           0x4064
+ #define PCIE_MISC_PCIE_STATUS                         0x4068
+ #define PCIE_MISC_REVISION                            0x406c
+@@ -55,6 +61,7 @@
+ #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI                0x4084
+ #define PCIE_MISC_HARD_PCIE_HARD_DEBUG                        0x4204
+ #define PCIE_INTR2_CPU_BASE                           0x4300
++#define PCIE_MSI_INTR2_BASE                           0x4500
+ /*
+  * Broadcom Settop Box PCIe Register Field shift and mask info. The
+@@ -115,6 +122,8 @@
+ #define BRCM_NUM_PCIE_OUT_WINS                0x4
+ #define BRCM_MAX_SCB                  0x4
++#define BRCM_INT_PCI_MSI_NR           32
++#define BRCM_PCIE_HW_REV_33           0x0303
+ #define BRCM_MSI_TARGET_ADDR_LT_4GB   0x0fffffffcULL
+ #define BRCM_MSI_TARGET_ADDR_GT_4GB   0xffffffffcULL
+@@ -203,6 +212,33 @@ struct brcm_window {
+       dma_addr_t size;
+ };
++struct brcm_msi {
++      struct device           *dev;
++      void __iomem            *base;
++      struct device_node      *dn;
++      struct irq_domain       *msi_domain;
++      struct irq_domain       *inner_domain;
++      struct mutex            lock; /* guards the alloc/free operations */
++      u64                     target_addr;
++      int                     irq;
++
++      /* intr_base is the base pointer for interrupt status/set/clr regs */
++      void __iomem            *intr_base;
++
++      /* intr_legacy_mask indicates how many bits are MSI interrupts */
++      u32                     intr_legacy_mask;
++
++      /*
++       * intr_legacy_offset indicates bit position of MSI_01. It is
++       * to map the register bit position to a hwirq that starts at 0.
++       */
++      u32                     intr_legacy_offset;
++
++      /* used indicates which MSI interrupts have been alloc'd */
++      unsigned long           used;
++      unsigned int            rev;
++};
++
+ /* Internal PCIe Host Controller Information.*/
+ struct brcm_pcie {
+       struct device           *dev;
+@@ -217,7 +253,10 @@ struct brcm_pcie {
+       int                     num_out_wins;
+       bool                    ssc;
+       int                     gen;
++      u64                     msi_target_addr;
+       struct brcm_window      out_wins[BRCM_NUM_PCIE_OUT_WINS];
++      struct brcm_msi         *msi;
++      bool                    msi_internal;
+       unsigned int            rev;
+       const int               *reg_offsets;
+       const int               *reg_field_info;
+@@ -225,9 +264,9 @@ struct brcm_pcie {
+ };
+ struct pcie_cfg_data {
+-      const int *reg_field_info;
+-      const int *offsets;
+-      const enum pcie_type type;
++      const int               *reg_field_info;
++      const int               *offsets;
++      const enum pcie_type    type;
+ };
+ static const int pcie_reg_field_info[] = {
+@@ -828,6 +867,267 @@ static void brcm_pcie_set_outbound_win(s
+       }
+ }
++static struct irq_chip brcm_msi_irq_chip = {
++      .name = "Brcm_MSI",
++      .irq_mask = pci_msi_mask_irq,
++      .irq_unmask = pci_msi_unmask_irq,
++};
++
++static struct msi_domain_info brcm_msi_domain_info = {
++      .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
++                 MSI_FLAG_PCI_MSIX),
++      .chip   = &brcm_msi_irq_chip,
++};
++
++static void brcm_pcie_msi_isr(struct irq_desc *desc)
++{
++      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct brcm_msi *msi;
++      unsigned long status, virq;
++      u32 mask, bit, hwirq;
++      struct device *dev;
++
++      chained_irq_enter(chip, desc);
++      msi = irq_desc_get_handler_data(desc);
++      mask = msi->intr_legacy_mask;
++      dev = msi->dev;
++
++      while ((status = bcm_readl(msi->intr_base + STATUS) & mask)) {
++              for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
++                      /* clear the interrupt */
++                      bcm_writel(1 << bit, msi->intr_base + CLR);
++
++                      /* Account for legacy interrupt offset */
++                      hwirq = bit - msi->intr_legacy_offset;
++
++                      virq = irq_find_mapping(msi->inner_domain, hwirq);
++                      if (virq) {
++                              if (msi->used & (1 << hwirq))
++                                      generic_handle_irq(virq);
++                              else
++                                      dev_info(dev, "unhandled MSI %d\n",
++                                               hwirq);
++                      } else {
++                              /* Unknown MSI, just clear it */
++                              dev_dbg(dev, "unexpected MSI\n");
++                      }
++              }
++      }
++      chained_irq_exit(chip, desc);
++}
++
++static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
++{
++      struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
++      u32 temp;
++
++      msg->address_lo = lower_32_bits(msi->target_addr);
++      msg->address_hi = upper_32_bits(msi->target_addr);
++      temp = bcm_readl(msi->base + PCIE_MISC_MSI_DATA_CONFIG);
++      msg->data = ((temp >> 16) & (temp & 0xffff)) | data->hwirq;
++}
++
++static int brcm_msi_set_affinity(struct irq_data *irq_data,
++                               const struct cpumask *mask, bool force)
++{
++      return -EINVAL;
++}
++
++static struct irq_chip brcm_msi_bottom_irq_chip = {
++      .name                   = "Brcm_MSI",
++      .irq_compose_msi_msg    = brcm_compose_msi_msg,
++      .irq_set_affinity       = brcm_msi_set_affinity,
++};
++
++static int brcm_msi_alloc(struct brcm_msi *msi)
++{
++      int bit, hwirq;
++
++      mutex_lock(&msi->lock);
++      bit = ~msi->used ? ffz(msi->used) : -1;
++
++      if (bit >= 0 && bit < BRCM_INT_PCI_MSI_NR) {
++              msi->used |= (1 << bit);
++              hwirq = bit - msi->intr_legacy_offset;
++      } else {
++              hwirq = -ENOSPC;
++      }
++
++      mutex_unlock(&msi->lock);
++      return hwirq;
++}
++
++static void brcm_msi_free(struct brcm_msi *msi, unsigned long hwirq)
++{
++      mutex_lock(&msi->lock);
++      msi->used &= ~(1 << (hwirq + msi->intr_legacy_offset));
++      mutex_unlock(&msi->lock);
++}
++
++static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
++                               unsigned int nr_irqs, void *args)
++{
++      struct brcm_msi *msi = domain->host_data;
++      int hwirq;
++
++      hwirq = brcm_msi_alloc(msi);
++
++      if (hwirq < 0)
++              return hwirq;
++
++      irq_domain_set_info(domain, virq, (irq_hw_number_t)hwirq,
++                          &brcm_msi_bottom_irq_chip, domain->host_data,
++                          handle_simple_irq, NULL, NULL);
++      return 0;
++}
++
++static void brcm_irq_domain_free(struct irq_domain *domain,
++                               unsigned int virq, unsigned int nr_irqs)
++{
++      struct irq_data *d = irq_domain_get_irq_data(domain, virq);
++      struct brcm_msi *msi = irq_data_get_irq_chip_data(d);
++
++      brcm_msi_free(msi, d->hwirq);
++}
++
++static void brcm_msi_set_regs(struct brcm_msi *msi)
++{
++      u32 data_val, msi_lo, msi_hi;
++
++      if (msi->rev >= BRCM_PCIE_HW_REV_33) {
++              /*
++               * ffe0 -- least sig 5 bits are 0 indicating 32 msgs
++               * 6540 -- this is our arbitrary unique data value
++               */
++              data_val = 0xffe06540;
++      } else {
++              /*
++               * fff8 -- least sig 3 bits are 0 indicating 8 msgs
++               * 6540 -- this is our arbitrary unique data value
++               */
++              data_val = 0xfff86540;
++      }
++
++      /*
++       * Make sure we are not masking MSIs.  Note that MSIs can be masked,
++       * but that occurs on the PCIe EP device
++       */
++      bcm_writel(0xffffffff & msi->intr_legacy_mask,
++                 msi->intr_base + MASK_CLR);
++
++      msi_lo = lower_32_bits(msi->target_addr);
++      msi_hi = upper_32_bits(msi->target_addr);
++      /*
++       * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
++       * enable, which we set to 1.
++       */
++      bcm_writel(msi_lo | 1, msi->base + PCIE_MISC_MSI_BAR_CONFIG_LO);
++      bcm_writel(msi_hi, msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
++      bcm_writel(data_val, msi->base + PCIE_MISC_MSI_DATA_CONFIG);
++}
++
++static const struct irq_domain_ops msi_domain_ops = {
++      .alloc  = brcm_irq_domain_alloc,
++      .free   = brcm_irq_domain_free,
++};
++
++static int brcm_allocate_domains(struct brcm_msi *msi)
++{
++      struct fwnode_handle *fwnode = of_node_to_fwnode(msi->dn);
++      struct device *dev = msi->dev;
++
++      msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
++                                                &msi_domain_ops, msi);
++      if (!msi->inner_domain) {
++              dev_err(dev, "failed to create IRQ domain\n");
++              return -ENOMEM;
++      }
++
++      msi->msi_domain = pci_msi_create_irq_domain(fwnode,
++                                                  &brcm_msi_domain_info,
++                                                  msi->inner_domain);
++      if (!msi->msi_domain) {
++              dev_err(dev, "failed to create MSI domain\n");
++              irq_domain_remove(msi->inner_domain);
++              return -ENOMEM;
++      }
++
++      return 0;
++}
++
++static void brcm_free_domains(struct brcm_msi *msi)
++{
++      irq_domain_remove(msi->msi_domain);
++      irq_domain_remove(msi->inner_domain);
++}
++
++static void brcm_msi_remove(struct brcm_pcie *pcie)
++{
++      struct brcm_msi *msi = pcie->msi;
++
++      if (!msi)
++              return;
++      irq_set_chained_handler(msi->irq, NULL);
++      irq_set_handler_data(msi->irq, NULL);
++      brcm_free_domains(msi);
++}
++
++static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
++{
++      struct brcm_msi *msi;
++      int irq, ret;
++      struct device *dev = pcie->dev;
++
++      irq = irq_of_parse_and_map(dev->of_node, 1);
++      if (irq <= 0) {
++              dev_err(dev, "cannot map msi intr\n");
++              return -ENODEV;
++      }
++
++      msi = devm_kzalloc(dev, sizeof(struct brcm_msi), GFP_KERNEL);
++      if (!msi)
++              return -ENOMEM;
++
++      msi->dev = dev;
++      msi->base = pcie->base;
++      msi->rev =  pcie->rev;
++      msi->dn = pcie->dn;
++      msi->target_addr = pcie->msi_target_addr;
++      msi->irq = irq;
++
++      ret = brcm_allocate_domains(msi);
++      if (ret)
++              return ret;
++
++      irq_set_chained_handler_and_data(msi->irq, brcm_pcie_msi_isr, msi);
++
++      if (msi->rev >= BRCM_PCIE_HW_REV_33) {
++              msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE;
++              /*
++               * This version of PCIe hw has only 32 intr bits
++               * starting at bit position 0.
++               */
++              msi->intr_legacy_mask = 0xffffffff;
++              msi->intr_legacy_offset = 0x0;
++              msi->used = 0x0;
++
++      } else {
++              msi->intr_base = msi->base + PCIE_INTR2_CPU_BASE;
++              /*
++               * This version of PCIe hw has only 8 intr bits starting
++               * at bit position 24.
++               */
++              msi->intr_legacy_mask = 0xff000000;
++              msi->intr_legacy_offset = 24;
++              msi->used = 0x00ffffff;
++      }
++
++      brcm_msi_set_regs(msi);
++      pcie->msi = msi;
++
++      return 0;
++}
++
+ /* Configuration space read/write support */
+ static int cfg_index(int busnr, int devfn, int reg)
+ {
+@@ -1072,6 +1372,7 @@ static int brcm_pcie_setup(struct brcm_p
+       u16 nlw, cls, lnksta;
+       bool ssc_good = false;
+       struct device *dev = pcie->dev;
++      u64 msi_target_addr;
+       /* Reset the bridge */
+       brcm_pcie_bridge_sw_init_set(pcie, 1);
+@@ -1116,27 +1417,24 @@ static int brcm_pcie_setup(struct brcm_p
+        * The PCIe host controller by design must set the inbound
+        * viewport to be a contiguous arrangement of all of the
+        * system's memory.  In addition, its size mut be a power of
+-       * two.  To further complicate matters, the viewport must
+-       * start on a pcie-address that is aligned on a multiple of its
+-       * size.  If a portion of the viewport does not represent
+-       * system memory -- e.g. 3GB of memory requires a 4GB viewport
+-       * -- we can map the outbound memory in or after 3GB and even
+-       * though the viewport will overlap the outbound memory the
+-       * controller will know to send outbound memory downstream and
+-       * everything else upstream.
++       * two.  Further, the MSI target address must NOT be placed
++       * inside this region, as the decoding logic will consider its
++       * address to be inbound memory traffic.  To further
++       * complicate matters, the viewport must start on a
++       * pcie-address that is aligned on a multiple of its size.
++       * If a portion of the viewport does not represent system
++       * memory -- e.g. 3GB of memory requires a 4GB viewport --
++       * we can map the outbound memory in or after 3GB and even
++       * though the viewport will overlap the outbound memory
++       * the controller will know to send outbound memory downstream
++       * and everything else upstream.
+        */
+       rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
+-      /*
+-       * Set simple configuration based on memory sizes
+-       * only.  We always start the viewport at address 0.
+-       */
+-      rc_bar2_offset = 0;
+-
+       if (dma_ranges) {
+               /*
+                * The best-case scenario is to place the inbound
+-               * region in the first 4GB of pci-space, as some
++               * region in the first 4GB of pcie-space, as some
+                * legacy devices can only address 32bits.
+                * We would also like to put the MSI under 4GB
+                * as well, since some devices require a 32bit
+@@ -1145,6 +1443,14 @@ static int brcm_pcie_setup(struct brcm_p
+               if (total_mem_size <= 0xc0000000ULL &&
+                   rc_bar2_size <= 0x100000000ULL) {
+                       rc_bar2_offset = 0;
++                      /* If the viewport is less then 4GB we can fit
++                       * the MSI target address under 4GB. Otherwise
++                       * put it right below 64GB.
++                       */
++                      msi_target_addr =
++                              (rc_bar2_size == 0x100000000ULL)
++                              ? BRCM_MSI_TARGET_ADDR_GT_4GB
++                              : BRCM_MSI_TARGET_ADDR_LT_4GB;
+               } else {
+                       /*
+                        * The system memory is 4GB or larger so we
+@@ -1154,8 +1460,12 @@ static int brcm_pcie_setup(struct brcm_p
+                        * start it at the 1x multiple of its size
+                        */
+                       rc_bar2_offset = rc_bar2_size;
+-              }
++                      /* Since we are starting the viewport at 4GB or
++                       * higher, put the MSI target address below 4GB
++                       */
++                      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
++              }
+       } else {
+               /*
+                * Set simple configuration based on memory sizes
+@@ -1163,7 +1473,12 @@ static int brcm_pcie_setup(struct brcm_p
+                * and set the MSI target address accordingly.
+                */
+               rc_bar2_offset = 0;
++
++              msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
++                      ? BRCM_MSI_TARGET_ADDR_GT_4GB
++                      : BRCM_MSI_TARGET_ADDR_LT_4GB;
+       }
++      pcie->msi_target_addr = msi_target_addr;
+       tmp = lower_32_bits(rc_bar2_offset);
+       tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
+@@ -1333,6 +1648,9 @@ static int brcm_pcie_resume(struct devic
+       if (ret)
+               return ret;
++      if (pcie->msi && pcie->msi_internal)
++              brcm_msi_set_regs(pcie->msi);
++
+       pcie->suspended = false;
+       return 0;
+@@ -1340,6 +1658,7 @@ static int brcm_pcie_resume(struct devic
+ static void _brcm_pcie_remove(struct brcm_pcie *pcie)
+ {
++      brcm_msi_remove(pcie);
+       turn_off(pcie);
+       clk_disable_unprepare(pcie->clk);
+       clk_put(pcie->clk);
+@@ -1368,7 +1687,7 @@ MODULE_DEVICE_TABLE(of, brcm_pcie_match)
+ static int brcm_pcie_probe(struct platform_device *pdev)
+ {
+-      struct device_node *dn = pdev->dev.of_node;
++      struct device_node *dn = pdev->dev.of_node, *msi_dn;
+       const struct of_device_id *of_id;
+       const struct pcie_cfg_data *data;
+       int ret;
+@@ -1448,6 +1767,20 @@ static int brcm_pcie_probe(struct platfo
+       if (ret)
+               goto fail;
++      msi_dn = of_parse_phandle(pcie->dn, "msi-parent", 0);
++      /* Use the internal MSI if no msi-parent property */
++      if (!msi_dn)
++              msi_dn = pcie->dn;
++
++      if (pci_msi_enabled() && msi_dn == pcie->dn) {
++              ret = brcm_pcie_enable_msi(pcie);
++              if (ret)
++                      dev_err(pcie->dev,
++                              "probe of internal MSI failed: %d)", ret);
++              else
++                      pcie->msi_internal = true;
++      }
++
+       list_splice_init(&pcie->resources, &bridge->windows);
+       bridge->dev.parent = &pdev->dev;
+       bridge->busnr = 0;
+@@ -1470,7 +1803,6 @@ static int brcm_pcie_probe(struct platfo
+       pcie->root_bus = bridge->bus;
+       return 0;
+-
+ fail:
+       _brcm_pcie_remove(pcie);
+       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0459-PCI-brcmstb-Add-dma-range-mapping-for-inbound-traffi.patch b/target/linux/brcm2708/patches-4.19/950-0459-PCI-brcmstb-Add-dma-range-mapping-for-inbound-traffi.patch
deleted file mode 100644 (file)
index 75615e3..0000000
+++ /dev/null
@@ -1,569 +0,0 @@
-From d3cc1c713b9436a7dc72788caa1d8de63ac3a01b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH] PCI: brcmstb: Add dma-range mapping for inbound
- traffic
-
-The Broadcom STB PCIe host controller is intimately related to the
-memory subsystem.  This close relationship adds complexity to how cpu
-system memory is mapped to PCIe memory.  Ideally, this mapping is an
-identity mapping, or an identity mapping off by a constant.  Not so in
-this case.
-
-Consider the Broadcom reference board BCM97445LCC_4X8 which has 6 GB
-of system memory.  Here is how the PCIe controller maps the
-system memory to PCIe memory:
-
-  memc0-a@[        0....3fffffff] <=> pci@[        0....3fffffff]
-  memc0-b@[100000000...13fffffff] <=> pci@[ 40000000....7fffffff]
-  memc1-a@[ 40000000....7fffffff] <=> pci@[ 80000000....bfffffff]
-  memc1-b@[300000000...33fffffff] <=> pci@[ c0000000....ffffffff]
-  memc2-a@[ 80000000....bfffffff] <=> pci@[100000000...13fffffff]
-  memc2-b@[c00000000...c3fffffff] <=> pci@[140000000...17fffffff]
-
-Although there are some "gaps" that can be added between the
-individual mappings by software, the permutation of memory regions for
-the most part is fixed by HW.  The solution of having something close
-to an identity mapping is not possible.
-
-The idea behind this HW design is that the same PCIe module can
-act as an RC or EP, and if it acts as an EP it concatenates all
-of system memory into a BAR so anything can be accessed.  Unfortunately,
-when the PCIe block is in the role of an RC it also presents this
-"BAR" to downstream PCIe devices, rather than offering an identity map
-between its system memory and PCIe space.
-
-Suppose that an endpoint driver allocs some DMA memory.  Suppose this
-memory is located at 0x6000_0000, which is in the middle of memc1-a.
-The driver wants a dma_addr_t value that it can pass on to the EP to
-use.  Without doing any custom mapping, the EP will use this value for
-DMA: the driver will get a dma_addr_t equal to 0x6000_0000.  But this
-won't work; the device needs a dma_addr_t that reflects the PCIe space
-address, namely 0xa000_0000.
-
-So, essentially the solution to this problem must modify the
-dma_addr_t returned by the DMA routines routines.  There are two
-ways (I know of) of doing this:
-
-(a) overriding/redefining the dma_to_phys() and phys_to_dma() calls
-that are used by the dma_ops routines.  This is the approach of
-
-       arch/mips/cavium-octeon/dma-octeon.c
-
-In ARM and ARM64 these two routines are defiend in asm/dma-mapping.h
-as static inline functions.
-
-(b) Subscribe to a notifier that notifies when a device is added to a
-bus.  When this happens, set_dma_ops() can be called for the device.
-This method is mentioned in:
-
-    http://lxr.free-electrons.com/source/drivers/of/platform.c?v=3.16#L152
-
-where it says as a comment
-
-    "In case if platform code need to use own special DMA
-    configuration, it can use Platform bus notifier and
-    handle BUS_NOTIFY_ADD_DEVICE event to fix up DMA
-    configuration."
-
-Solution (b) is what this commit does.  It uses its own set of
-dma_ops which are wrappers around the arch_dma_ops.  The
-wrappers translate the dma addresses before/after invoking
-the arch_dma_ops, as appropriate.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- drivers/pci/controller/pcie-brcmstb.c | 420 +++++++++++++++++++++++++-
- 1 file changed, 411 insertions(+), 9 deletions(-)
-
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -4,6 +4,7 @@
- #include <linux/clk.h>
- #include <linux/compiler.h>
- #include <linux/delay.h>
-+#include <linux/dma-mapping.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
-@@ -319,11 +320,307 @@ static struct pci_ops brcm_pcie_ops = {
-       ((val & ~reg##_##field##_MASK) | \
-        (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
-+static const struct dma_map_ops *arch_dma_ops;
-+static const struct dma_map_ops *brcm_dma_ops_ptr;
-+static struct of_pci_range *dma_ranges;
-+static int num_dma_ranges;
-+
- static phys_addr_t scb_size[BRCM_MAX_SCB];
- static int num_memc;
- static int num_pcie;
- static DEFINE_MUTEX(brcm_pcie_lock);
-+static dma_addr_t brcm_to_pci(dma_addr_t addr)
-+{
-+      struct of_pci_range *p;
-+
-+      if (!num_dma_ranges)
-+              return addr;
-+
-+      for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
-+              if (addr >= p->cpu_addr && addr < (p->cpu_addr + p->size))
-+                      return addr - p->cpu_addr + p->pci_addr;
-+
-+      return addr;
-+}
-+
-+static dma_addr_t brcm_to_cpu(dma_addr_t addr)
-+{
-+      struct of_pci_range *p;
-+
-+      if (!num_dma_ranges)
-+              return addr;
-+
-+      for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
-+              if (addr >= p->pci_addr && addr < (p->pci_addr + p->size))
-+                      return addr - p->pci_addr + p->cpu_addr;
-+
-+      return addr;
-+}
-+
-+static void *brcm_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-+                      gfp_t gfp, unsigned long attrs)
-+{
-+      void *ret;
-+
-+      ret = arch_dma_ops->alloc(dev, size, handle, gfp, attrs);
-+      if (ret)
-+              *handle = brcm_to_pci(*handle);
-+      return ret;
-+}
-+
-+static void brcm_free(struct device *dev, size_t size, void *cpu_addr,
-+                    dma_addr_t handle, unsigned long attrs)
-+{
-+      handle = brcm_to_cpu(handle);
-+      arch_dma_ops->free(dev, size, cpu_addr, handle, attrs);
-+}
-+
-+static int brcm_mmap(struct device *dev, struct vm_area_struct *vma,
-+                   void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+                   unsigned long attrs)
-+{
-+      dma_addr = brcm_to_cpu(dma_addr);
-+      return arch_dma_ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
-+}
-+
-+static int brcm_get_sgtable(struct device *dev, struct sg_table *sgt,
-+                          void *cpu_addr, dma_addr_t handle, size_t size,
-+                          unsigned long attrs)
-+{
-+      handle = brcm_to_cpu(handle);
-+      return arch_dma_ops->get_sgtable(dev, sgt, cpu_addr, handle, size,
-+                                     attrs);
-+}
-+
-+static dma_addr_t brcm_map_page(struct device *dev, struct page *page,
-+                              unsigned long offset, size_t size,
-+                              enum dma_data_direction dir,
-+                              unsigned long attrs)
-+{
-+      return brcm_to_pci(arch_dma_ops->map_page(dev, page, offset, size,
-+                                                dir, attrs));
-+}
-+
-+static void brcm_unmap_page(struct device *dev, dma_addr_t handle,
-+                          size_t size, enum dma_data_direction dir,
-+                          unsigned long attrs)
-+{
-+      handle = brcm_to_cpu(handle);
-+      arch_dma_ops->unmap_page(dev, handle, size, dir, attrs);
-+}
-+
-+static int brcm_map_sg(struct device *dev, struct scatterlist *sgl,
-+                     int nents, enum dma_data_direction dir,
-+                     unsigned long attrs)
-+{
-+      int i, j;
-+      struct scatterlist *sg;
-+
-+      for_each_sg(sgl, sg, nents, i) {
-+#ifdef CONFIG_NEED_SG_DMA_LENGTH
-+              sg->dma_length = sg->length;
-+#endif
-+              sg->dma_address =
-+                      brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
-+                                                 sg->length, dir, attrs);
-+              if (dma_mapping_error(dev, sg->dma_address))
-+                      goto bad_mapping;
-+      }
-+      return nents;
-+
-+bad_mapping:
-+      for_each_sg(sgl, sg, i, j)
-+              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
-+                                           sg_dma_len(sg), dir, attrs);
-+      return 0;
-+}
-+
-+static void brcm_unmap_sg(struct device *dev,
-+                        struct scatterlist *sgl, int nents,
-+                        enum dma_data_direction dir,
-+                        unsigned long attrs)
-+{
-+      int i;
-+      struct scatterlist *sg;
-+
-+      for_each_sg(sgl, sg, nents, i)
-+              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
-+                                           sg_dma_len(sg), dir, attrs);
-+}
-+
-+static void brcm_sync_single_for_cpu(struct device *dev,
-+                                   dma_addr_t handle, size_t size,
-+                                   enum dma_data_direction dir)
-+{
-+      handle = brcm_to_cpu(handle);
-+      arch_dma_ops->sync_single_for_cpu(dev, handle, size, dir);
-+}
-+
-+static void brcm_sync_single_for_device(struct device *dev,
-+                                      dma_addr_t handle, size_t size,
-+                                      enum dma_data_direction dir)
-+{
-+      handle = brcm_to_cpu(handle);
-+      arch_dma_ops->sync_single_for_device(dev, handle, size, dir);
-+}
-+
-+static dma_addr_t brcm_map_resource(struct device *dev, phys_addr_t phys,
-+                                  size_t size,
-+                                  enum dma_data_direction dir,
-+                                  unsigned long attrs)
-+{
-+      if (arch_dma_ops->map_resource)
-+              return brcm_to_pci(arch_dma_ops->map_resource
-+                                 (dev, phys, size, dir, attrs));
-+      return brcm_to_pci((dma_addr_t)phys);
-+}
-+
-+static void brcm_unmap_resource(struct device *dev, dma_addr_t handle,
-+                              size_t size, enum dma_data_direction dir,
-+                              unsigned long attrs)
-+{
-+      if (arch_dma_ops->unmap_resource)
-+              arch_dma_ops->unmap_resource(dev, brcm_to_cpu(handle), size,
-+                                           dir, attrs);
-+}
-+
-+void brcm_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
-+                        int nents, enum dma_data_direction dir)
-+{
-+      struct scatterlist *sg;
-+      int i;
-+
-+      for_each_sg(sgl, sg, nents, i)
-+              brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
-+                                                    sg->length, dir);
-+}
-+
-+void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
-+                           int nents, enum dma_data_direction dir)
-+{
-+      struct scatterlist *sg;
-+      int i;
-+
-+      for_each_sg(sgl, sg, nents, i)
-+              brcm_dma_ops_ptr->sync_single_for_device(dev,
-+                                                       sg_dma_address(sg),
-+                                                       sg->length, dir);
-+}
-+
-+static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
-+{
-+      return arch_dma_ops->mapping_error(dev, dma_addr);
-+}
-+
-+static int brcm_dma_supported(struct device *dev, u64 mask)
-+{
-+      if (num_dma_ranges) {
-+              /*
-+               * It is our translated addresses that the EP will "see", so
-+               * we check all of the ranges for the largest possible value.
-+               */
-+              int i;
-+
-+              for (i = 0; i < num_dma_ranges; i++)
-+                      if (dma_ranges[i].pci_addr + dma_ranges[i].size - 1
-+                          > mask)
-+                              return 0;
-+              return 1;
-+      }
-+
-+      return arch_dma_ops->dma_supported(dev, mask);
-+}
-+
-+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
-+u64 brcm_get_required_mask)(struct device *dev)
-+{
-+      return arch_dma_ops->get_required_mask(dev);
-+}
-+#endif
-+
-+static const struct dma_map_ops brcm_dma_ops = {
-+      .alloc                  = brcm_alloc,
-+      .free                   = brcm_free,
-+      .mmap                   = brcm_mmap,
-+      .get_sgtable            = brcm_get_sgtable,
-+      .map_page               = brcm_map_page,
-+      .unmap_page             = brcm_unmap_page,
-+      .map_sg                 = brcm_map_sg,
-+      .unmap_sg               = brcm_unmap_sg,
-+      .map_resource           = brcm_map_resource,
-+      .unmap_resource         = brcm_unmap_resource,
-+      .sync_single_for_cpu    = brcm_sync_single_for_cpu,
-+      .sync_single_for_device = brcm_sync_single_for_device,
-+      .sync_sg_for_cpu        = brcm_sync_sg_for_cpu,
-+      .sync_sg_for_device     = brcm_sync_sg_for_device,
-+      .mapping_error          = brcm_mapping_error,
-+      .dma_supported          = brcm_dma_supported,
-+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
-+      .get_required_mask      = brcm_get_required_mask,
-+#endif
-+};
-+
-+static void brcm_set_dma_ops(struct device *dev)
-+{
-+      int ret;
-+
-+      if (IS_ENABLED(CONFIG_ARM64)) {
-+              /*
-+               * We are going to invoke get_dma_ops().  That
-+               * function, at this point in time, invokes
-+               * get_arch_dma_ops(), and for ARM64 that function
-+               * returns a pointer to dummy_dma_ops.  So then we'd
-+               * like to call arch_setup_dma_ops(), but that isn't
-+               * exported.  Instead, we call of_dma_configure(),
-+               * which is exported, and this calls
-+               * arch_setup_dma_ops().  Once we do this the call to
-+               * get_dma_ops() will work properly because
-+               * dev->dma_ops will be set.
-+               */
-+              ret = of_dma_configure(dev, dev->of_node, true);
-+              if (ret) {
-+                      dev_err(dev, "of_dma_configure() failed: %d\n", ret);
-+                      return;
-+              }
-+      }
-+
-+      arch_dma_ops = get_dma_ops(dev);
-+      if (!arch_dma_ops) {
-+              dev_err(dev, "failed to get arch_dma_ops\n");
-+              return;
-+      }
-+
-+      set_dma_ops(dev, &brcm_dma_ops);
-+}
-+
-+static int brcmstb_platform_notifier(struct notifier_block *nb,
-+                                   unsigned long event, void *__dev)
-+{
-+      struct device *dev = __dev;
-+
-+      brcm_dma_ops_ptr = &brcm_dma_ops;
-+      if (event != BUS_NOTIFY_ADD_DEVICE)
-+              return NOTIFY_DONE;
-+
-+      brcm_set_dma_ops(dev);
-+      return NOTIFY_OK;
-+}
-+
-+static struct notifier_block brcmstb_platform_nb = {
-+      .notifier_call = brcmstb_platform_notifier,
-+};
-+
-+static int brcm_register_notifier(void)
-+{
-+      return bus_register_notifier(&pci_bus_type, &brcmstb_platform_nb);
-+}
-+
-+static int brcm_unregister_notifier(void)
-+{
-+      return bus_unregister_notifier(&pci_bus_type, &brcmstb_platform_nb);
-+}
-+
- static u32 rd_fld(void __iomem *p, u32 mask, int shift)
- {
-       return (bcm_readl(p) & mask) >> shift;
-@@ -597,9 +894,71 @@ static inline void brcm_pcie_perst_set(s
-               WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
- }
-+static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
-+                                   struct device_node *node)
-+{
-+      const int na = 3, ns = 2;
-+      int rlen;
-+
-+      parser->node = node;
-+      parser->pna = of_n_addr_cells(node);
-+      parser->np = parser->pna + na + ns;
-+
-+      parser->range = of_get_property(node, "dma-ranges", &rlen);
-+      if (!parser->range)
-+              return -ENOENT;
-+
-+      parser->end = parser->range + rlen / sizeof(__be32);
-+
-+      return 0;
-+}
-+
-+static int brcm_pcie_parse_map_dma_ranges(struct brcm_pcie *pcie)
-+{
-+      int i;
-+      struct of_pci_range_parser parser;
-+      struct device_node *dn = pcie->dn;
-+
-+      /*
-+       * Parse dma-ranges property if present.  If there are multiple
-+       * PCIe controllers, we only have to parse from one of them since
-+       * the others will have an identical mapping.
-+       */
-+      if (!pci_dma_range_parser_init(&parser, dn)) {
-+              unsigned int max_ranges
-+                      = (parser.end - parser.range) / parser.np;
-+
-+              dma_ranges = kcalloc(max_ranges, sizeof(struct of_pci_range),
-+                                   GFP_KERNEL);
-+              if (!dma_ranges)
-+                      return -ENOMEM;
-+
-+              for (i = 0; of_pci_range_parser_one(&parser, dma_ranges + i);
-+                   i++)
-+                      num_dma_ranges++;
-+      }
-+
-+      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-+              u64 size = brcmstb_memory_memc_size(i);
-+
-+              if (size == (u64)-1) {
-+                      dev_err(pcie->dev, "cannot get memc%d size", i);
-+                      return -EINVAL;
-+              } else if (size) {
-+                      scb_size[i] = roundup_pow_of_two_64(size);
-+                      num_memc++;
-+              } else {
-+                      break;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
- static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
- {
-       int i, ret = 0;
-+      struct device *dev = pcie->dev;
-       mutex_lock(&brcm_pcie_lock);
-       if (num_pcie > 0) {
-@@ -607,12 +966,21 @@ static int brcm_pcie_add_controller(stru
-               goto done;
-       }
-+      ret = brcm_register_notifier();
-+      if (ret) {
-+              dev_err(dev, "failed to register pci bus notifier\n");
-+              goto done;
-+      }
-+      ret = brcm_pcie_parse_map_dma_ranges(pcie);
-+      if (ret)
-+              goto done;
-+
-       /* Determine num_memc and their sizes */
-       for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-               u64 size = brcmstb_memory_memc_size(i);
-               if (size == (u64)-1) {
--                      dev_err(pcie->dev, "cannot get memc%d size\n", i);
-+                      dev_err(dev, "cannot get memc%d size\n", i);
-                       ret = -EINVAL;
-                       goto done;
-               } else if (size) {
-@@ -636,8 +1004,16 @@ done:
- static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
- {
-       mutex_lock(&brcm_pcie_lock);
--      if (--num_pcie == 0)
--              num_memc = 0;
-+      if (--num_pcie > 0)
-+              goto out;
-+
-+      if (brcm_unregister_notifier())
-+              dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
-+      kfree(dma_ranges);
-+      dma_ranges = NULL;
-+      num_dma_ranges = 0;
-+      num_memc = 0;
-+out:
-       mutex_unlock(&brcm_pcie_lock);
- }
-@@ -757,6 +1133,38 @@ static int brcm_pcie_setup(struct brcm_p
-        */
-       rc_bar2_offset = 0;
-+      if (dma_ranges) {
-+              /*
-+               * The best-case scenario is to place the inbound
-+               * region in the first 4GB of pci-space, as some
-+               * legacy devices can only address 32bits.
-+               * We would also like to put the MSI under 4GB
-+               * as well, since some devices require a 32bit
-+               * MSI target address.
-+               */
-+              if (total_mem_size <= 0xc0000000ULL &&
-+                  rc_bar2_size <= 0x100000000ULL) {
-+                      rc_bar2_offset = 0;
-+              } else {
-+                      /*
-+                       * The system memory is 4GB or larger so we
-+                       * cannot start the inbound region at location
-+                       * 0 (since we have to allow some space for
-+                       * outbound memory @ 3GB).  So instead we
-+                       * start it at the 1x multiple of its size
-+                       */
-+                      rc_bar2_offset = rc_bar2_size;
-+              }
-+
-+      } else {
-+              /*
-+               * Set simple configuration based on memory sizes
-+               * only.  We always start the viewport at address 0,
-+               * and set the MSI target address accordingly.
-+               */
-+              rc_bar2_offset = 0;
-+      }
-+
-       tmp = lower_32_bits(rc_bar2_offset);
-       tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
-                          encode_ibar_size(rc_bar2_size));
-@@ -967,7 +1375,6 @@ static int brcm_pcie_probe(struct platfo
-       struct brcm_pcie *pcie;
-       struct resource *res;
-       void __iomem *base;
--      u32 tmp;
-       struct pci_host_bridge *bridge;
-       struct pci_bus *child;
-@@ -984,11 +1391,6 @@ static int brcm_pcie_probe(struct platfo
-               return -EINVAL;
-       }
--      if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
--              dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
--              return -EINVAL;
--      }
--
-       data = of_id->data;
-       pcie->reg_offsets = data->offsets;
-       pcie->reg_field_info = data->reg_field_info;
diff --git a/target/linux/brcm2708/patches-4.19/950-0459-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch b/target/linux/brcm2708/patches-4.19/950-0459-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch
new file mode 100644 (file)
index 0000000..632e986
--- /dev/null
@@ -0,0 +1,77 @@
+From cb1acabb459677efbf95c54ce1dc5252be30a018 Mon Sep 17 00:00:00 2001
+From: Jim Quinlan <jim2101024@gmail.com>
+Date: Mon, 15 Jan 2018 18:28:39 -0500
+Subject: [PATCH] dt-bindings: pci: Add DT docs for Brcmstb PCIe device
+
+The DT bindings description of the Brcmstb PCIe device is described.  This
+node can be used by almost all Broadcom settop box chips, using
+ARM, ARM64, or MIPS CPU architectures.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ .../devicetree/bindings/pci/brcmstb-pcie.txt  | 59 +++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
+@@ -0,0 +1,59 @@
++Brcmstb PCIe Host Controller Device Tree Bindings
++
++Required Properties:
++- compatible
++  "brcm,bcm7425-pcie" -- for 7425 family MIPS-based SOCs.
++  "brcm,bcm7435-pcie" -- for 7435 family MIPS-based SOCs.
++  "brcm,bcm7445-pcie" -- for 7445 and later ARM based SOCs (not including
++      the 7278).
++  "brcm,bcm7278-pcie"  -- for 7278 family ARM-based SOCs.
++
++- reg -- the register start address and length for the PCIe reg block.
++- interrupts -- two interrupts are specified; the first interrupt is for
++     the PCI host controller and the second is for MSI if the built-in
++     MSI controller is to be used.
++- interrupt-names -- names of the interrupts (above): "pcie" and "msi".
++- #address-cells -- set to <3>.
++- #size-cells -- set to <2>.
++- #interrupt-cells: set to <1>.
++- interrupt-map-mask and interrupt-map, standard PCI properties to define the
++     mapping of the PCIe interface to interrupt numbers.
++- ranges: ranges for the PCI memory and I/O regions.
++- linux,pci-domain -- should be unique per host controller.
++
++Optional Properties:
++- clocks -- phandle of pcie clock.
++- clock-names -- set to "sw_pcie" if clocks is used.
++- dma-ranges -- Specifies the inbound memory mapping regions when
++     an "identity map" is not possible.
++- msi-controller -- this property is typically specified to have the
++     PCIe controller use its internal MSI controller.
++- msi-parent -- set to use an external MSI interrupt controller.
++- brcm,enable-ssc -- (boolean) indicates usage of spread-spectrum clocking.
++- max-link-speed --  (integer) indicates desired generation of link:
++     1 => 2.5 Gbps (gen1), 2 => 5.0 Gbps (gen2), 3 => 8.0 Gbps (gen3).
++
++Example Node:
++
++pcie0: pcie@f0460000 {
++              reg = <0x0 0xf0460000 0x0 0x9310>;
++              interrupts = <0x0 0x0 0x4>;
++              compatible = "brcm,bcm7445-pcie";
++              #address-cells = <3>;
++              #size-cells = <2>;
++              ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000
++                        0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
++              #interrupt-cells = <1>;
++              interrupt-map-mask = <0 0 0 7>;
++              interrupt-map = <0 0 0 1 &intc 0 47 3
++                               0 0 0 2 &intc 0 48 3
++                               0 0 0 3 &intc 0 49 3
++                               0 0 0 4 &intc 0 50 3>;
++              clocks = <&sw_pcie0>;
++              clock-names = "sw_pcie";
++              msi-parent = <&pcie0>;  /* use PCIe's internal MSI controller */
++              msi-controller;         /* use PCIe's internal MSI controller */
++              brcm,ssc;
++              max-link-speed = <1>;
++              linux,pci-domain = <0>;
++      };
diff --git a/target/linux/brcm2708/patches-4.19/950-0460-PCI-brcmstb-Add-MSI-capability.patch b/target/linux/brcm2708/patches-4.19/950-0460-PCI-brcmstb-Add-MSI-capability.patch
deleted file mode 100644 (file)
index 856bf2b..0000000
+++ /dev/null
@@ -1,543 +0,0 @@
-From cd3af4fa73ab25353f0865ebe8e0d2af1fd2a50b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH] PCI: brcmstb: Add MSI capability
-
-This commit adds MSI to the Broadcom STB PCIe host controller. It does
-not add MSIX since that functionality is not in the HW.  The MSI
-controller is physically located within the PCIe block, however, there
-is no reason why the MSI controller could not be moved elsewhere in
-the future.
-
-Since the internal Brcmstb MSI controller is intertwined with the PCIe
-controller, it is not its own platform device but rather part of the
-PCIe platform device.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- drivers/pci/controller/pcie-brcmstb.c | 374 ++++++++++++++++++++++++--
- 1 file changed, 353 insertions(+), 21 deletions(-)
-
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -1,6 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright (C) 2009 - 2017 Broadcom */
-+#include <linux/bitops.h>
- #include <linux/clk.h>
- #include <linux/compiler.h>
- #include <linux/delay.h>
-@@ -9,11 +10,13 @@
- #include <linux/interrupt.h>
- #include <linux/io.h>
- #include <linux/ioport.h>
-+#include <linux/irqchip/chained_irq.h>
- #include <linux/irqdomain.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
- #include <linux/log2.h>
- #include <linux/module.h>
-+#include <linux/msi.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- #include <linux/of_pci.h>
-@@ -47,6 +50,9 @@
- #define PCIE_MISC_RC_BAR2_CONFIG_LO                   0x4034
- #define PCIE_MISC_RC_BAR2_CONFIG_HI                   0x4038
- #define PCIE_MISC_RC_BAR3_CONFIG_LO                   0x403c
-+#define PCIE_MISC_MSI_BAR_CONFIG_LO                   0x4044
-+#define PCIE_MISC_MSI_BAR_CONFIG_HI                   0x4048
-+#define PCIE_MISC_MSI_DATA_CONFIG                     0x404c
- #define PCIE_MISC_PCIE_CTRL                           0x4064
- #define PCIE_MISC_PCIE_STATUS                         0x4068
- #define PCIE_MISC_REVISION                            0x406c
-@@ -55,6 +61,7 @@
- #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI                0x4084
- #define PCIE_MISC_HARD_PCIE_HARD_DEBUG                        0x4204
- #define PCIE_INTR2_CPU_BASE                           0x4300
-+#define PCIE_MSI_INTR2_BASE                           0x4500
- /*
-  * Broadcom Settop Box PCIe Register Field shift and mask info. The
-@@ -115,6 +122,8 @@
- #define BRCM_NUM_PCIE_OUT_WINS                0x4
- #define BRCM_MAX_SCB                  0x4
-+#define BRCM_INT_PCI_MSI_NR           32
-+#define BRCM_PCIE_HW_REV_33           0x0303
- #define BRCM_MSI_TARGET_ADDR_LT_4GB   0x0fffffffcULL
- #define BRCM_MSI_TARGET_ADDR_GT_4GB   0xffffffffcULL
-@@ -203,6 +212,33 @@ struct brcm_window {
-       dma_addr_t size;
- };
-+struct brcm_msi {
-+      struct device           *dev;
-+      void __iomem            *base;
-+      struct device_node      *dn;
-+      struct irq_domain       *msi_domain;
-+      struct irq_domain       *inner_domain;
-+      struct mutex            lock; /* guards the alloc/free operations */
-+      u64                     target_addr;
-+      int                     irq;
-+
-+      /* intr_base is the base pointer for interrupt status/set/clr regs */
-+      void __iomem            *intr_base;
-+
-+      /* intr_legacy_mask indicates how many bits are MSI interrupts */
-+      u32                     intr_legacy_mask;
-+
-+      /*
-+       * intr_legacy_offset indicates bit position of MSI_01. It is
-+       * to map the register bit position to a hwirq that starts at 0.
-+       */
-+      u32                     intr_legacy_offset;
-+
-+      /* used indicates which MSI interrupts have been alloc'd */
-+      unsigned long           used;
-+      unsigned int            rev;
-+};
-+
- /* Internal PCIe Host Controller Information.*/
- struct brcm_pcie {
-       struct device           *dev;
-@@ -217,7 +253,10 @@ struct brcm_pcie {
-       int                     num_out_wins;
-       bool                    ssc;
-       int                     gen;
-+      u64                     msi_target_addr;
-       struct brcm_window      out_wins[BRCM_NUM_PCIE_OUT_WINS];
-+      struct brcm_msi         *msi;
-+      bool                    msi_internal;
-       unsigned int            rev;
-       const int               *reg_offsets;
-       const int               *reg_field_info;
-@@ -225,9 +264,9 @@ struct brcm_pcie {
- };
- struct pcie_cfg_data {
--      const int *reg_field_info;
--      const int *offsets;
--      const enum pcie_type type;
-+      const int               *reg_field_info;
-+      const int               *offsets;
-+      const enum pcie_type    type;
- };
- static const int pcie_reg_field_info[] = {
-@@ -828,6 +867,267 @@ static void brcm_pcie_set_outbound_win(s
-       }
- }
-+static struct irq_chip brcm_msi_irq_chip = {
-+      .name = "Brcm_MSI",
-+      .irq_mask = pci_msi_mask_irq,
-+      .irq_unmask = pci_msi_unmask_irq,
-+};
-+
-+static struct msi_domain_info brcm_msi_domain_info = {
-+      .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-+                 MSI_FLAG_PCI_MSIX),
-+      .chip   = &brcm_msi_irq_chip,
-+};
-+
-+static void brcm_pcie_msi_isr(struct irq_desc *desc)
-+{
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      struct brcm_msi *msi;
-+      unsigned long status, virq;
-+      u32 mask, bit, hwirq;
-+      struct device *dev;
-+
-+      chained_irq_enter(chip, desc);
-+      msi = irq_desc_get_handler_data(desc);
-+      mask = msi->intr_legacy_mask;
-+      dev = msi->dev;
-+
-+      while ((status = bcm_readl(msi->intr_base + STATUS) & mask)) {
-+              for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
-+                      /* clear the interrupt */
-+                      bcm_writel(1 << bit, msi->intr_base + CLR);
-+
-+                      /* Account for legacy interrupt offset */
-+                      hwirq = bit - msi->intr_legacy_offset;
-+
-+                      virq = irq_find_mapping(msi->inner_domain, hwirq);
-+                      if (virq) {
-+                              if (msi->used & (1 << hwirq))
-+                                      generic_handle_irq(virq);
-+                              else
-+                                      dev_info(dev, "unhandled MSI %d\n",
-+                                               hwirq);
-+                      } else {
-+                              /* Unknown MSI, just clear it */
-+                              dev_dbg(dev, "unexpected MSI\n");
-+                      }
-+              }
-+      }
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-+{
-+      struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
-+      u32 temp;
-+
-+      msg->address_lo = lower_32_bits(msi->target_addr);
-+      msg->address_hi = upper_32_bits(msi->target_addr);
-+      temp = bcm_readl(msi->base + PCIE_MISC_MSI_DATA_CONFIG);
-+      msg->data = ((temp >> 16) & (temp & 0xffff)) | data->hwirq;
-+}
-+
-+static int brcm_msi_set_affinity(struct irq_data *irq_data,
-+                               const struct cpumask *mask, bool force)
-+{
-+      return -EINVAL;
-+}
-+
-+static struct irq_chip brcm_msi_bottom_irq_chip = {
-+      .name                   = "Brcm_MSI",
-+      .irq_compose_msi_msg    = brcm_compose_msi_msg,
-+      .irq_set_affinity       = brcm_msi_set_affinity,
-+};
-+
-+static int brcm_msi_alloc(struct brcm_msi *msi)
-+{
-+      int bit, hwirq;
-+
-+      mutex_lock(&msi->lock);
-+      bit = ~msi->used ? ffz(msi->used) : -1;
-+
-+      if (bit >= 0 && bit < BRCM_INT_PCI_MSI_NR) {
-+              msi->used |= (1 << bit);
-+              hwirq = bit - msi->intr_legacy_offset;
-+      } else {
-+              hwirq = -ENOSPC;
-+      }
-+
-+      mutex_unlock(&msi->lock);
-+      return hwirq;
-+}
-+
-+static void brcm_msi_free(struct brcm_msi *msi, unsigned long hwirq)
-+{
-+      mutex_lock(&msi->lock);
-+      msi->used &= ~(1 << (hwirq + msi->intr_legacy_offset));
-+      mutex_unlock(&msi->lock);
-+}
-+
-+static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
-+                               unsigned int nr_irqs, void *args)
-+{
-+      struct brcm_msi *msi = domain->host_data;
-+      int hwirq;
-+
-+      hwirq = brcm_msi_alloc(msi);
-+
-+      if (hwirq < 0)
-+              return hwirq;
-+
-+      irq_domain_set_info(domain, virq, (irq_hw_number_t)hwirq,
-+                          &brcm_msi_bottom_irq_chip, domain->host_data,
-+                          handle_simple_irq, NULL, NULL);
-+      return 0;
-+}
-+
-+static void brcm_irq_domain_free(struct irq_domain *domain,
-+                               unsigned int virq, unsigned int nr_irqs)
-+{
-+      struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-+      struct brcm_msi *msi = irq_data_get_irq_chip_data(d);
-+
-+      brcm_msi_free(msi, d->hwirq);
-+}
-+
-+static void brcm_msi_set_regs(struct brcm_msi *msi)
-+{
-+      u32 data_val, msi_lo, msi_hi;
-+
-+      if (msi->rev >= BRCM_PCIE_HW_REV_33) {
-+              /*
-+               * ffe0 -- least sig 5 bits are 0 indicating 32 msgs
-+               * 6540 -- this is our arbitrary unique data value
-+               */
-+              data_val = 0xffe06540;
-+      } else {
-+              /*
-+               * fff8 -- least sig 3 bits are 0 indicating 8 msgs
-+               * 6540 -- this is our arbitrary unique data value
-+               */
-+              data_val = 0xfff86540;
-+      }
-+
-+      /*
-+       * Make sure we are not masking MSIs.  Note that MSIs can be masked,
-+       * but that occurs on the PCIe EP device
-+       */
-+      bcm_writel(0xffffffff & msi->intr_legacy_mask,
-+                 msi->intr_base + MASK_CLR);
-+
-+      msi_lo = lower_32_bits(msi->target_addr);
-+      msi_hi = upper_32_bits(msi->target_addr);
-+      /*
-+       * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
-+       * enable, which we set to 1.
-+       */
-+      bcm_writel(msi_lo | 1, msi->base + PCIE_MISC_MSI_BAR_CONFIG_LO);
-+      bcm_writel(msi_hi, msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
-+      bcm_writel(data_val, msi->base + PCIE_MISC_MSI_DATA_CONFIG);
-+}
-+
-+static const struct irq_domain_ops msi_domain_ops = {
-+      .alloc  = brcm_irq_domain_alloc,
-+      .free   = brcm_irq_domain_free,
-+};
-+
-+static int brcm_allocate_domains(struct brcm_msi *msi)
-+{
-+      struct fwnode_handle *fwnode = of_node_to_fwnode(msi->dn);
-+      struct device *dev = msi->dev;
-+
-+      msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
-+                                                &msi_domain_ops, msi);
-+      if (!msi->inner_domain) {
-+              dev_err(dev, "failed to create IRQ domain\n");
-+              return -ENOMEM;
-+      }
-+
-+      msi->msi_domain = pci_msi_create_irq_domain(fwnode,
-+                                                  &brcm_msi_domain_info,
-+                                                  msi->inner_domain);
-+      if (!msi->msi_domain) {
-+              dev_err(dev, "failed to create MSI domain\n");
-+              irq_domain_remove(msi->inner_domain);
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+
-+static void brcm_free_domains(struct brcm_msi *msi)
-+{
-+      irq_domain_remove(msi->msi_domain);
-+      irq_domain_remove(msi->inner_domain);
-+}
-+
-+static void brcm_msi_remove(struct brcm_pcie *pcie)
-+{
-+      struct brcm_msi *msi = pcie->msi;
-+
-+      if (!msi)
-+              return;
-+      irq_set_chained_handler(msi->irq, NULL);
-+      irq_set_handler_data(msi->irq, NULL);
-+      brcm_free_domains(msi);
-+}
-+
-+static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
-+{
-+      struct brcm_msi *msi;
-+      int irq, ret;
-+      struct device *dev = pcie->dev;
-+
-+      irq = irq_of_parse_and_map(dev->of_node, 1);
-+      if (irq <= 0) {
-+              dev_err(dev, "cannot map msi intr\n");
-+              return -ENODEV;
-+      }
-+
-+      msi = devm_kzalloc(dev, sizeof(struct brcm_msi), GFP_KERNEL);
-+      if (!msi)
-+              return -ENOMEM;
-+
-+      msi->dev = dev;
-+      msi->base = pcie->base;
-+      msi->rev =  pcie->rev;
-+      msi->dn = pcie->dn;
-+      msi->target_addr = pcie->msi_target_addr;
-+      msi->irq = irq;
-+
-+      ret = brcm_allocate_domains(msi);
-+      if (ret)
-+              return ret;
-+
-+      irq_set_chained_handler_and_data(msi->irq, brcm_pcie_msi_isr, msi);
-+
-+      if (msi->rev >= BRCM_PCIE_HW_REV_33) {
-+              msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE;
-+              /*
-+               * This version of PCIe hw has only 32 intr bits
-+               * starting at bit position 0.
-+               */
-+              msi->intr_legacy_mask = 0xffffffff;
-+              msi->intr_legacy_offset = 0x0;
-+              msi->used = 0x0;
-+
-+      } else {
-+              msi->intr_base = msi->base + PCIE_INTR2_CPU_BASE;
-+              /*
-+               * This version of PCIe hw has only 8 intr bits starting
-+               * at bit position 24.
-+               */
-+              msi->intr_legacy_mask = 0xff000000;
-+              msi->intr_legacy_offset = 24;
-+              msi->used = 0x00ffffff;
-+      }
-+
-+      brcm_msi_set_regs(msi);
-+      pcie->msi = msi;
-+
-+      return 0;
-+}
-+
- /* Configuration space read/write support */
- static int cfg_index(int busnr, int devfn, int reg)
- {
-@@ -1072,6 +1372,7 @@ static int brcm_pcie_setup(struct brcm_p
-       u16 nlw, cls, lnksta;
-       bool ssc_good = false;
-       struct device *dev = pcie->dev;
-+      u64 msi_target_addr;
-       /* Reset the bridge */
-       brcm_pcie_bridge_sw_init_set(pcie, 1);
-@@ -1116,27 +1417,24 @@ static int brcm_pcie_setup(struct brcm_p
-        * The PCIe host controller by design must set the inbound
-        * viewport to be a contiguous arrangement of all of the
-        * system's memory.  In addition, its size mut be a power of
--       * two.  To further complicate matters, the viewport must
--       * start on a pcie-address that is aligned on a multiple of its
--       * size.  If a portion of the viewport does not represent
--       * system memory -- e.g. 3GB of memory requires a 4GB viewport
--       * -- we can map the outbound memory in or after 3GB and even
--       * though the viewport will overlap the outbound memory the
--       * controller will know to send outbound memory downstream and
--       * everything else upstream.
-+       * two.  Further, the MSI target address must NOT be placed
-+       * inside this region, as the decoding logic will consider its
-+       * address to be inbound memory traffic.  To further
-+       * complicate matters, the viewport must start on a
-+       * pcie-address that is aligned on a multiple of its size.
-+       * If a portion of the viewport does not represent system
-+       * memory -- e.g. 3GB of memory requires a 4GB viewport --
-+       * we can map the outbound memory in or after 3GB and even
-+       * though the viewport will overlap the outbound memory
-+       * the controller will know to send outbound memory downstream
-+       * and everything else upstream.
-        */
-       rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
--      /*
--       * Set simple configuration based on memory sizes
--       * only.  We always start the viewport at address 0.
--       */
--      rc_bar2_offset = 0;
--
-       if (dma_ranges) {
-               /*
-                * The best-case scenario is to place the inbound
--               * region in the first 4GB of pci-space, as some
-+               * region in the first 4GB of pcie-space, as some
-                * legacy devices can only address 32bits.
-                * We would also like to put the MSI under 4GB
-                * as well, since some devices require a 32bit
-@@ -1145,6 +1443,14 @@ static int brcm_pcie_setup(struct brcm_p
-               if (total_mem_size <= 0xc0000000ULL &&
-                   rc_bar2_size <= 0x100000000ULL) {
-                       rc_bar2_offset = 0;
-+                      /* If the viewport is less then 4GB we can fit
-+                       * the MSI target address under 4GB. Otherwise
-+                       * put it right below 64GB.
-+                       */
-+                      msi_target_addr =
-+                              (rc_bar2_size == 0x100000000ULL)
-+                              ? BRCM_MSI_TARGET_ADDR_GT_4GB
-+                              : BRCM_MSI_TARGET_ADDR_LT_4GB;
-               } else {
-                       /*
-                        * The system memory is 4GB or larger so we
-@@ -1154,8 +1460,12 @@ static int brcm_pcie_setup(struct brcm_p
-                        * start it at the 1x multiple of its size
-                        */
-                       rc_bar2_offset = rc_bar2_size;
--              }
-+                      /* Since we are starting the viewport at 4GB or
-+                       * higher, put the MSI target address below 4GB
-+                       */
-+                      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
-+              }
-       } else {
-               /*
-                * Set simple configuration based on memory sizes
-@@ -1163,7 +1473,12 @@ static int brcm_pcie_setup(struct brcm_p
-                * and set the MSI target address accordingly.
-                */
-               rc_bar2_offset = 0;
-+
-+              msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
-+                      ? BRCM_MSI_TARGET_ADDR_GT_4GB
-+                      : BRCM_MSI_TARGET_ADDR_LT_4GB;
-       }
-+      pcie->msi_target_addr = msi_target_addr;
-       tmp = lower_32_bits(rc_bar2_offset);
-       tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
-@@ -1333,6 +1648,9 @@ static int brcm_pcie_resume(struct devic
-       if (ret)
-               return ret;
-+      if (pcie->msi && pcie->msi_internal)
-+              brcm_msi_set_regs(pcie->msi);
-+
-       pcie->suspended = false;
-       return 0;
-@@ -1340,6 +1658,7 @@ static int brcm_pcie_resume(struct devic
- static void _brcm_pcie_remove(struct brcm_pcie *pcie)
- {
-+      brcm_msi_remove(pcie);
-       turn_off(pcie);
-       clk_disable_unprepare(pcie->clk);
-       clk_put(pcie->clk);
-@@ -1368,7 +1687,7 @@ MODULE_DEVICE_TABLE(of, brcm_pcie_match)
- static int brcm_pcie_probe(struct platform_device *pdev)
- {
--      struct device_node *dn = pdev->dev.of_node;
-+      struct device_node *dn = pdev->dev.of_node, *msi_dn;
-       const struct of_device_id *of_id;
-       const struct pcie_cfg_data *data;
-       int ret;
-@@ -1448,6 +1767,20 @@ static int brcm_pcie_probe(struct platfo
-       if (ret)
-               goto fail;
-+      msi_dn = of_parse_phandle(pcie->dn, "msi-parent", 0);
-+      /* Use the internal MSI if no msi-parent property */
-+      if (!msi_dn)
-+              msi_dn = pcie->dn;
-+
-+      if (pci_msi_enabled() && msi_dn == pcie->dn) {
-+              ret = brcm_pcie_enable_msi(pcie);
-+              if (ret)
-+                      dev_err(pcie->dev,
-+                              "probe of internal MSI failed: %d)", ret);
-+              else
-+                      pcie->msi_internal = true;
-+      }
-+
-       list_splice_init(&pcie->resources, &bridge->windows);
-       bridge->dev.parent = &pdev->dev;
-       bridge->busnr = 0;
-@@ -1470,7 +1803,6 @@ static int brcm_pcie_probe(struct platfo
-       pcie->root_bus = bridge->bus;
-       return 0;
--
- fail:
-       _brcm_pcie_remove(pcie);
-       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0460-pcie-brcmstb-Changes-for-BCM2711.patch b/target/linux/brcm2708/patches-4.19/950-0460-pcie-brcmstb-Changes-for-BCM2711.patch
new file mode 100644 (file)
index 0000000..b44ec4c
--- /dev/null
@@ -0,0 +1,1411 @@
+From 545951be6cabac8b1df85771c44335a0eaaa3c5d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH] pcie-brcmstb: Changes for BCM2711
+
+The initial brcmstb PCIe driver - originally taken from the V3(?)
+patch set - has been modified significantly for the BCM2711.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/dma/bcm2835-dma.c                    | 107 ++++
+ drivers/pci/controller/Makefile              |   4 +
+ drivers/pci/controller/pcie-brcmstb-bounce.c | 564 +++++++++++++++++++
+ drivers/pci/controller/pcie-brcmstb-bounce.h |  32 ++
+ drivers/pci/controller/pcie-brcmstb.c        | 237 ++++----
+ drivers/soc/bcm/brcmstb/Makefile             |   2 +-
+ drivers/soc/bcm/brcmstb/memory.c             | 158 ++++++
+ 7 files changed, 996 insertions(+), 108 deletions(-)
+ create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.c
+ create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.h
+ create mode 100644 drivers/soc/bcm/brcmstb/memory.c
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -68,6 +68,17 @@ struct bcm2835_dma_cb {
+       uint32_t pad[2];
+ };
++struct bcm2838_dma40_scb {
++      uint32_t ti;
++      uint32_t src;
++      uint32_t srci;
++      uint32_t dst;
++      uint32_t dsti;
++      uint32_t len;
++      uint32_t next_cb;
++      uint32_t rsvd;
++};
++
+ struct bcm2835_cb_entry {
+       struct bcm2835_dma_cb *cb;
+       dma_addr_t paddr;
+@@ -185,6 +196,45 @@ struct bcm2835_desc {
+ #define MAX_DMA_LEN SZ_1G
+ #define MAX_LITE_DMA_LEN (SZ_64K - 4)
++/* 40-bit DMA support */
++#define BCM2838_DMA40_CS      0x00
++#define BCM2838_DMA40_CB      0x04
++#define BCM2838_DMA40_DEBUG   0x0c
++#define BCM2858_DMA40_TI      0x10
++#define BCM2838_DMA40_SRC     0x14
++#define BCM2838_DMA40_SRCI    0x18
++#define BCM2838_DMA40_DEST    0x1c
++#define BCM2838_DMA40_DESTI   0x20
++#define BCM2838_DMA40_LEN     0x24
++#define BCM2838_DMA40_NEXT_CB 0x28
++#define BCM2838_DMA40_DEBUG2  0x2c
++
++#define BCM2838_DMA40_CS_ACTIVE       BIT(0)
++#define BCM2838_DMA40_CS_END  BIT(1)
++
++#define BCM2838_DMA40_CS_QOS(x)       (((x) & 0x1f) << 16)
++#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
++#define BCM2838_DMA40_CS_WRITE_WAIT   BIT(28)
++
++#define BCM2838_DMA40_BURST_LEN(x)    ((((x) - 1) & 0xf) << 8)
++#define BCM2838_DMA40_INC             BIT(12)
++#define BCM2838_DMA40_SIZE_128        (2 << 13)
++
++#define BCM2838_DMA40_MEMCPY_QOS \
++      (BCM2838_DMA40_CS_QOS(0x0) | \
++       BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
++       BCM2838_DMA40_CS_WRITE_WAIT)
++
++#define BCM2838_DMA40_MEMCPY_XFER_INFO \
++      (BCM2838_DMA40_SIZE_128 | \
++       BCM2838_DMA40_INC | \
++       BCM2838_DMA40_BURST_LEN(16))
++
++static void __iomem *memcpy_chan;
++static struct bcm2838_dma40_scb *memcpy_scb;
++static dma_addr_t memcpy_scb_dma;
++DEFINE_SPINLOCK(memcpy_lock);
++
+ static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
+ {
+       /* lite and normal channels have different max frame length */
+@@ -868,6 +918,56 @@ static void bcm2835_dma_free(struct bcm2
+       }
+ }
++int bcm2838_dma40_memcpy_init(struct device *dev)
++{
++      if (memcpy_scb)
++              return 0;
++
++      memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
++                                      &memcpy_scb_dma, GFP_KERNEL);
++
++      if (!memcpy_scb) {
++              pr_err("bcm2838_dma40_memcpy_init failed!\n");
++              return -ENOMEM;
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL(bcm2838_dma40_memcpy_init);
++
++void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size)
++{
++      struct bcm2838_dma40_scb *scb = memcpy_scb;
++      unsigned long flags;
++
++      if (!scb) {
++              pr_err("bcm2838_dma40_memcpy not initialised!\n");
++              return;
++      }
++
++      spin_lock_irqsave(&memcpy_lock, flags);
++
++      scb->ti = 0;
++      scb->src = lower_32_bits(src);
++      scb->srci = upper_32_bits(src) | BCM2838_DMA40_MEMCPY_XFER_INFO;
++      scb->dst = lower_32_bits(dst);
++      scb->dsti = upper_32_bits(dst) | BCM2838_DMA40_MEMCPY_XFER_INFO;
++      scb->len = size;
++      scb->next_cb = 0;
++
++      writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
++      writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
++             memcpy_chan + BCM2838_DMA40_CS);
++      /* Poll for completion */
++      while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
++              cpu_relax();
++
++      writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
++
++      spin_unlock_irqrestore(&memcpy_lock, flags);
++}
++EXPORT_SYMBOL(bcm2838_dma40_memcpy);
++
+ static const struct of_device_id bcm2835_dma_of_match[] = {
+       { .compatible = "brcm,bcm2835-dma", },
+       {},
+@@ -966,6 +1066,13 @@ static int bcm2835_dma_probe(struct plat
+       /* Channel 0 is used by the legacy API */
+       chans_available &= ~BCM2835_DMA_BULK_MASK;
++      /* We can't use channels 11-13 yet */
++      chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
++
++      /* Grab channel 14 for the 40-bit DMA memcpy */
++      chans_available &= ~BIT(14);
++      memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
++
+       /* get irqs for each channel that we support */
+       for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
+               /* skip masked out channels */
+--- a/drivers/pci/controller/Makefile
++++ b/drivers/pci/controller/Makefile
+@@ -29,6 +29,10 @@ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-medi
+ obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
+ obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
+ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
++ifdef CONFIG_ARM
++obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
++endif
++
+ obj-$(CONFIG_VMD) += vmd.o
+ # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+ obj-y                         += dwc/
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
+@@ -0,0 +1,564 @@
++/*
++ *  This code started out as a version of arch/arm/common/dmabounce.c,
++ *  modified to cope with highmem pages. Now it has been changed heavily -
++ *  it now preallocates a large block (currently 4MB) and carves it up
++ *  sequentially in ring fashion, and DMA is used to copy the data - to the
++ *  point where very little of the original remains.
++ *
++ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
++ *
++ *  Original version by Brad Parker (brad@heeltoe.com)
++ *  Re-written by Christopher Hoover <ch@murgatroid.com>
++ *  Made generic by Deepak Saxena <dsaxena@plexity.net>
++ *
++ *  Copyright (C) 2002 Hewlett Packard Company.
++ *  Copyright (C) 2004 MontaVista Software, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or
++ *  modify it under the terms of the GNU General Public License
++ *  version 2 as published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/page-flags.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmapool.h>
++#include <linux/list.h>
++#include <linux/scatterlist.h>
++#include <linux/bitmap.h>
++
++#include <asm/cacheflush.h>
++#include <asm/dma-iommu.h>
++
++#define STATS
++
++#ifdef STATS
++#define DO_STATS(X) do { X ; } while (0)
++#else
++#define DO_STATS(X) do { } while (0)
++#endif
++
++/* ************************************************** */
++
++struct safe_buffer {
++      struct list_head node;
++
++      /* original request */
++      size_t          size;
++      int             direction;
++
++      struct dmabounce_pool *pool;
++      void            *safe;
++      dma_addr_t      unsafe_dma_addr;
++      dma_addr_t      safe_dma_addr;
++};
++
++struct dmabounce_pool {
++      unsigned long   pages;
++      void            *virt_addr;
++      dma_addr_t      dma_addr;
++      unsigned long   *alloc_map;
++      unsigned long   alloc_pos;
++      spinlock_t      lock;
++      struct device   *dev;
++      unsigned long   num_pages;
++#ifdef STATS
++      size_t          max_size;
++      unsigned long   num_bufs;
++      unsigned long   max_bufs;
++      unsigned long   max_pages;
++#endif
++};
++
++struct dmabounce_device_info {
++      struct device *dev;
++      dma_addr_t threshold;
++      struct list_head safe_buffers;
++      struct dmabounce_pool pool;
++      rwlock_t lock;
++#ifdef STATS
++      unsigned long map_count;
++      unsigned long unmap_count;
++      unsigned long sync_dev_count;
++      unsigned long sync_cpu_count;
++      unsigned long fail_count;
++      int attr_res;
++#endif
++};
++
++static struct dmabounce_device_info *g_dmabounce_device_info;
++
++extern int bcm2838_dma40_memcpy_init(struct device *dev);
++extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
++
++#ifdef STATS
++static ssize_t
++bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++      return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
++              device_info->map_count,
++              device_info->unmap_count,
++              device_info->sync_dev_count,
++              device_info->sync_cpu_count,
++              device_info->fail_count,
++              device_info->pool.max_size,
++              device_info->pool.num_bufs,
++              device_info->pool.max_bufs,
++              device_info->pool.num_pages * PAGE_SIZE,
++              device_info->pool.max_pages * PAGE_SIZE);
++}
++
++static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
++#endif
++
++static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
++                       unsigned long buffer_size)
++{
++      int ret = -ENOMEM;
++      pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
++      pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
++      if (!pool->alloc_map)
++              goto err_bitmap;
++      pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
++                                           &pool->dma_addr, GFP_KERNEL);
++      if (!pool->virt_addr)
++              goto err_dmabuf;
++
++      pool->alloc_pos = 0;
++      spin_lock_init(&pool->lock);
++      pool->dev = dev;
++      pool->num_pages = 0;
++
++      DO_STATS(pool->max_size = 0);
++      DO_STATS(pool->num_bufs = 0);
++      DO_STATS(pool->max_bufs = 0);
++      DO_STATS(pool->max_pages = 0);
++
++      return  0;
++
++err_dmabuf:
++      bitmap_free(pool->alloc_map);
++err_bitmap:
++      return ret;
++}
++
++static void bounce_destroy(struct dmabounce_pool *pool)
++{
++      dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
++                        pool->dma_addr);
++
++      bitmap_free(pool->alloc_map);
++}
++
++static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
++                        dma_addr_t *dmaaddrp)
++{
++      unsigned long pages;
++      unsigned long flags;
++      unsigned long pos;
++
++      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
++
++      DO_STATS(pool->max_size = max(size, pool->max_size));
++
++      spin_lock_irqsave(&pool->lock, flags);
++      pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
++                                       pool->alloc_pos, pages, 0);
++      /* If not found, try from the start */
++      if (pos >= pool->pages && pool->alloc_pos)
++              pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
++                                               0, pages, 0);
++
++      if (pos >= pool->pages) {
++              spin_unlock_irqrestore(&pool->lock, flags);
++              return NULL;
++      }
++
++      bitmap_set(pool->alloc_map, pos, pages);
++      pool->alloc_pos = (pos + pages) % pool->pages;
++      pool->num_pages += pages;
++
++      DO_STATS(pool->num_bufs++);
++      DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
++      DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
++
++      spin_unlock_irqrestore(&pool->lock, flags);
++
++      *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
++
++      return pool->virt_addr + pos * PAGE_SIZE;
++}
++
++static void
++bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
++{
++      unsigned long pages;
++      unsigned long flags;
++      unsigned long pos;
++
++      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
++      pos = (buf - pool->virt_addr)/PAGE_SIZE;
++
++      BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
++
++      spin_lock_irqsave(&pool->lock, flags);
++      bitmap_clear(pool->alloc_map, pos, pages);
++      pool->num_pages -= pages;
++      if (pool->num_pages == 0)
++              pool->alloc_pos = 0;
++      DO_STATS(pool->num_bufs--);
++      spin_unlock_irqrestore(&pool->lock, flags);
++}
++
++/* allocate a 'safe' buffer and keep track of it */
++static struct safe_buffer *
++alloc_safe_buffer(struct dmabounce_device_info *device_info,
++                dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
++{
++      struct safe_buffer *buf;
++      struct dmabounce_pool *pool = &device_info->pool;
++      struct device *dev = device_info->dev;
++      unsigned long flags;
++
++      /*
++       * Although one might expect this to be called in thread context,
++       * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
++       * was previously used to select the appropriate allocation mode,
++       * but this is unsafe.
++       */
++      buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
++      if (!buf) {
++              dev_warn(dev, "%s: kmalloc failed\n", __func__);
++              return NULL;
++      }
++
++      buf->unsafe_dma_addr = dma_addr;
++      buf->size = size;
++      buf->direction = dir;
++      buf->pool = pool;
++
++      buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
++
++      if (!buf->safe) {
++              dev_warn(dev,
++                       "%s: could not alloc dma memory (size=%d)\n",
++                       __func__, size);
++              kfree(buf);
++              return NULL;
++      }
++
++      write_lock_irqsave(&device_info->lock, flags);
++      list_add(&buf->node, &device_info->safe_buffers);
++      write_unlock_irqrestore(&device_info->lock, flags);
++
++      return buf;
++}
++
++/* determine if a buffer is from our "safe" pool */
++static struct safe_buffer *
++find_safe_buffer(struct dmabounce_device_info *device_info,
++               dma_addr_t safe_dma_addr)
++{
++      struct safe_buffer *b, *rb = NULL;
++      unsigned long flags;
++
++      read_lock_irqsave(&device_info->lock, flags);
++
++      list_for_each_entry(b, &device_info->safe_buffers, node)
++              if (b->safe_dma_addr <= safe_dma_addr &&
++                  b->safe_dma_addr + b->size > safe_dma_addr) {
++                      rb = b;
++                      break;
++              }
++
++      read_unlock_irqrestore(&device_info->lock, flags);
++      return rb;
++}
++
++static void
++free_safe_buffer(struct dmabounce_device_info *device_info,
++               struct safe_buffer *buf)
++{
++      unsigned long flags;
++
++      write_lock_irqsave(&device_info->lock, flags);
++      list_del(&buf->node);
++      write_unlock_irqrestore(&device_info->lock, flags);
++
++      bounce_free(buf->pool, buf->safe, buf->size);
++
++      kfree(buf);
++}
++
++/* ************************************************** */
++
++static struct safe_buffer *
++find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
++{
++      if (!dev || !g_dmabounce_device_info)
++              return NULL;
++      if (dma_mapping_error(dev, dma_addr)) {
++              dev_err(dev, "Trying to %s invalid mapping\n", where);
++              return NULL;
++      }
++      return find_safe_buffer(g_dmabounce_device_info, dma_addr);
++}
++
++static dma_addr_t
++map_single(struct device *dev, struct safe_buffer *buf, size_t size,
++         enum dma_data_direction dir, unsigned long attrs)
++{
++      BUG_ON(buf->size != size);
++      BUG_ON(buf->direction != dir);
++
++      dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
++              (u64)buf->safe_dma_addr);
++
++      if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
++          !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
++              bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
++                                   size);
++
++      return buf->safe_dma_addr;
++}
++
++static dma_addr_t
++unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
++           enum dma_data_direction dir, unsigned long attrs)
++{
++      BUG_ON(buf->size != size);
++      BUG_ON(buf->direction != dir);
++
++      if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
++          !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
++              dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
++                      (u64)buf->unsafe_dma_addr);
++
++              bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
++                                   size);
++      }
++      return buf->unsafe_dma_addr;
++}
++
++/* ************************************************** */
++
++/*
++ * see if a buffer address is in an 'unsafe' range.  if it is
++ * allocate a 'safe' buffer and copy the unsafe buffer into it.
++ * substitute the safe buffer for the unsafe one.
++ * (basically move the buffer from an unsafe area to a safe one)
++ */
++static dma_addr_t
++dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
++                 size_t size, enum dma_data_direction dir,
++                 unsigned long attrs)
++{
++      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++      dma_addr_t dma_addr;
++
++      dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
++
++      arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
++
++      if (device_info && (dma_addr + size) > device_info->threshold) {
++              struct safe_buffer *buf;
++
++              buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
++              if (!buf) {
++                      DO_STATS(device_info->fail_count++);
++                      return ARM_MAPPING_ERROR;
++              }
++
++              DO_STATS(device_info->map_count++);
++
++              dma_addr = map_single(dev, buf, size, dir, attrs);
++      }
++
++      return dma_addr;
++}
++
++/*
++ * see if a mapped address was really a "safe" buffer and if so, copy
++ * the data from the safe buffer back to the unsafe buffer and free up
++ * the safe buffer.  (basically return things back to the way they
++ * should be)
++ */
++static void
++dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
++                   enum dma_data_direction dir, unsigned long attrs)
++{
++      struct safe_buffer *buf;
++
++      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++      if (buf) {
++              DO_STATS(g_dmabounce_device_info->unmap_count++);
++              dma_addr = unmap_single(dev, buf, size, dir, attrs);
++              free_safe_buffer(g_dmabounce_device_info, buf);
++      }
++
++      arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
++}
++
++/*
++ * A version of dmabounce_map_page that assumes the mapping has already
++ * been created - intended for streaming operation.
++ */
++static void
++dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
++                        enum dma_data_direction dir)
++{
++      struct safe_buffer *buf;
++
++      arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
++
++      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++      if (buf) {
++              DO_STATS(g_dmabounce_device_info->sync_dev_count++);
++              map_single(dev, buf, size, dir, 0);
++      }
++}
++
++/*
++ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
++ * intended for streaming operation.
++ */
++static void
++dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
++                     size_t size, enum dma_data_direction dir)
++{
++      struct safe_buffer *buf;
++
++      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++      if (buf) {
++              DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
++              dma_addr = unmap_single(dev, buf, size, dir, 0);
++      }
++
++      arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
++}
++
++static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
++{
++      if (g_dmabounce_device_info)
++              return 0;
++
++      return arm_dma_ops.dma_supported(dev, dma_mask);
++}
++
++static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++      return arm_dma_ops.mapping_error(dev, dma_addr);
++}
++
++static const struct dma_map_ops dmabounce_ops = {
++      .alloc                  = arm_dma_alloc,
++      .free                   = arm_dma_free,
++      .mmap                   = arm_dma_mmap,
++      .get_sgtable            = arm_dma_get_sgtable,
++      .map_page               = dmabounce_map_page,
++      .unmap_page             = dmabounce_unmap_page,
++      .sync_single_for_cpu    = dmabounce_sync_for_cpu,
++      .sync_single_for_device = dmabounce_sync_for_device,
++      .map_sg                 = arm_dma_map_sg,
++      .unmap_sg               = arm_dma_unmap_sg,
++      .sync_sg_for_cpu        = arm_dma_sync_sg_for_cpu,
++      .sync_sg_for_device     = arm_dma_sync_sg_for_device,
++      .dma_supported          = dmabounce_dma_supported,
++      .mapping_error          = dmabounce_mapping_error,
++};
++
++int brcm_pcie_bounce_register_dev(struct device *dev,
++                                unsigned long buffer_size,
++                                dma_addr_t threshold)
++{
++      struct dmabounce_device_info *device_info;
++      int ret;
++
++      /* Only support a single client */
++      if (g_dmabounce_device_info)
++              return -EBUSY;
++
++      ret = bcm2838_dma40_memcpy_init(dev);
++      if (ret)
++          return ret;
++
++      device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
++      if (!device_info) {
++              dev_err(dev,
++                      "Could not allocated dmabounce_device_info\n");
++              return -ENOMEM;
++      }
++
++      ret = bounce_create(&device_info->pool, dev, buffer_size);
++      if (ret) {
++              dev_err(dev,
++                      "dmabounce: could not allocate %ld byte DMA pool\n",
++                      buffer_size);
++              goto err_bounce;
++      }
++
++      device_info->dev = dev;
++      device_info->threshold = threshold;
++      INIT_LIST_HEAD(&device_info->safe_buffers);
++      rwlock_init(&device_info->lock);
++
++      DO_STATS(device_info->map_count = 0);
++      DO_STATS(device_info->unmap_count = 0);
++      DO_STATS(device_info->sync_dev_count = 0);
++      DO_STATS(device_info->sync_cpu_count = 0);
++      DO_STATS(device_info->fail_count = 0);
++      DO_STATS(device_info->attr_res =
++               device_create_file(dev, &dev_attr_dmabounce_stats));
++
++      g_dmabounce_device_info = device_info;
++      set_dma_ops(dev, &dmabounce_ops);
++
++      dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
++               buffer_size / 1024, &threshold);
++
++      return 0;
++
++ err_bounce:
++      kfree(device_info);
++      return ret;
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
++
++void brcm_pcie_bounce_unregister_dev(struct device *dev)
++{
++      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++
++      g_dmabounce_device_info = NULL;
++      set_dma_ops(dev, NULL);
++
++      if (!device_info) {
++              dev_warn(dev,
++                       "Never registered with dmabounce but attempting"
++                       "to unregister!\n");
++              return;
++      }
++
++      if (!list_empty(&device_info->safe_buffers)) {
++              dev_err(dev,
++                      "Removing from dmabounce with pending buffers!\n");
++              BUG();
++      }
++
++      bounce_destroy(&device_info->pool);
++
++      DO_STATS(if (device_info->attr_res == 0)
++                       device_remove_file(dev, &dev_attr_dmabounce_stats));
++
++      kfree(device_info);
++
++      dev_info(dev, "dmabounce: device unregistered\n");
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
++
++MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
++MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
++ */
++
++#ifndef _PCIE_BRCMSTB_BOUNCE_H
++#define _PCIE_BRCMSTB_BOUNCE_H
++
++#ifdef CONFIG_ARM
++
++int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
++                                dma_addr_t threshold);
++
++int brcm_pcie_bounce_unregister_dev(struct device *dev);
++
++#else
++
++static inline int brcm_pcie_bounce_register_dev(struct device *dev,
++                                              unsigned long buffer_size,
++                                              dma_addr_t threshold)
++{
++      return 0;
++}
++
++static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
++{
++      return 0;
++}
++
++#endif
++
++#endif /* _PCIE_BRCMSTB_BOUNCE_H */
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -29,6 +29,7 @@
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include "../pci.h"
++#include "pcie-brcmstb-bounce.h"
+ /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
+ #define BRCM_PCIE_CAP_REGS                            0x00ac
+@@ -53,6 +54,7 @@
+ #define PCIE_MISC_MSI_BAR_CONFIG_LO                   0x4044
+ #define PCIE_MISC_MSI_BAR_CONFIG_HI                   0x4048
+ #define PCIE_MISC_MSI_DATA_CONFIG                     0x404c
++#define PCIE_MISC_EOI_CTRL                            0x4060
+ #define PCIE_MISC_PCIE_CTRL                           0x4064
+ #define PCIE_MISC_PCIE_STATUS                         0x4068
+ #define PCIE_MISC_REVISION                            0x406c
+@@ -260,12 +262,14 @@ struct brcm_pcie {
+       unsigned int            rev;
+       const int               *reg_offsets;
+       const int               *reg_field_info;
++      u32                     max_burst_size;
+       enum pcie_type          type;
+ };
+ struct pcie_cfg_data {
+       const int               *reg_field_info;
+       const int               *offsets;
++      const u32               max_burst_size;
+       const enum pcie_type    type;
+ };
+@@ -288,24 +292,27 @@ static const int pcie_offset_bcm7425[] =
+ static const struct pcie_cfg_data bcm7425_cfg = {
+       .reg_field_info = pcie_reg_field_info,
+       .offsets        = pcie_offset_bcm7425,
++      .max_burst_size = BURST_SIZE_256,
+       .type           = BCM7425,
+ };
+ static const int pcie_offsets[] = {
+       [RGR1_SW_INIT_1] = 0x9210,
+       [EXT_CFG_INDEX]  = 0x9000,
+-      [EXT_CFG_DATA]   = 0x9004,
++      [EXT_CFG_DATA]   = 0x8000,
+ };
+ static const struct pcie_cfg_data bcm7435_cfg = {
+       .reg_field_info = pcie_reg_field_info,
+       .offsets        = pcie_offsets,
++      .max_burst_size = BURST_SIZE_256,
+       .type           = BCM7435,
+ };
+ static const struct pcie_cfg_data generic_cfg = {
+       .reg_field_info = pcie_reg_field_info,
+       .offsets        = pcie_offsets,
++      .max_burst_size = BURST_SIZE_128, // before BURST_SIZE_512
+       .type           = GENERIC,
+ };
+@@ -318,6 +325,7 @@ static const int pcie_offset_bcm7278[] =
+ static const struct pcie_cfg_data bcm7278_cfg = {
+       .reg_field_info = pcie_reg_field_info_bcm7278,
+       .offsets        = pcie_offset_bcm7278,
++      .max_burst_size = BURST_SIZE_512,
+       .type           = BCM7278,
+ };
+@@ -360,7 +368,6 @@ static struct pci_ops brcm_pcie_ops = {
+        (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
+ static const struct dma_map_ops *arch_dma_ops;
+-static const struct dma_map_ops *brcm_dma_ops_ptr;
+ static struct of_pci_range *dma_ranges;
+ static int num_dma_ranges;
+@@ -369,6 +376,16 @@ static int num_memc;
+ static int num_pcie;
+ static DEFINE_MUTEX(brcm_pcie_lock);
++static unsigned int bounce_buffer = 32*1024*1024;
++module_param(bounce_buffer, uint, 0644);
++MODULE_PARM_DESC(bounce_buffer, "Size of bounce buffer");
++
++static unsigned int bounce_threshold = 0xc0000000;
++module_param(bounce_threshold, uint, 0644);
++MODULE_PARM_DESC(bounce_threshold, "Bounce threshold");
++
++static struct brcm_pcie *g_pcie;
++
+ static dma_addr_t brcm_to_pci(dma_addr_t addr)
+ {
+       struct of_pci_range *p;
+@@ -457,12 +474,10 @@ static int brcm_map_sg(struct device *de
+       struct scatterlist *sg;
+       for_each_sg(sgl, sg, nents, i) {
+-#ifdef CONFIG_NEED_SG_DMA_LENGTH
+-              sg->dma_length = sg->length;
+-#endif
++              sg_dma_len(sg) = sg->length;
+               sg->dma_address =
+-                      brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
+-                                                 sg->length, dir, attrs);
++                      brcm_map_page(dev, sg_page(sg), sg->offset,
++                                    sg->length, dir, attrs);
+               if (dma_mapping_error(dev, sg->dma_address))
+                       goto bad_mapping;
+       }
+@@ -470,8 +485,8 @@ static int brcm_map_sg(struct device *de
+ bad_mapping:
+       for_each_sg(sgl, sg, i, j)
+-              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
+-                                           sg_dma_len(sg), dir, attrs);
++              brcm_unmap_page(dev, sg_dma_address(sg),
++                              sg_dma_len(sg), dir, attrs);
+       return 0;
+ }
+@@ -484,8 +499,8 @@ static void brcm_unmap_sg(struct device
+       struct scatterlist *sg;
+       for_each_sg(sgl, sg, nents, i)
+-              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
+-                                           sg_dma_len(sg), dir, attrs);
++              brcm_unmap_page(dev, sg_dma_address(sg),
++                              sg_dma_len(sg), dir, attrs);
+ }
+ static void brcm_sync_single_for_cpu(struct device *dev,
+@@ -531,8 +546,8 @@ void brcm_sync_sg_for_cpu(struct device
+       int i;
+       for_each_sg(sgl, sg, nents, i)
+-              brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
+-                                                    sg->length, dir);
++              brcm_sync_single_for_cpu(dev, sg_dma_address(sg),
++                                       sg->length, dir);
+ }
+ void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
+@@ -542,9 +557,9 @@ void brcm_sync_sg_for_device(struct devi
+       int i;
+       for_each_sg(sgl, sg, nents, i)
+-              brcm_dma_ops_ptr->sync_single_for_device(dev,
+-                                                       sg_dma_address(sg),
+-                                                       sg->length, dir);
++              brcm_sync_single_for_device(dev,
++                                          sg_dma_address(sg),
++                                          sg->length, dir);
+ }
+ static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
+@@ -633,17 +648,47 @@ static void brcm_set_dma_ops(struct devi
+       set_dma_ops(dev, &brcm_dma_ops);
+ }
++static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
++                                     unsigned int val);
+ static int brcmstb_platform_notifier(struct notifier_block *nb,
+                                    unsigned long event, void *__dev)
+ {
++      extern unsigned long max_pfn;
+       struct device *dev = __dev;
++      const char *rc_name = "0000:00:00.0";
+-      brcm_dma_ops_ptr = &brcm_dma_ops;
+-      if (event != BUS_NOTIFY_ADD_DEVICE)
+-              return NOTIFY_DONE;
++      switch (event) {
++      case BUS_NOTIFY_ADD_DEVICE:
++              if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
++                  strcmp(dev->kobj.name, rc_name)) {
++                      int ret;
++
++                      ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
++                                                          (dma_addr_t)bounce_threshold);
++                      if (ret) {
++                              dev_err(dev,
++                                      "brcm_pcie_bounce_register_dev() failed: %d\n",
++                              ret);
++                              return ret;
++                      }
++              }
++              brcm_set_dma_ops(dev);
++              return NOTIFY_OK;
++
++      case BUS_NOTIFY_DEL_DEVICE:
++              if (!strcmp(dev->kobj.name, rc_name) && g_pcie) {
++                      /* Force a bus reset */
++                      brcm_pcie_perst_set(g_pcie, 1);
++                      msleep(100);
++                      brcm_pcie_perst_set(g_pcie, 0);
++              } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
++                      brcm_pcie_bounce_unregister_dev(dev);
++              }
++              return NOTIFY_OK;
+-      brcm_set_dma_ops(dev);
+-      return NOTIFY_OK;
++      default:
++              return NOTIFY_DONE;
++      }
+ }
+ static struct notifier_block brcmstb_platform_nb = {
+@@ -914,6 +959,7 @@ static void brcm_pcie_msi_isr(struct irq
+               }
+       }
+       chained_irq_exit(chip, desc);
++      bcm_writel(1, msi->base + PCIE_MISC_EOI_CTRL);
+ }
+ static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+@@ -930,7 +976,8 @@ static void brcm_compose_msi_msg(struct
+ static int brcm_msi_set_affinity(struct irq_data *irq_data,
+                                const struct cpumask *mask, bool force)
+ {
+-      return -EINVAL;
++      struct brcm_msi *msi = irq_data_get_irq_chip_data(irq_data);
++      return __irq_set_affinity(msi->irq, mask, force);
+ }
+ static struct irq_chip brcm_msi_bottom_irq_chip = {
+@@ -1168,9 +1215,9 @@ static void __iomem *brcm_pcie_map_conf(
+               return PCI_SLOT(devfn) ? NULL : base + where;
+       /* For devices, write to the config space index register */
+-      idx = cfg_index(bus->number, devfn, where);
++      idx = cfg_index(bus->number, devfn, 0);
+       bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
+-      return base + DATA_ADDR(pcie) + (where & 0x3);
++      return base + DATA_ADDR(pcie) + where;
+ }
+ static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
+@@ -1238,20 +1285,6 @@ static int brcm_pcie_parse_map_dma_range
+                       num_dma_ranges++;
+       }
+-      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
+-              u64 size = brcmstb_memory_memc_size(i);
+-
+-              if (size == (u64)-1) {
+-                      dev_err(pcie->dev, "cannot get memc%d size", i);
+-                      return -EINVAL;
+-              } else if (size) {
+-                      scb_size[i] = roundup_pow_of_two_64(size);
+-                      num_memc++;
+-              } else {
+-                      break;
+-              }
+-      }
+-
+       return 0;
+ }
+@@ -1275,26 +1308,25 @@ static int brcm_pcie_add_controller(stru
+       if (ret)
+               goto done;
+-      /* Determine num_memc and their sizes */
+-      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
+-              u64 size = brcmstb_memory_memc_size(i);
+-
+-              if (size == (u64)-1) {
+-                      dev_err(dev, "cannot get memc%d size\n", i);
+-                      ret = -EINVAL;
+-                      goto done;
+-              } else if (size) {
+-                      scb_size[i] = roundup_pow_of_two_64(size);
+-                      num_memc++;
+-              } else {
+-                      break;
++      if (!num_dma_ranges) {
++              /* Determine num_memc and their sizes by other means */
++              for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
++                      u64 size = brcmstb_memory_memc_size(i);
++
++                      if (size == (u64)-1) {
++                              dev_err(dev, "cannot get memc%d size\n", i);
++                              ret = -EINVAL;
++                              goto done;
++                      } else if (size) {
++                              scb_size[i] = roundup_pow_of_two_64(size);
++                      } else {
++                              break;
++                      }
+               }
+-      }
+-      if (!ret && num_memc == 0) {
+-              ret = -EINVAL;
+-              goto done;
++              num_memc = i;
+       }
++      g_pcie = pcie;
+       num_pcie++;
+ done:
+       mutex_unlock(&brcm_pcie_lock);
+@@ -1307,6 +1339,7 @@ static void brcm_pcie_remove_controller(
+       if (--num_pcie > 0)
+               goto out;
++      g_pcie = NULL;
+       if (brcm_unregister_notifier())
+               dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
+       kfree(dma_ranges);
+@@ -1367,7 +1400,7 @@ static int brcm_pcie_setup(struct brcm_p
+       void __iomem *base = pcie->base;
+       unsigned int scb_size_val;
+       u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
+-      u32 tmp, burst;
++      u32 tmp;
+       int i, j, ret, limit;
+       u16 nlw, cls, lnksta;
+       bool ssc_good = false;
+@@ -1400,20 +1433,15 @@ static int brcm_pcie_setup(struct brcm_p
+       /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
+       tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
+       tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
+-      burst = (pcie->type == GENERIC || pcie->type == BCM7278)
+-              ? BURST_SIZE_512 : BURST_SIZE_256;
+-      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
++      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE,
++                         pcie->max_burst_size);
+       bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
+       /*
+        * Set up inbound memory view for the EP (called RC_BAR2,
+        * not to be confused with the BARs that are advertised by
+        * the EP).
+-       */
+-      for (i = 0; i < num_memc; i++)
+-              total_mem_size += scb_size[i];
+-
+-      /*
++       *
+        * The PCIe host controller by design must set the inbound
+        * viewport to be a contiguous arrangement of all of the
+        * system's memory.  In addition, its size mut be a power of
+@@ -1429,55 +1457,49 @@ static int brcm_pcie_setup(struct brcm_p
+        * the controller will know to send outbound memory downstream
+        * and everything else upstream.
+        */
+-      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
+-      if (dma_ranges) {
++      if (num_dma_ranges) {
+               /*
+-               * The best-case scenario is to place the inbound
+-               * region in the first 4GB of pcie-space, as some
+-               * legacy devices can only address 32bits.
+-               * We would also like to put the MSI under 4GB
+-               * as well, since some devices require a 32bit
+-               * MSI target address.
++               * Use the base address and size(s) provided in the dma-ranges
++               * property.
+                */
+-              if (total_mem_size <= 0xc0000000ULL &&
+-                  rc_bar2_size <= 0x100000000ULL) {
+-                      rc_bar2_offset = 0;
+-                      /* If the viewport is less then 4GB we can fit
+-                       * the MSI target address under 4GB. Otherwise
+-                       * put it right below 64GB.
+-                       */
+-                      msi_target_addr =
+-                              (rc_bar2_size == 0x100000000ULL)
+-                              ? BRCM_MSI_TARGET_ADDR_GT_4GB
+-                              : BRCM_MSI_TARGET_ADDR_LT_4GB;
+-              } else {
+-                      /*
+-                       * The system memory is 4GB or larger so we
+-                       * cannot start the inbound region at location
+-                       * 0 (since we have to allow some space for
+-                       * outbound memory @ 3GB).  So instead we
+-                       * start it at the 1x multiple of its size
+-                       */
+-                      rc_bar2_offset = rc_bar2_size;
+-
+-                      /* Since we are starting the viewport at 4GB or
+-                       * higher, put the MSI target address below 4GB
+-                       */
+-                      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
+-              }
+-      } else {
++              for (i = 0; i < num_dma_ranges; i++)
++                      scb_size[i] = roundup_pow_of_two_64(dma_ranges[i].size);
++
++              num_memc = num_dma_ranges;
++              rc_bar2_offset = dma_ranges[0].pci_addr;
++      } else if (num_memc) {
+               /*
+                * Set simple configuration based on memory sizes
+-               * only.  We always start the viewport at address 0,
+-               * and set the MSI target address accordingly.
++               * only.  We always start the viewport at address 0.
+                */
+               rc_bar2_offset = 0;
++      } else {
++              return -EINVAL;
++      }
++
++      for (i = 0; i < num_memc; i++)
++              total_mem_size += scb_size[i];
++
++      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
+-              msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
+-                      ? BRCM_MSI_TARGET_ADDR_GT_4GB
+-                      : BRCM_MSI_TARGET_ADDR_LT_4GB;
++      /* Verify the alignment is correct */
++      if (rc_bar2_offset & (rc_bar2_size - 1)) {
++              dev_err(dev, "inbound window is misaligned\n");
++              return -EINVAL;
+       }
++
++      /*
++       * Position the MSI target low if possible.
++       *
++       * TO DO: Consider outbound window when choosing MSI target and
++       * verifying configuration.
++       */
++      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
++      if (rc_bar2_offset <= msi_target_addr &&
++          rc_bar2_offset + rc_bar2_size > msi_target_addr)
++              msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
++
+       pcie->msi_target_addr = msi_target_addr;
+       tmp = lower_32_bits(rc_bar2_offset);
+@@ -1713,6 +1735,7 @@ static int brcm_pcie_probe(struct platfo
+       data = of_id->data;
+       pcie->reg_offsets = data->offsets;
+       pcie->reg_field_info = data->reg_field_info;
++      pcie->max_burst_size = data->max_burst_size;
+       pcie->type = data->type;
+       pcie->dn = dn;
+       pcie->dev = &pdev->dev;
+@@ -1732,7 +1755,7 @@ static int brcm_pcie_probe(struct platfo
+       pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
+       if (IS_ERR(pcie->clk)) {
+-              dev_err(&pdev->dev, "could not get clock\n");
++              dev_warn(&pdev->dev, "could not get clock\n");
+               pcie->clk = NULL;
+       }
+       pcie->base = base;
+@@ -1755,7 +1778,8 @@ static int brcm_pcie_probe(struct platfo
+       ret = clk_prepare_enable(pcie->clk);
+       if (ret) {
+-              dev_err(&pdev->dev, "could not enable clock\n");
++              if (ret != -EPROBE_DEFER)
++                      dev_err(&pdev->dev, "could not enable clock\n");
+               return ret;
+       }
+@@ -1818,7 +1842,6 @@ static struct platform_driver brcm_pcie_
+       .remove = brcm_pcie_remove,
+       .driver = {
+               .name = "brcm-pcie",
+-              .owner = THIS_MODULE,
+               .of_match_table = brcm_pcie_match,
+               .pm = &brcm_pcie_pm_ops,
+       },
+--- a/drivers/soc/bcm/brcmstb/Makefile
++++ b/drivers/soc/bcm/brcmstb/Makefile
+@@ -1,2 +1,2 @@
+-obj-y                         += common.o biuctrl.o
++obj-y                         += common.o biuctrl.o memory.o
+ obj-$(CONFIG_BRCMSTB_PM)      += pm/
+--- /dev/null
++++ b/drivers/soc/bcm/brcmstb/memory.c
+@@ -0,0 +1,158 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright © 2015-2017 Broadcom */
++
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/libfdt.h>
++#include <linux/of_address.h>
++#include <linux/of_fdt.h>
++#include <linux/sizes.h>
++#include <soc/brcmstb/memory_api.h>
++
++/* Macro to help extract property data */
++#define DT_PROP_DATA_TO_U32(b, offs) (fdt32_to_cpu(*(u32 *)(b + offs)))
++
++/* Constants used when retrieving memc info */
++#define NUM_BUS_RANGES 10
++#define BUS_RANGE_ULIMIT_SHIFT 4
++#define BUS_RANGE_LLIMIT_SHIFT 4
++#define BUS_RANGE_PA_SHIFT 12
++
++enum {
++      BUSNUM_MCP0 = 0x4,
++      BUSNUM_MCP1 = 0x5,
++      BUSNUM_MCP2 = 0x6,
++};
++
++/*
++ * If the DT nodes are handy, determine which MEMC holds the specified
++ * physical address.
++ */
++#ifdef CONFIG_ARCH_BRCMSTB
++int __brcmstb_memory_phys_addr_to_memc(phys_addr_t pa, void __iomem *base)
++{
++      int memc = -1;
++      int i;
++
++      for (i = 0; i < NUM_BUS_RANGES; i++, base += 8) {
++              const u64 ulimit_raw = readl(base);
++              const u64 llimit_raw = readl(base + 4);
++              const u64 ulimit =
++                      ((ulimit_raw >> BUS_RANGE_ULIMIT_SHIFT)
++                       << BUS_RANGE_PA_SHIFT) | 0xfff;
++              const u64 llimit = (llimit_raw >> BUS_RANGE_LLIMIT_SHIFT)
++                                 << BUS_RANGE_PA_SHIFT;
++              const u32 busnum = (u32)(ulimit_raw & 0xf);
++
++              if (pa >= llimit && pa <= ulimit) {
++                      if (busnum >= BUSNUM_MCP0 && busnum <= BUSNUM_MCP2) {
++                              memc = busnum - BUSNUM_MCP0;
++                              break;
++                      }
++              }
++      }
++
++      return memc;
++}
++
++int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
++{
++      int memc = -1;
++      struct device_node *np;
++      void __iomem *cpubiuctrl;
++
++      np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
++      if (!np)
++              return memc;
++
++      cpubiuctrl = of_iomap(np, 0);
++      if (!cpubiuctrl)
++              goto cleanup;
++
++      memc = __brcmstb_memory_phys_addr_to_memc(pa, cpubiuctrl);
++      iounmap(cpubiuctrl);
++
++cleanup:
++      of_node_put(np);
++
++      return memc;
++}
++
++#elif defined(CONFIG_MIPS)
++int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
++{
++      /* The logic here is fairly simple and hardcoded: if pa <= 0x5000_0000,
++       * then this is MEMC0, else MEMC1.
++       *
++       * For systems with 2GB on MEMC0, MEMC1 starts at 9000_0000, with 1GB
++       * on MEMC0, MEMC1 starts at 6000_0000.
++       */
++      if (pa >= 0x50000000ULL)
++              return 1;
++      else
++              return 0;
++}
++#endif
++
++u64 brcmstb_memory_memc_size(int memc)
++{
++      const void *fdt = initial_boot_params;
++      const int mem_offset = fdt_path_offset(fdt, "/memory");
++      int addr_cells = 1, size_cells = 1;
++      const struct fdt_property *prop;
++      int proplen, cellslen;
++      u64 memc_size = 0;
++      int i;
++
++      /* Get root size and address cells if specified */
++      prop = fdt_get_property(fdt, 0, "#size-cells", &proplen);
++      if (prop)
++              size_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
++
++      prop = fdt_get_property(fdt, 0, "#address-cells", &proplen);
++      if (prop)
++              addr_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
++
++      if (mem_offset < 0)
++              return -1;
++
++      prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
++      cellslen = (int)sizeof(u32) * (addr_cells + size_cells);
++      if ((proplen % cellslen) != 0)
++              return -1;
++
++      for (i = 0; i < proplen / cellslen; ++i) {
++              u64 addr = 0;
++              u64 size = 0;
++              int memc_idx;
++              int j;
++
++              for (j = 0; j < addr_cells; ++j) {
++                      int offset = (cellslen * i) + (sizeof(u32) * j);
++
++                      addr |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
++                              ((addr_cells - j - 1) * 32);
++              }
++              for (j = 0; j < size_cells; ++j) {
++                      int offset = (cellslen * i) +
++                              (sizeof(u32) * (j + addr_cells));
++
++                      size |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
++                              ((size_cells - j - 1) * 32);
++              }
++
++              if ((phys_addr_t)addr != addr) {
++                      pr_err("phys_addr_t is smaller than provided address 0x%llx!\n",
++                             addr);
++                      return -1;
++              }
++
++              memc_idx = brcmstb_memory_phys_addr_to_memc((phys_addr_t)addr);
++              if (memc_idx == memc)
++                      memc_size += size;
++      }
++
++      return memc_size;
++}
++EXPORT_SYMBOL_GPL(brcmstb_memory_memc_size);
++
diff --git a/target/linux/brcm2708/patches-4.19/950-0461-arm-bcm2835-DMA-can-only-address-1GB.patch b/target/linux/brcm2708/patches-4.19/950-0461-arm-bcm2835-DMA-can-only-address-1GB.patch
new file mode 100644 (file)
index 0000000..89919c1
--- /dev/null
@@ -0,0 +1,25 @@
+From 9334afe7293b3a78b7e070a70880b2db7aa98365 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:47:42 +0100
+Subject: [PATCH] arm: bcm2835: DMA can only address 1GB
+
+The legacy peripherals can only address the first gigabyte of RAM, so
+ensure that DMA allocations are restricted to that region.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -123,6 +123,9 @@ static const char * const bcm2835_compat
+ };
+ DT_MACHINE_START(BCM2835, "BCM2835")
++#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
++      .dma_zone_size  = SZ_1G,
++#endif
+       .map_io = bcm2835_map_io,
+       .init_machine = bcm2835_init,
+       .dt_compat = bcm2835_compat,
diff --git a/target/linux/brcm2708/patches-4.19/950-0461-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch b/target/linux/brcm2708/patches-4.19/950-0461-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch
deleted file mode 100644 (file)
index 632e986..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-From cb1acabb459677efbf95c54ce1dc5252be30a018 Mon Sep 17 00:00:00 2001
-From: Jim Quinlan <jim2101024@gmail.com>
-Date: Mon, 15 Jan 2018 18:28:39 -0500
-Subject: [PATCH] dt-bindings: pci: Add DT docs for Brcmstb PCIe device
-
-The DT bindings description of the Brcmstb PCIe device is described.  This
-node can be used by almost all Broadcom settop box chips, using
-ARM, ARM64, or MIPS CPU architectures.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- .../devicetree/bindings/pci/brcmstb-pcie.txt  | 59 +++++++++++++++++++
- 1 file changed, 59 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
-@@ -0,0 +1,59 @@
-+Brcmstb PCIe Host Controller Device Tree Bindings
-+
-+Required Properties:
-+- compatible
-+  "brcm,bcm7425-pcie" -- for 7425 family MIPS-based SOCs.
-+  "brcm,bcm7435-pcie" -- for 7435 family MIPS-based SOCs.
-+  "brcm,bcm7445-pcie" -- for 7445 and later ARM based SOCs (not including
-+      the 7278).
-+  "brcm,bcm7278-pcie"  -- for 7278 family ARM-based SOCs.
-+
-+- reg -- the register start address and length for the PCIe reg block.
-+- interrupts -- two interrupts are specified; the first interrupt is for
-+     the PCI host controller and the second is for MSI if the built-in
-+     MSI controller is to be used.
-+- interrupt-names -- names of the interrupts (above): "pcie" and "msi".
-+- #address-cells -- set to <3>.
-+- #size-cells -- set to <2>.
-+- #interrupt-cells: set to <1>.
-+- interrupt-map-mask and interrupt-map, standard PCI properties to define the
-+     mapping of the PCIe interface to interrupt numbers.
-+- ranges: ranges for the PCI memory and I/O regions.
-+- linux,pci-domain -- should be unique per host controller.
-+
-+Optional Properties:
-+- clocks -- phandle of pcie clock.
-+- clock-names -- set to "sw_pcie" if clocks is used.
-+- dma-ranges -- Specifies the inbound memory mapping regions when
-+     an "identity map" is not possible.
-+- msi-controller -- this property is typically specified to have the
-+     PCIe controller use its internal MSI controller.
-+- msi-parent -- set to use an external MSI interrupt controller.
-+- brcm,enable-ssc -- (boolean) indicates usage of spread-spectrum clocking.
-+- max-link-speed --  (integer) indicates desired generation of link:
-+     1 => 2.5 Gbps (gen1), 2 => 5.0 Gbps (gen2), 3 => 8.0 Gbps (gen3).
-+
-+Example Node:
-+
-+pcie0: pcie@f0460000 {
-+              reg = <0x0 0xf0460000 0x0 0x9310>;
-+              interrupts = <0x0 0x0 0x4>;
-+              compatible = "brcm,bcm7445-pcie";
-+              #address-cells = <3>;
-+              #size-cells = <2>;
-+              ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000
-+                        0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
-+              #interrupt-cells = <1>;
-+              interrupt-map-mask = <0 0 0 7>;
-+              interrupt-map = <0 0 0 1 &intc 0 47 3
-+                               0 0 0 2 &intc 0 48 3
-+                               0 0 0 3 &intc 0 49 3
-+                               0 0 0 4 &intc 0 50 3>;
-+              clocks = <&sw_pcie0>;
-+              clock-names = "sw_pcie";
-+              msi-parent = <&pcie0>;  /* use PCIe's internal MSI controller */
-+              msi-controller;         /* use PCIe's internal MSI controller */
-+              brcm,ssc;
-+              max-link-speed = <1>;
-+              linux,pci-domain = <0>;
-+      };
diff --git a/target/linux/brcm2708/patches-4.19/950-0462-mmc-bcm2835-sdhost-Support-64-bit-physical-addresses.patch b/target/linux/brcm2708/patches-4.19/950-0462-mmc-bcm2835-sdhost-Support-64-bit-physical-addresses.patch
new file mode 100644 (file)
index 0000000..a2aeeea
--- /dev/null
@@ -0,0 +1,56 @@
+From 8a58288d710a817b5dc7747f0bec1fb167368e7e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 Aug 2018 09:05:15 +0100
+Subject: [PATCH] mmc: bcm2835-sdhost: Support 64-bit physical
+ addresses
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/bcm2835-sdhost.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/mmc/host/bcm2835-sdhost.c
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -148,7 +148,7 @@ struct bcm2835_host {
+       spinlock_t              lock;
+       void __iomem            *ioaddr;
+-      u32                     bus_addr;
++      phys_addr_t             bus_addr;
+       struct mmc_host         *mmc;
+@@ -246,8 +246,8 @@ static void log_init(struct device *dev,
+       sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr,
+                                            GFP_KERNEL);
+       if (sdhost_log_buf) {
+-              pr_info("sdhost: log_buf @ %p (%x)\n",
+-                      sdhost_log_buf, (u32)sdhost_log_addr);
++              pr_info("sdhost: log_buf @ %p (%llx)\n",
++                      sdhost_log_buf, (u64)sdhost_log_addr);
+               timer_base = ioremap_nocache(bus_to_phys + 0x7e003000, SZ_4K);
+               if (!timer_base)
+                       pr_err("sdhost: failed to remap timer\n");
+@@ -2024,6 +2024,7 @@ static int bcm2835_sdhost_probe(struct p
+       struct mmc_host *mmc;
+       const __be32 *addr;
+       u32 msg[3];
++      int na;
+       int ret;
+       pr_debug("bcm2835_sdhost_probe\n");
+@@ -2047,12 +2048,13 @@ static int bcm2835_sdhost_probe(struct p
+               goto err;
+       }
++      na = of_n_addr_cells(node);
+       addr = of_get_address(node, 0, NULL, NULL);
+       if (!addr) {
+               dev_err(dev, "could not get DMA-register address\n");
+               return -ENODEV;
+       }
+-      host->bus_addr = be32_to_cpup(addr);
++      host->bus_addr = (phys_addr_t)of_read_number(addr, na);
+       pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
+                (unsigned long)host->ioaddr,
+                (unsigned long)iomem->start,
diff --git a/target/linux/brcm2708/patches-4.19/950-0462-pcie-brcmstb-Changes-for-BCM2711.patch b/target/linux/brcm2708/patches-4.19/950-0462-pcie-brcmstb-Changes-for-BCM2711.patch
deleted file mode 100644 (file)
index b44ec4c..0000000
+++ /dev/null
@@ -1,1411 +0,0 @@
-From 545951be6cabac8b1df85771c44335a0eaaa3c5d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH] pcie-brcmstb: Changes for BCM2711
-
-The initial brcmstb PCIe driver - originally taken from the V3(?)
-patch set - has been modified significantly for the BCM2711.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/dma/bcm2835-dma.c                    | 107 ++++
- drivers/pci/controller/Makefile              |   4 +
- drivers/pci/controller/pcie-brcmstb-bounce.c | 564 +++++++++++++++++++
- drivers/pci/controller/pcie-brcmstb-bounce.h |  32 ++
- drivers/pci/controller/pcie-brcmstb.c        | 237 ++++----
- drivers/soc/bcm/brcmstb/Makefile             |   2 +-
- drivers/soc/bcm/brcmstb/memory.c             | 158 ++++++
- 7 files changed, 996 insertions(+), 108 deletions(-)
- create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.c
- create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.h
- create mode 100644 drivers/soc/bcm/brcmstb/memory.c
-
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -68,6 +68,17 @@ struct bcm2835_dma_cb {
-       uint32_t pad[2];
- };
-+struct bcm2838_dma40_scb {
-+      uint32_t ti;
-+      uint32_t src;
-+      uint32_t srci;
-+      uint32_t dst;
-+      uint32_t dsti;
-+      uint32_t len;
-+      uint32_t next_cb;
-+      uint32_t rsvd;
-+};
-+
- struct bcm2835_cb_entry {
-       struct bcm2835_dma_cb *cb;
-       dma_addr_t paddr;
-@@ -185,6 +196,45 @@ struct bcm2835_desc {
- #define MAX_DMA_LEN SZ_1G
- #define MAX_LITE_DMA_LEN (SZ_64K - 4)
-+/* 40-bit DMA support */
-+#define BCM2838_DMA40_CS      0x00
-+#define BCM2838_DMA40_CB      0x04
-+#define BCM2838_DMA40_DEBUG   0x0c
-+#define BCM2858_DMA40_TI      0x10
-+#define BCM2838_DMA40_SRC     0x14
-+#define BCM2838_DMA40_SRCI    0x18
-+#define BCM2838_DMA40_DEST    0x1c
-+#define BCM2838_DMA40_DESTI   0x20
-+#define BCM2838_DMA40_LEN     0x24
-+#define BCM2838_DMA40_NEXT_CB 0x28
-+#define BCM2838_DMA40_DEBUG2  0x2c
-+
-+#define BCM2838_DMA40_CS_ACTIVE       BIT(0)
-+#define BCM2838_DMA40_CS_END  BIT(1)
-+
-+#define BCM2838_DMA40_CS_QOS(x)       (((x) & 0x1f) << 16)
-+#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
-+#define BCM2838_DMA40_CS_WRITE_WAIT   BIT(28)
-+
-+#define BCM2838_DMA40_BURST_LEN(x)    ((((x) - 1) & 0xf) << 8)
-+#define BCM2838_DMA40_INC             BIT(12)
-+#define BCM2838_DMA40_SIZE_128        (2 << 13)
-+
-+#define BCM2838_DMA40_MEMCPY_QOS \
-+      (BCM2838_DMA40_CS_QOS(0x0) | \
-+       BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
-+       BCM2838_DMA40_CS_WRITE_WAIT)
-+
-+#define BCM2838_DMA40_MEMCPY_XFER_INFO \
-+      (BCM2838_DMA40_SIZE_128 | \
-+       BCM2838_DMA40_INC | \
-+       BCM2838_DMA40_BURST_LEN(16))
-+
-+static void __iomem *memcpy_chan;
-+static struct bcm2838_dma40_scb *memcpy_scb;
-+static dma_addr_t memcpy_scb_dma;
-+DEFINE_SPINLOCK(memcpy_lock);
-+
- static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
- {
-       /* lite and normal channels have different max frame length */
-@@ -868,6 +918,56 @@ static void bcm2835_dma_free(struct bcm2
-       }
- }
-+int bcm2838_dma40_memcpy_init(struct device *dev)
-+{
-+      if (memcpy_scb)
-+              return 0;
-+
-+      memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
-+                                      &memcpy_scb_dma, GFP_KERNEL);
-+
-+      if (!memcpy_scb) {
-+              pr_err("bcm2838_dma40_memcpy_init failed!\n");
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(bcm2838_dma40_memcpy_init);
-+
-+void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size)
-+{
-+      struct bcm2838_dma40_scb *scb = memcpy_scb;
-+      unsigned long flags;
-+
-+      if (!scb) {
-+              pr_err("bcm2838_dma40_memcpy not initialised!\n");
-+              return;
-+      }
-+
-+      spin_lock_irqsave(&memcpy_lock, flags);
-+
-+      scb->ti = 0;
-+      scb->src = lower_32_bits(src);
-+      scb->srci = upper_32_bits(src) | BCM2838_DMA40_MEMCPY_XFER_INFO;
-+      scb->dst = lower_32_bits(dst);
-+      scb->dsti = upper_32_bits(dst) | BCM2838_DMA40_MEMCPY_XFER_INFO;
-+      scb->len = size;
-+      scb->next_cb = 0;
-+
-+      writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
-+      writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
-+             memcpy_chan + BCM2838_DMA40_CS);
-+      /* Poll for completion */
-+      while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
-+              cpu_relax();
-+
-+      writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
-+
-+      spin_unlock_irqrestore(&memcpy_lock, flags);
-+}
-+EXPORT_SYMBOL(bcm2838_dma40_memcpy);
-+
- static const struct of_device_id bcm2835_dma_of_match[] = {
-       { .compatible = "brcm,bcm2835-dma", },
-       {},
-@@ -966,6 +1066,13 @@ static int bcm2835_dma_probe(struct plat
-       /* Channel 0 is used by the legacy API */
-       chans_available &= ~BCM2835_DMA_BULK_MASK;
-+      /* We can't use channels 11-13 yet */
-+      chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
-+
-+      /* Grab channel 14 for the 40-bit DMA memcpy */
-+      chans_available &= ~BIT(14);
-+      memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
-+
-       /* get irqs for each channel that we support */
-       for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
-               /* skip masked out channels */
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -29,6 +29,10 @@ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-medi
- obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
- obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
- obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
-+ifdef CONFIG_ARM
-+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
-+endif
-+
- obj-$(CONFIG_VMD) += vmd.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y                         += dwc/
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
-@@ -0,0 +1,564 @@
-+/*
-+ *  This code started out as a version of arch/arm/common/dmabounce.c,
-+ *  modified to cope with highmem pages. Now it has been changed heavily -
-+ *  it now preallocates a large block (currently 4MB) and carves it up
-+ *  sequentially in ring fashion, and DMA is used to copy the data - to the
-+ *  point where very little of the original remains.
-+ *
-+ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
-+ *
-+ *  Original version by Brad Parker (brad@heeltoe.com)
-+ *  Re-written by Christopher Hoover <ch@murgatroid.com>
-+ *  Made generic by Deepak Saxena <dsaxena@plexity.net>
-+ *
-+ *  Copyright (C) 2002 Hewlett Packard Company.
-+ *  Copyright (C) 2004 MontaVista Software, Inc.
-+ *
-+ *  This program is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU General Public License
-+ *  version 2 as published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/page-flags.h>
-+#include <linux/device.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/dmapool.h>
-+#include <linux/list.h>
-+#include <linux/scatterlist.h>
-+#include <linux/bitmap.h>
-+
-+#include <asm/cacheflush.h>
-+#include <asm/dma-iommu.h>
-+
-+#define STATS
-+
-+#ifdef STATS
-+#define DO_STATS(X) do { X ; } while (0)
-+#else
-+#define DO_STATS(X) do { } while (0)
-+#endif
-+
-+/* ************************************************** */
-+
-+struct safe_buffer {
-+      struct list_head node;
-+
-+      /* original request */
-+      size_t          size;
-+      int             direction;
-+
-+      struct dmabounce_pool *pool;
-+      void            *safe;
-+      dma_addr_t      unsafe_dma_addr;
-+      dma_addr_t      safe_dma_addr;
-+};
-+
-+struct dmabounce_pool {
-+      unsigned long   pages;
-+      void            *virt_addr;
-+      dma_addr_t      dma_addr;
-+      unsigned long   *alloc_map;
-+      unsigned long   alloc_pos;
-+      spinlock_t      lock;
-+      struct device   *dev;
-+      unsigned long   num_pages;
-+#ifdef STATS
-+      size_t          max_size;
-+      unsigned long   num_bufs;
-+      unsigned long   max_bufs;
-+      unsigned long   max_pages;
-+#endif
-+};
-+
-+struct dmabounce_device_info {
-+      struct device *dev;
-+      dma_addr_t threshold;
-+      struct list_head safe_buffers;
-+      struct dmabounce_pool pool;
-+      rwlock_t lock;
-+#ifdef STATS
-+      unsigned long map_count;
-+      unsigned long unmap_count;
-+      unsigned long sync_dev_count;
-+      unsigned long sync_cpu_count;
-+      unsigned long fail_count;
-+      int attr_res;
-+#endif
-+};
-+
-+static struct dmabounce_device_info *g_dmabounce_device_info;
-+
-+extern int bcm2838_dma40_memcpy_init(struct device *dev);
-+extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
-+
-+#ifdef STATS
-+static ssize_t
-+bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+      return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
-+              device_info->map_count,
-+              device_info->unmap_count,
-+              device_info->sync_dev_count,
-+              device_info->sync_cpu_count,
-+              device_info->fail_count,
-+              device_info->pool.max_size,
-+              device_info->pool.num_bufs,
-+              device_info->pool.max_bufs,
-+              device_info->pool.num_pages * PAGE_SIZE,
-+              device_info->pool.max_pages * PAGE_SIZE);
-+}
-+
-+static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
-+#endif
-+
-+static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
-+                       unsigned long buffer_size)
-+{
-+      int ret = -ENOMEM;
-+      pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
-+      pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
-+      if (!pool->alloc_map)
-+              goto err_bitmap;
-+      pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
-+                                           &pool->dma_addr, GFP_KERNEL);
-+      if (!pool->virt_addr)
-+              goto err_dmabuf;
-+
-+      pool->alloc_pos = 0;
-+      spin_lock_init(&pool->lock);
-+      pool->dev = dev;
-+      pool->num_pages = 0;
-+
-+      DO_STATS(pool->max_size = 0);
-+      DO_STATS(pool->num_bufs = 0);
-+      DO_STATS(pool->max_bufs = 0);
-+      DO_STATS(pool->max_pages = 0);
-+
-+      return  0;
-+
-+err_dmabuf:
-+      bitmap_free(pool->alloc_map);
-+err_bitmap:
-+      return ret;
-+}
-+
-+static void bounce_destroy(struct dmabounce_pool *pool)
-+{
-+      dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
-+                        pool->dma_addr);
-+
-+      bitmap_free(pool->alloc_map);
-+}
-+
-+static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
-+                        dma_addr_t *dmaaddrp)
-+{
-+      unsigned long pages;
-+      unsigned long flags;
-+      unsigned long pos;
-+
-+      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+
-+      DO_STATS(pool->max_size = max(size, pool->max_size));
-+
-+      spin_lock_irqsave(&pool->lock, flags);
-+      pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+                                       pool->alloc_pos, pages, 0);
-+      /* If not found, try from the start */
-+      if (pos >= pool->pages && pool->alloc_pos)
-+              pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+                                               0, pages, 0);
-+
-+      if (pos >= pool->pages) {
-+              spin_unlock_irqrestore(&pool->lock, flags);
-+              return NULL;
-+      }
-+
-+      bitmap_set(pool->alloc_map, pos, pages);
-+      pool->alloc_pos = (pos + pages) % pool->pages;
-+      pool->num_pages += pages;
-+
-+      DO_STATS(pool->num_bufs++);
-+      DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
-+      DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
-+
-+      spin_unlock_irqrestore(&pool->lock, flags);
-+
-+      *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
-+
-+      return pool->virt_addr + pos * PAGE_SIZE;
-+}
-+
-+static void
-+bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
-+{
-+      unsigned long pages;
-+      unsigned long flags;
-+      unsigned long pos;
-+
-+      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+      pos = (buf - pool->virt_addr)/PAGE_SIZE;
-+
-+      BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
-+
-+      spin_lock_irqsave(&pool->lock, flags);
-+      bitmap_clear(pool->alloc_map, pos, pages);
-+      pool->num_pages -= pages;
-+      if (pool->num_pages == 0)
-+              pool->alloc_pos = 0;
-+      DO_STATS(pool->num_bufs--);
-+      spin_unlock_irqrestore(&pool->lock, flags);
-+}
-+
-+/* allocate a 'safe' buffer and keep track of it */
-+static struct safe_buffer *
-+alloc_safe_buffer(struct dmabounce_device_info *device_info,
-+                dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+      struct dmabounce_pool *pool = &device_info->pool;
-+      struct device *dev = device_info->dev;
-+      unsigned long flags;
-+
-+      /*
-+       * Although one might expect this to be called in thread context,
-+       * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
-+       * was previously used to select the appropriate allocation mode,
-+       * but this is unsafe.
-+       */
-+      buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
-+      if (!buf) {
-+              dev_warn(dev, "%s: kmalloc failed\n", __func__);
-+              return NULL;
-+      }
-+
-+      buf->unsafe_dma_addr = dma_addr;
-+      buf->size = size;
-+      buf->direction = dir;
-+      buf->pool = pool;
-+
-+      buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
-+
-+      if (!buf->safe) {
-+              dev_warn(dev,
-+                       "%s: could not alloc dma memory (size=%d)\n",
-+                       __func__, size);
-+              kfree(buf);
-+              return NULL;
-+      }
-+
-+      write_lock_irqsave(&device_info->lock, flags);
-+      list_add(&buf->node, &device_info->safe_buffers);
-+      write_unlock_irqrestore(&device_info->lock, flags);
-+
-+      return buf;
-+}
-+
-+/* determine if a buffer is from our "safe" pool */
-+static struct safe_buffer *
-+find_safe_buffer(struct dmabounce_device_info *device_info,
-+               dma_addr_t safe_dma_addr)
-+{
-+      struct safe_buffer *b, *rb = NULL;
-+      unsigned long flags;
-+
-+      read_lock_irqsave(&device_info->lock, flags);
-+
-+      list_for_each_entry(b, &device_info->safe_buffers, node)
-+              if (b->safe_dma_addr <= safe_dma_addr &&
-+                  b->safe_dma_addr + b->size > safe_dma_addr) {
-+                      rb = b;
-+                      break;
-+              }
-+
-+      read_unlock_irqrestore(&device_info->lock, flags);
-+      return rb;
-+}
-+
-+static void
-+free_safe_buffer(struct dmabounce_device_info *device_info,
-+               struct safe_buffer *buf)
-+{
-+      unsigned long flags;
-+
-+      write_lock_irqsave(&device_info->lock, flags);
-+      list_del(&buf->node);
-+      write_unlock_irqrestore(&device_info->lock, flags);
-+
-+      bounce_free(buf->pool, buf->safe, buf->size);
-+
-+      kfree(buf);
-+}
-+
-+/* ************************************************** */
-+
-+static struct safe_buffer *
-+find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
-+{
-+      if (!dev || !g_dmabounce_device_info)
-+              return NULL;
-+      if (dma_mapping_error(dev, dma_addr)) {
-+              dev_err(dev, "Trying to %s invalid mapping\n", where);
-+              return NULL;
-+      }
-+      return find_safe_buffer(g_dmabounce_device_info, dma_addr);
-+}
-+
-+static dma_addr_t
-+map_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+         enum dma_data_direction dir, unsigned long attrs)
-+{
-+      BUG_ON(buf->size != size);
-+      BUG_ON(buf->direction != dir);
-+
-+      dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
-+              (u64)buf->safe_dma_addr);
-+
-+      if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+          !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-+              bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
-+                                   size);
-+
-+      return buf->safe_dma_addr;
-+}
-+
-+static dma_addr_t
-+unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+           enum dma_data_direction dir, unsigned long attrs)
-+{
-+      BUG_ON(buf->size != size);
-+      BUG_ON(buf->direction != dir);
-+
-+      if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+          !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
-+              dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
-+                      (u64)buf->unsafe_dma_addr);
-+
-+              bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
-+                                   size);
-+      }
-+      return buf->unsafe_dma_addr;
-+}
-+
-+/* ************************************************** */
-+
-+/*
-+ * see if a buffer address is in an 'unsafe' range.  if it is
-+ * allocate a 'safe' buffer and copy the unsafe buffer into it.
-+ * substitute the safe buffer for the unsafe one.
-+ * (basically move the buffer from an unsafe area to a safe one)
-+ */
-+static dma_addr_t
-+dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
-+                 size_t size, enum dma_data_direction dir,
-+                 unsigned long attrs)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+      dma_addr_t dma_addr;
-+
-+      dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
-+
-+      arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
-+
-+      if (device_info && (dma_addr + size) > device_info->threshold) {
-+              struct safe_buffer *buf;
-+
-+              buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
-+              if (!buf) {
-+                      DO_STATS(device_info->fail_count++);
-+                      return ARM_MAPPING_ERROR;
-+              }
-+
-+              DO_STATS(device_info->map_count++);
-+
-+              dma_addr = map_single(dev, buf, size, dir, attrs);
-+      }
-+
-+      return dma_addr;
-+}
-+
-+/*
-+ * see if a mapped address was really a "safe" buffer and if so, copy
-+ * the data from the safe buffer back to the unsafe buffer and free up
-+ * the safe buffer.  (basically return things back to the way they
-+ * should be)
-+ */
-+static void
-+dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-+                   enum dma_data_direction dir, unsigned long attrs)
-+{
-+      struct safe_buffer *buf;
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->unmap_count++);
-+              dma_addr = unmap_single(dev, buf, size, dir, attrs);
-+              free_safe_buffer(g_dmabounce_device_info, buf);
-+      }
-+
-+      arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+/*
-+ * A version of dmabounce_map_page that assumes the mapping has already
-+ * been created - intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
-+                        enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+
-+      arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->sync_dev_count++);
-+              map_single(dev, buf, size, dir, 0);
-+      }
-+}
-+
-+/*
-+ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
-+ * intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
-+                     size_t size, enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
-+              dma_addr = unmap_single(dev, buf, size, dir, 0);
-+      }
-+
-+      arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
-+{
-+      if (g_dmabounce_device_info)
-+              return 0;
-+
-+      return arm_dma_ops.dma_supported(dev, dma_mask);
-+}
-+
-+static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
-+{
-+      return arm_dma_ops.mapping_error(dev, dma_addr);
-+}
-+
-+static const struct dma_map_ops dmabounce_ops = {
-+      .alloc                  = arm_dma_alloc,
-+      .free                   = arm_dma_free,
-+      .mmap                   = arm_dma_mmap,
-+      .get_sgtable            = arm_dma_get_sgtable,
-+      .map_page               = dmabounce_map_page,
-+      .unmap_page             = dmabounce_unmap_page,
-+      .sync_single_for_cpu    = dmabounce_sync_for_cpu,
-+      .sync_single_for_device = dmabounce_sync_for_device,
-+      .map_sg                 = arm_dma_map_sg,
-+      .unmap_sg               = arm_dma_unmap_sg,
-+      .sync_sg_for_cpu        = arm_dma_sync_sg_for_cpu,
-+      .sync_sg_for_device     = arm_dma_sync_sg_for_device,
-+      .dma_supported          = dmabounce_dma_supported,
-+      .mapping_error          = dmabounce_mapping_error,
-+};
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev,
-+                                unsigned long buffer_size,
-+                                dma_addr_t threshold)
-+{
-+      struct dmabounce_device_info *device_info;
-+      int ret;
-+
-+      /* Only support a single client */
-+      if (g_dmabounce_device_info)
-+              return -EBUSY;
-+
-+      ret = bcm2838_dma40_memcpy_init(dev);
-+      if (ret)
-+          return ret;
-+
-+      device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
-+      if (!device_info) {
-+              dev_err(dev,
-+                      "Could not allocated dmabounce_device_info\n");
-+              return -ENOMEM;
-+      }
-+
-+      ret = bounce_create(&device_info->pool, dev, buffer_size);
-+      if (ret) {
-+              dev_err(dev,
-+                      "dmabounce: could not allocate %ld byte DMA pool\n",
-+                      buffer_size);
-+              goto err_bounce;
-+      }
-+
-+      device_info->dev = dev;
-+      device_info->threshold = threshold;
-+      INIT_LIST_HEAD(&device_info->safe_buffers);
-+      rwlock_init(&device_info->lock);
-+
-+      DO_STATS(device_info->map_count = 0);
-+      DO_STATS(device_info->unmap_count = 0);
-+      DO_STATS(device_info->sync_dev_count = 0);
-+      DO_STATS(device_info->sync_cpu_count = 0);
-+      DO_STATS(device_info->fail_count = 0);
-+      DO_STATS(device_info->attr_res =
-+               device_create_file(dev, &dev_attr_dmabounce_stats));
-+
-+      g_dmabounce_device_info = device_info;
-+      set_dma_ops(dev, &dmabounce_ops);
-+
-+      dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
-+               buffer_size / 1024, &threshold);
-+
-+      return 0;
-+
-+ err_bounce:
-+      kfree(device_info);
-+      return ret;
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
-+
-+void brcm_pcie_bounce_unregister_dev(struct device *dev)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+
-+      g_dmabounce_device_info = NULL;
-+      set_dma_ops(dev, NULL);
-+
-+      if (!device_info) {
-+              dev_warn(dev,
-+                       "Never registered with dmabounce but attempting"
-+                       "to unregister!\n");
-+              return;
-+      }
-+
-+      if (!list_empty(&device_info->safe_buffers)) {
-+              dev_err(dev,
-+                      "Removing from dmabounce with pending buffers!\n");
-+              BUG();
-+      }
-+
-+      bounce_destroy(&device_info->pool);
-+
-+      DO_STATS(if (device_info->attr_res == 0)
-+                       device_remove_file(dev, &dev_attr_dmabounce_stats));
-+
-+      kfree(device_info);
-+
-+      dev_info(dev, "dmabounce: device unregistered\n");
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
-+
-+MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
-+MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
-+ */
-+
-+#ifndef _PCIE_BRCMSTB_BOUNCE_H
-+#define _PCIE_BRCMSTB_BOUNCE_H
-+
-+#ifdef CONFIG_ARM
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
-+                                dma_addr_t threshold);
-+
-+int brcm_pcie_bounce_unregister_dev(struct device *dev);
-+
-+#else
-+
-+static inline int brcm_pcie_bounce_register_dev(struct device *dev,
-+                                              unsigned long buffer_size,
-+                                              dma_addr_t threshold)
-+{
-+      return 0;
-+}
-+
-+static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
-+{
-+      return 0;
-+}
-+
-+#endif
-+
-+#endif /* _PCIE_BRCMSTB_BOUNCE_H */
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -29,6 +29,7 @@
- #include <linux/string.h>
- #include <linux/types.h>
- #include "../pci.h"
-+#include "pcie-brcmstb-bounce.h"
- /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
- #define BRCM_PCIE_CAP_REGS                            0x00ac
-@@ -53,6 +54,7 @@
- #define PCIE_MISC_MSI_BAR_CONFIG_LO                   0x4044
- #define PCIE_MISC_MSI_BAR_CONFIG_HI                   0x4048
- #define PCIE_MISC_MSI_DATA_CONFIG                     0x404c
-+#define PCIE_MISC_EOI_CTRL                            0x4060
- #define PCIE_MISC_PCIE_CTRL                           0x4064
- #define PCIE_MISC_PCIE_STATUS                         0x4068
- #define PCIE_MISC_REVISION                            0x406c
-@@ -260,12 +262,14 @@ struct brcm_pcie {
-       unsigned int            rev;
-       const int               *reg_offsets;
-       const int               *reg_field_info;
-+      u32                     max_burst_size;
-       enum pcie_type          type;
- };
- struct pcie_cfg_data {
-       const int               *reg_field_info;
-       const int               *offsets;
-+      const u32               max_burst_size;
-       const enum pcie_type    type;
- };
-@@ -288,24 +292,27 @@ static const int pcie_offset_bcm7425[] =
- static const struct pcie_cfg_data bcm7425_cfg = {
-       .reg_field_info = pcie_reg_field_info,
-       .offsets        = pcie_offset_bcm7425,
-+      .max_burst_size = BURST_SIZE_256,
-       .type           = BCM7425,
- };
- static const int pcie_offsets[] = {
-       [RGR1_SW_INIT_1] = 0x9210,
-       [EXT_CFG_INDEX]  = 0x9000,
--      [EXT_CFG_DATA]   = 0x9004,
-+      [EXT_CFG_DATA]   = 0x8000,
- };
- static const struct pcie_cfg_data bcm7435_cfg = {
-       .reg_field_info = pcie_reg_field_info,
-       .offsets        = pcie_offsets,
-+      .max_burst_size = BURST_SIZE_256,
-       .type           = BCM7435,
- };
- static const struct pcie_cfg_data generic_cfg = {
-       .reg_field_info = pcie_reg_field_info,
-       .offsets        = pcie_offsets,
-+      .max_burst_size = BURST_SIZE_128, // before BURST_SIZE_512
-       .type           = GENERIC,
- };
-@@ -318,6 +325,7 @@ static const int pcie_offset_bcm7278[] =
- static const struct pcie_cfg_data bcm7278_cfg = {
-       .reg_field_info = pcie_reg_field_info_bcm7278,
-       .offsets        = pcie_offset_bcm7278,
-+      .max_burst_size = BURST_SIZE_512,
-       .type           = BCM7278,
- };
-@@ -360,7 +368,6 @@ static struct pci_ops brcm_pcie_ops = {
-        (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
- static const struct dma_map_ops *arch_dma_ops;
--static const struct dma_map_ops *brcm_dma_ops_ptr;
- static struct of_pci_range *dma_ranges;
- static int num_dma_ranges;
-@@ -369,6 +376,16 @@ static int num_memc;
- static int num_pcie;
- static DEFINE_MUTEX(brcm_pcie_lock);
-+static unsigned int bounce_buffer = 32*1024*1024;
-+module_param(bounce_buffer, uint, 0644);
-+MODULE_PARM_DESC(bounce_buffer, "Size of bounce buffer");
-+
-+static unsigned int bounce_threshold = 0xc0000000;
-+module_param(bounce_threshold, uint, 0644);
-+MODULE_PARM_DESC(bounce_threshold, "Bounce threshold");
-+
-+static struct brcm_pcie *g_pcie;
-+
- static dma_addr_t brcm_to_pci(dma_addr_t addr)
- {
-       struct of_pci_range *p;
-@@ -457,12 +474,10 @@ static int brcm_map_sg(struct device *de
-       struct scatterlist *sg;
-       for_each_sg(sgl, sg, nents, i) {
--#ifdef CONFIG_NEED_SG_DMA_LENGTH
--              sg->dma_length = sg->length;
--#endif
-+              sg_dma_len(sg) = sg->length;
-               sg->dma_address =
--                      brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
--                                                 sg->length, dir, attrs);
-+                      brcm_map_page(dev, sg_page(sg), sg->offset,
-+                                    sg->length, dir, attrs);
-               if (dma_mapping_error(dev, sg->dma_address))
-                       goto bad_mapping;
-       }
-@@ -470,8 +485,8 @@ static int brcm_map_sg(struct device *de
- bad_mapping:
-       for_each_sg(sgl, sg, i, j)
--              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
--                                           sg_dma_len(sg), dir, attrs);
-+              brcm_unmap_page(dev, sg_dma_address(sg),
-+                              sg_dma_len(sg), dir, attrs);
-       return 0;
- }
-@@ -484,8 +499,8 @@ static void brcm_unmap_sg(struct device
-       struct scatterlist *sg;
-       for_each_sg(sgl, sg, nents, i)
--              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
--                                           sg_dma_len(sg), dir, attrs);
-+              brcm_unmap_page(dev, sg_dma_address(sg),
-+                              sg_dma_len(sg), dir, attrs);
- }
- static void brcm_sync_single_for_cpu(struct device *dev,
-@@ -531,8 +546,8 @@ void brcm_sync_sg_for_cpu(struct device
-       int i;
-       for_each_sg(sgl, sg, nents, i)
--              brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
--                                                    sg->length, dir);
-+              brcm_sync_single_for_cpu(dev, sg_dma_address(sg),
-+                                       sg->length, dir);
- }
- void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
-@@ -542,9 +557,9 @@ void brcm_sync_sg_for_device(struct devi
-       int i;
-       for_each_sg(sgl, sg, nents, i)
--              brcm_dma_ops_ptr->sync_single_for_device(dev,
--                                                       sg_dma_address(sg),
--                                                       sg->length, dir);
-+              brcm_sync_single_for_device(dev,
-+                                          sg_dma_address(sg),
-+                                          sg->length, dir);
- }
- static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
-@@ -633,17 +648,47 @@ static void brcm_set_dma_ops(struct devi
-       set_dma_ops(dev, &brcm_dma_ops);
- }
-+static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
-+                                     unsigned int val);
- static int brcmstb_platform_notifier(struct notifier_block *nb,
-                                    unsigned long event, void *__dev)
- {
-+      extern unsigned long max_pfn;
-       struct device *dev = __dev;
-+      const char *rc_name = "0000:00:00.0";
--      brcm_dma_ops_ptr = &brcm_dma_ops;
--      if (event != BUS_NOTIFY_ADD_DEVICE)
--              return NOTIFY_DONE;
-+      switch (event) {
-+      case BUS_NOTIFY_ADD_DEVICE:
-+              if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
-+                  strcmp(dev->kobj.name, rc_name)) {
-+                      int ret;
-+
-+                      ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
-+                                                          (dma_addr_t)bounce_threshold);
-+                      if (ret) {
-+                              dev_err(dev,
-+                                      "brcm_pcie_bounce_register_dev() failed: %d\n",
-+                              ret);
-+                              return ret;
-+                      }
-+              }
-+              brcm_set_dma_ops(dev);
-+              return NOTIFY_OK;
-+
-+      case BUS_NOTIFY_DEL_DEVICE:
-+              if (!strcmp(dev->kobj.name, rc_name) && g_pcie) {
-+                      /* Force a bus reset */
-+                      brcm_pcie_perst_set(g_pcie, 1);
-+                      msleep(100);
-+                      brcm_pcie_perst_set(g_pcie, 0);
-+              } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
-+                      brcm_pcie_bounce_unregister_dev(dev);
-+              }
-+              return NOTIFY_OK;
--      brcm_set_dma_ops(dev);
--      return NOTIFY_OK;
-+      default:
-+              return NOTIFY_DONE;
-+      }
- }
- static struct notifier_block brcmstb_platform_nb = {
-@@ -914,6 +959,7 @@ static void brcm_pcie_msi_isr(struct irq
-               }
-       }
-       chained_irq_exit(chip, desc);
-+      bcm_writel(1, msi->base + PCIE_MISC_EOI_CTRL);
- }
- static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-@@ -930,7 +976,8 @@ static void brcm_compose_msi_msg(struct
- static int brcm_msi_set_affinity(struct irq_data *irq_data,
-                                const struct cpumask *mask, bool force)
- {
--      return -EINVAL;
-+      struct brcm_msi *msi = irq_data_get_irq_chip_data(irq_data);
-+      return __irq_set_affinity(msi->irq, mask, force);
- }
- static struct irq_chip brcm_msi_bottom_irq_chip = {
-@@ -1168,9 +1215,9 @@ static void __iomem *brcm_pcie_map_conf(
-               return PCI_SLOT(devfn) ? NULL : base + where;
-       /* For devices, write to the config space index register */
--      idx = cfg_index(bus->number, devfn, where);
-+      idx = cfg_index(bus->number, devfn, 0);
-       bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
--      return base + DATA_ADDR(pcie) + (where & 0x3);
-+      return base + DATA_ADDR(pcie) + where;
- }
- static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
-@@ -1238,20 +1285,6 @@ static int brcm_pcie_parse_map_dma_range
-                       num_dma_ranges++;
-       }
--      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
--              u64 size = brcmstb_memory_memc_size(i);
--
--              if (size == (u64)-1) {
--                      dev_err(pcie->dev, "cannot get memc%d size", i);
--                      return -EINVAL;
--              } else if (size) {
--                      scb_size[i] = roundup_pow_of_two_64(size);
--                      num_memc++;
--              } else {
--                      break;
--              }
--      }
--
-       return 0;
- }
-@@ -1275,26 +1308,25 @@ static int brcm_pcie_add_controller(stru
-       if (ret)
-               goto done;
--      /* Determine num_memc and their sizes */
--      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
--              u64 size = brcmstb_memory_memc_size(i);
--
--              if (size == (u64)-1) {
--                      dev_err(dev, "cannot get memc%d size\n", i);
--                      ret = -EINVAL;
--                      goto done;
--              } else if (size) {
--                      scb_size[i] = roundup_pow_of_two_64(size);
--                      num_memc++;
--              } else {
--                      break;
-+      if (!num_dma_ranges) {
-+              /* Determine num_memc and their sizes by other means */
-+              for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-+                      u64 size = brcmstb_memory_memc_size(i);
-+
-+                      if (size == (u64)-1) {
-+                              dev_err(dev, "cannot get memc%d size\n", i);
-+                              ret = -EINVAL;
-+                              goto done;
-+                      } else if (size) {
-+                              scb_size[i] = roundup_pow_of_two_64(size);
-+                      } else {
-+                              break;
-+                      }
-               }
--      }
--      if (!ret && num_memc == 0) {
--              ret = -EINVAL;
--              goto done;
-+              num_memc = i;
-       }
-+      g_pcie = pcie;
-       num_pcie++;
- done:
-       mutex_unlock(&brcm_pcie_lock);
-@@ -1307,6 +1339,7 @@ static void brcm_pcie_remove_controller(
-       if (--num_pcie > 0)
-               goto out;
-+      g_pcie = NULL;
-       if (brcm_unregister_notifier())
-               dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
-       kfree(dma_ranges);
-@@ -1367,7 +1400,7 @@ static int brcm_pcie_setup(struct brcm_p
-       void __iomem *base = pcie->base;
-       unsigned int scb_size_val;
-       u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
--      u32 tmp, burst;
-+      u32 tmp;
-       int i, j, ret, limit;
-       u16 nlw, cls, lnksta;
-       bool ssc_good = false;
-@@ -1400,20 +1433,15 @@ static int brcm_pcie_setup(struct brcm_p
-       /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
-       tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
-       tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
--      burst = (pcie->type == GENERIC || pcie->type == BCM7278)
--              ? BURST_SIZE_512 : BURST_SIZE_256;
--      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
-+      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE,
-+                         pcie->max_burst_size);
-       bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
-       /*
-        * Set up inbound memory view for the EP (called RC_BAR2,
-        * not to be confused with the BARs that are advertised by
-        * the EP).
--       */
--      for (i = 0; i < num_memc; i++)
--              total_mem_size += scb_size[i];
--
--      /*
-+       *
-        * The PCIe host controller by design must set the inbound
-        * viewport to be a contiguous arrangement of all of the
-        * system's memory.  In addition, its size mut be a power of
-@@ -1429,55 +1457,49 @@ static int brcm_pcie_setup(struct brcm_p
-        * the controller will know to send outbound memory downstream
-        * and everything else upstream.
-        */
--      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
--      if (dma_ranges) {
-+      if (num_dma_ranges) {
-               /*
--               * The best-case scenario is to place the inbound
--               * region in the first 4GB of pcie-space, as some
--               * legacy devices can only address 32bits.
--               * We would also like to put the MSI under 4GB
--               * as well, since some devices require a 32bit
--               * MSI target address.
-+               * Use the base address and size(s) provided in the dma-ranges
-+               * property.
-                */
--              if (total_mem_size <= 0xc0000000ULL &&
--                  rc_bar2_size <= 0x100000000ULL) {
--                      rc_bar2_offset = 0;
--                      /* If the viewport is less then 4GB we can fit
--                       * the MSI target address under 4GB. Otherwise
--                       * put it right below 64GB.
--                       */
--                      msi_target_addr =
--                              (rc_bar2_size == 0x100000000ULL)
--                              ? BRCM_MSI_TARGET_ADDR_GT_4GB
--                              : BRCM_MSI_TARGET_ADDR_LT_4GB;
--              } else {
--                      /*
--                       * The system memory is 4GB or larger so we
--                       * cannot start the inbound region at location
--                       * 0 (since we have to allow some space for
--                       * outbound memory @ 3GB).  So instead we
--                       * start it at the 1x multiple of its size
--                       */
--                      rc_bar2_offset = rc_bar2_size;
--
--                      /* Since we are starting the viewport at 4GB or
--                       * higher, put the MSI target address below 4GB
--                       */
--                      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
--              }
--      } else {
-+              for (i = 0; i < num_dma_ranges; i++)
-+                      scb_size[i] = roundup_pow_of_two_64(dma_ranges[i].size);
-+
-+              num_memc = num_dma_ranges;
-+              rc_bar2_offset = dma_ranges[0].pci_addr;
-+      } else if (num_memc) {
-               /*
-                * Set simple configuration based on memory sizes
--               * only.  We always start the viewport at address 0,
--               * and set the MSI target address accordingly.
-+               * only.  We always start the viewport at address 0.
-                */
-               rc_bar2_offset = 0;
-+      } else {
-+              return -EINVAL;
-+      }
-+
-+      for (i = 0; i < num_memc; i++)
-+              total_mem_size += scb_size[i];
-+
-+      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
--              msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
--                      ? BRCM_MSI_TARGET_ADDR_GT_4GB
--                      : BRCM_MSI_TARGET_ADDR_LT_4GB;
-+      /* Verify the alignment is correct */
-+      if (rc_bar2_offset & (rc_bar2_size - 1)) {
-+              dev_err(dev, "inbound window is misaligned\n");
-+              return -EINVAL;
-       }
-+
-+      /*
-+       * Position the MSI target low if possible.
-+       *
-+       * TO DO: Consider outbound window when choosing MSI target and
-+       * verifying configuration.
-+       */
-+      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
-+      if (rc_bar2_offset <= msi_target_addr &&
-+          rc_bar2_offset + rc_bar2_size > msi_target_addr)
-+              msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
-+
-       pcie->msi_target_addr = msi_target_addr;
-       tmp = lower_32_bits(rc_bar2_offset);
-@@ -1713,6 +1735,7 @@ static int brcm_pcie_probe(struct platfo
-       data = of_id->data;
-       pcie->reg_offsets = data->offsets;
-       pcie->reg_field_info = data->reg_field_info;
-+      pcie->max_burst_size = data->max_burst_size;
-       pcie->type = data->type;
-       pcie->dn = dn;
-       pcie->dev = &pdev->dev;
-@@ -1732,7 +1755,7 @@ static int brcm_pcie_probe(struct platfo
-       pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
-       if (IS_ERR(pcie->clk)) {
--              dev_err(&pdev->dev, "could not get clock\n");
-+              dev_warn(&pdev->dev, "could not get clock\n");
-               pcie->clk = NULL;
-       }
-       pcie->base = base;
-@@ -1755,7 +1778,8 @@ static int brcm_pcie_probe(struct platfo
-       ret = clk_prepare_enable(pcie->clk);
-       if (ret) {
--              dev_err(&pdev->dev, "could not enable clock\n");
-+              if (ret != -EPROBE_DEFER)
-+                      dev_err(&pdev->dev, "could not enable clock\n");
-               return ret;
-       }
-@@ -1818,7 +1842,6 @@ static struct platform_driver brcm_pcie_
-       .remove = brcm_pcie_remove,
-       .driver = {
-               .name = "brcm-pcie",
--              .owner = THIS_MODULE,
-               .of_match_table = brcm_pcie_match,
-               .pm = &brcm_pcie_pm_ops,
-       },
---- a/drivers/soc/bcm/brcmstb/Makefile
-+++ b/drivers/soc/bcm/brcmstb/Makefile
-@@ -1,2 +1,2 @@
--obj-y                         += common.o biuctrl.o
-+obj-y                         += common.o biuctrl.o memory.o
- obj-$(CONFIG_BRCMSTB_PM)      += pm/
---- /dev/null
-+++ b/drivers/soc/bcm/brcmstb/memory.c
-@@ -0,0 +1,158 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* Copyright © 2015-2017 Broadcom */
-+
-+#include <linux/device.h>
-+#include <linux/io.h>
-+#include <linux/libfdt.h>
-+#include <linux/of_address.h>
-+#include <linux/of_fdt.h>
-+#include <linux/sizes.h>
-+#include <soc/brcmstb/memory_api.h>
-+
-+/* Macro to help extract property data */
-+#define DT_PROP_DATA_TO_U32(b, offs) (fdt32_to_cpu(*(u32 *)(b + offs)))
-+
-+/* Constants used when retrieving memc info */
-+#define NUM_BUS_RANGES 10
-+#define BUS_RANGE_ULIMIT_SHIFT 4
-+#define BUS_RANGE_LLIMIT_SHIFT 4
-+#define BUS_RANGE_PA_SHIFT 12
-+
-+enum {
-+      BUSNUM_MCP0 = 0x4,
-+      BUSNUM_MCP1 = 0x5,
-+      BUSNUM_MCP2 = 0x6,
-+};
-+
-+/*
-+ * If the DT nodes are handy, determine which MEMC holds the specified
-+ * physical address.
-+ */
-+#ifdef CONFIG_ARCH_BRCMSTB
-+int __brcmstb_memory_phys_addr_to_memc(phys_addr_t pa, void __iomem *base)
-+{
-+      int memc = -1;
-+      int i;
-+
-+      for (i = 0; i < NUM_BUS_RANGES; i++, base += 8) {
-+              const u64 ulimit_raw = readl(base);
-+              const u64 llimit_raw = readl(base + 4);
-+              const u64 ulimit =
-+                      ((ulimit_raw >> BUS_RANGE_ULIMIT_SHIFT)
-+                       << BUS_RANGE_PA_SHIFT) | 0xfff;
-+              const u64 llimit = (llimit_raw >> BUS_RANGE_LLIMIT_SHIFT)
-+                                 << BUS_RANGE_PA_SHIFT;
-+              const u32 busnum = (u32)(ulimit_raw & 0xf);
-+
-+              if (pa >= llimit && pa <= ulimit) {
-+                      if (busnum >= BUSNUM_MCP0 && busnum <= BUSNUM_MCP2) {
-+                              memc = busnum - BUSNUM_MCP0;
-+                              break;
-+                      }
-+              }
-+      }
-+
-+      return memc;
-+}
-+
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+      int memc = -1;
-+      struct device_node *np;
-+      void __iomem *cpubiuctrl;
-+
-+      np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
-+      if (!np)
-+              return memc;
-+
-+      cpubiuctrl = of_iomap(np, 0);
-+      if (!cpubiuctrl)
-+              goto cleanup;
-+
-+      memc = __brcmstb_memory_phys_addr_to_memc(pa, cpubiuctrl);
-+      iounmap(cpubiuctrl);
-+
-+cleanup:
-+      of_node_put(np);
-+
-+      return memc;
-+}
-+
-+#elif defined(CONFIG_MIPS)
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+      /* The logic here is fairly simple and hardcoded: if pa <= 0x5000_0000,
-+       * then this is MEMC0, else MEMC1.
-+       *
-+       * For systems with 2GB on MEMC0, MEMC1 starts at 9000_0000, with 1GB
-+       * on MEMC0, MEMC1 starts at 6000_0000.
-+       */
-+      if (pa >= 0x50000000ULL)
-+              return 1;
-+      else
-+              return 0;
-+}
-+#endif
-+
-+u64 brcmstb_memory_memc_size(int memc)
-+{
-+      const void *fdt = initial_boot_params;
-+      const int mem_offset = fdt_path_offset(fdt, "/memory");
-+      int addr_cells = 1, size_cells = 1;
-+      const struct fdt_property *prop;
-+      int proplen, cellslen;
-+      u64 memc_size = 0;
-+      int i;
-+
-+      /* Get root size and address cells if specified */
-+      prop = fdt_get_property(fdt, 0, "#size-cells", &proplen);
-+      if (prop)
-+              size_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
-+
-+      prop = fdt_get_property(fdt, 0, "#address-cells", &proplen);
-+      if (prop)
-+              addr_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
-+
-+      if (mem_offset < 0)
-+              return -1;
-+
-+      prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
-+      cellslen = (int)sizeof(u32) * (addr_cells + size_cells);
-+      if ((proplen % cellslen) != 0)
-+              return -1;
-+
-+      for (i = 0; i < proplen / cellslen; ++i) {
-+              u64 addr = 0;
-+              u64 size = 0;
-+              int memc_idx;
-+              int j;
-+
-+              for (j = 0; j < addr_cells; ++j) {
-+                      int offset = (cellslen * i) + (sizeof(u32) * j);
-+
-+                      addr |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
-+                              ((addr_cells - j - 1) * 32);
-+              }
-+              for (j = 0; j < size_cells; ++j) {
-+                      int offset = (cellslen * i) +
-+                              (sizeof(u32) * (j + addr_cells));
-+
-+                      size |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
-+                              ((size_cells - j - 1) * 32);
-+              }
-+
-+              if ((phys_addr_t)addr != addr) {
-+                      pr_err("phys_addr_t is smaller than provided address 0x%llx!\n",
-+                             addr);
-+                      return -1;
-+              }
-+
-+              memc_idx = brcmstb_memory_phys_addr_to_memc((phys_addr_t)addr);
-+              if (memc_idx == memc)
-+                      memc_size += size;
-+      }
-+
-+      return memc_size;
-+}
-+EXPORT_SYMBOL_GPL(brcmstb_memory_memc_size);
-+
diff --git a/target/linux/brcm2708/patches-4.19/950-0463-arm-bcm2835-DMA-can-only-address-1GB.patch b/target/linux/brcm2708/patches-4.19/950-0463-arm-bcm2835-DMA-can-only-address-1GB.patch
deleted file mode 100644 (file)
index 89919c1..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 9334afe7293b3a78b7e070a70880b2db7aa98365 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 May 2019 15:47:42 +0100
-Subject: [PATCH] arm: bcm2835: DMA can only address 1GB
-
-The legacy peripherals can only address the first gigabyte of RAM, so
-ensure that DMA allocations are restricted to that region.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/mach-bcm/board_bcm2835.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -123,6 +123,9 @@ static const char * const bcm2835_compat
- };
- DT_MACHINE_START(BCM2835, "BCM2835")
-+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
-+      .dma_zone_size  = SZ_1G,
-+#endif
-       .map_io = bcm2835_map_io,
-       .init_machine = bcm2835_init,
-       .dt_compat = bcm2835_compat,
diff --git a/target/linux/brcm2708/patches-4.19/950-0463-mmc-sdhci-Mask-spurious-interrupts.patch b/target/linux/brcm2708/patches-4.19/950-0463-mmc-sdhci-Mask-spurious-interrupts.patch
new file mode 100644 (file)
index 0000000..fd5cb52
--- /dev/null
@@ -0,0 +1,29 @@
+From be309b7db77215610d5ac15bf0aacd47ea5b3433 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 28 Sep 2018 16:24:05 +0100
+Subject: [PATCH] mmc: sdhci: Mask "spurious" interrupts
+
+Add a filter for "spurious" Transfer Complete interrupts, attempting
+to make it as specific as possible:
+* INT_DATA_END (transfer complete) is set
+* There is a stop command in progress
+* There is no data transfer in progress
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/sdhci.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -2935,6 +2935,10 @@ static irqreturn_t sdhci_irq(int irq, vo
+                       result = IRQ_WAKE_THREAD;
+               }
++              if ((intmask & SDHCI_INT_DATA_END) && !host->data &&
++                  host->cmd && (host->cmd == host->cmd->mrq->stop))
++                      intmask &= ~SDHCI_INT_DATA_END;
++
+               if (intmask & SDHCI_INT_CMD_MASK)
+                       sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
diff --git a/target/linux/brcm2708/patches-4.19/950-0464-mmc-bcm2835-sdhost-Support-64-bit-physical-addresses.patch b/target/linux/brcm2708/patches-4.19/950-0464-mmc-bcm2835-sdhost-Support-64-bit-physical-addresses.patch
deleted file mode 100644 (file)
index a2aeeea..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 8a58288d710a817b5dc7747f0bec1fb167368e7e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 Aug 2018 09:05:15 +0100
-Subject: [PATCH] mmc: bcm2835-sdhost: Support 64-bit physical
- addresses
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/bcm2835-sdhost.c | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
---- a/drivers/mmc/host/bcm2835-sdhost.c
-+++ b/drivers/mmc/host/bcm2835-sdhost.c
-@@ -148,7 +148,7 @@ struct bcm2835_host {
-       spinlock_t              lock;
-       void __iomem            *ioaddr;
--      u32                     bus_addr;
-+      phys_addr_t             bus_addr;
-       struct mmc_host         *mmc;
-@@ -246,8 +246,8 @@ static void log_init(struct device *dev,
-       sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr,
-                                            GFP_KERNEL);
-       if (sdhost_log_buf) {
--              pr_info("sdhost: log_buf @ %p (%x)\n",
--                      sdhost_log_buf, (u32)sdhost_log_addr);
-+              pr_info("sdhost: log_buf @ %p (%llx)\n",
-+                      sdhost_log_buf, (u64)sdhost_log_addr);
-               timer_base = ioremap_nocache(bus_to_phys + 0x7e003000, SZ_4K);
-               if (!timer_base)
-                       pr_err("sdhost: failed to remap timer\n");
-@@ -2024,6 +2024,7 @@ static int bcm2835_sdhost_probe(struct p
-       struct mmc_host *mmc;
-       const __be32 *addr;
-       u32 msg[3];
-+      int na;
-       int ret;
-       pr_debug("bcm2835_sdhost_probe\n");
-@@ -2047,12 +2048,13 @@ static int bcm2835_sdhost_probe(struct p
-               goto err;
-       }
-+      na = of_n_addr_cells(node);
-       addr = of_get_address(node, 0, NULL, NULL);
-       if (!addr) {
-               dev_err(dev, "could not get DMA-register address\n");
-               return -ENODEV;
-       }
--      host->bus_addr = be32_to_cpup(addr);
-+      host->bus_addr = (phys_addr_t)of_read_number(addr, na);
-       pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
-                (unsigned long)host->ioaddr,
-                (unsigned long)iomem->start,
diff --git a/target/linux/brcm2708/patches-4.19/950-0464-mmc-sdhci-iproc-Add-support-for-emmc2-of-the-BCM2838.patch b/target/linux/brcm2708/patches-4.19/950-0464-mmc-sdhci-iproc-Add-support-for-emmc2-of-the-BCM2838.patch
new file mode 100644 (file)
index 0000000..d960766
--- /dev/null
@@ -0,0 +1,36 @@
+From 0a1c3ff378e60f2a59153cfc1c7529bfe05eb115 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 27 Apr 2019 12:33:57 +0200
+Subject: [PATCH] mmc: sdhci-iproc: Add support for emmc2 of the
+ BCM2838
+
+The emmc2 interface of the BCM2838 should be integrated in sdhci-iproc
+to avoid code redundancy. Except 32 bit only access no other quirks are
+known yet. Add an additional compatible string for upstream proposal.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ drivers/mmc/host/sdhci-iproc.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/mmc/host/sdhci-iproc.c
++++ b/drivers/mmc/host/sdhci-iproc.c
+@@ -250,8 +250,18 @@ static const struct sdhci_iproc_data bcm
+       .mmc_caps = 0x00000000,
+ };
++static const struct sdhci_pltfm_data sdhci_bcm2838_pltfm_data = {
++      .ops = &sdhci_iproc_32only_ops,
++};
++
++static const struct sdhci_iproc_data bcm2838_data = {
++      .pdata = &sdhci_bcm2838_pltfm_data,
++};
++
+ static const struct of_device_id sdhci_iproc_of_match[] = {
+       { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
++      { .compatible = "brcm,bcm2838-sdhci", .data = &bcm2838_data },
++      { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2838_data },
+       { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
+       { .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
+       { }
diff --git a/target/linux/brcm2708/patches-4.19/950-0465-hwrng-iproc-rng200-Add-BCM2838-support.patch b/target/linux/brcm2708/patches-4.19/950-0465-hwrng-iproc-rng200-Add-BCM2838-support.patch
new file mode 100644 (file)
index 0000000..c2a29a0
--- /dev/null
@@ -0,0 +1,158 @@
+From e9c0fd87b6169baf5bd10293a85675d505086191 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 4 May 2019 17:06:15 +0200
+Subject: [PATCH] hwrng: iproc-rng200: Add BCM2838 support
+
+The HWRNG on the BCM2838 is compatible to iproc-rng200, so add the
+support to this driver instead of bcm2835-rng.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ drivers/char/hw_random/Kconfig        |  4 +-
+ drivers/char/hw_random/iproc-rng200.c | 81 +++++++++++++++++++++++++--
+ 2 files changed, 79 insertions(+), 6 deletions(-)
+
+--- a/drivers/char/hw_random/Kconfig
++++ b/drivers/char/hw_random/Kconfig
+@@ -89,11 +89,11 @@ config HW_RANDOM_BCM2835
+ config HW_RANDOM_IPROC_RNG200
+       tristate "Broadcom iProc/STB RNG200 support"
+-      depends on ARCH_BCM_IPROC || ARCH_BRCMSTB
++      depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB
+       default HW_RANDOM
+       ---help---
+         This driver provides kernel-side support for the RNG200
+-        hardware found on the Broadcom iProc and STB SoCs.
++        hardware found on the Broadcom iProc, BCM2838 and STB SoCs.
+         To compile this driver as a module, choose M here: the
+         module will be called iproc-rng200
+--- a/drivers/char/hw_random/iproc-rng200.c
++++ b/drivers/char/hw_random/iproc-rng200.c
+@@ -29,6 +29,7 @@
+ #define RNG_CTRL_RNG_RBGEN_MASK                               0x00001FFF
+ #define RNG_CTRL_RNG_RBGEN_ENABLE                     0x00000001
+ #define RNG_CTRL_RNG_RBGEN_DISABLE                    0x00000000
++#define RNG_CTRL_RNG_DIV_CTRL_SHIFT                   13
+ #define RNG_SOFT_RESET_OFFSET                         0x04
+ #define RNG_SOFT_RESET                                        0x00000001
+@@ -36,16 +37,23 @@
+ #define RBG_SOFT_RESET_OFFSET                         0x08
+ #define RBG_SOFT_RESET                                        0x00000001
++#define RNG_TOTAL_BIT_COUNT_OFFSET                    0x0C
++
++#define RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET          0x10
++
+ #define RNG_INT_STATUS_OFFSET                         0x18
+ #define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK   0x80000000
+ #define RNG_INT_STATUS_STARTUP_TRANSITIONS_MET_IRQ_MASK       0x00020000
+ #define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK             0x00000020
+ #define RNG_INT_STATUS_TOTAL_BITS_COUNT_IRQ_MASK      0x00000001
++#define RNG_INT_ENABLE_OFFSET                         0x1C
++
+ #define RNG_FIFO_DATA_OFFSET                          0x20
+ #define RNG_FIFO_COUNT_OFFSET                         0x24
+ #define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK            0x000000FF
++#define RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT               8
+ struct iproc_rng200_dev {
+       struct hwrng rng;
+@@ -166,6 +174,64 @@ static int iproc_rng200_init(struct hwrn
+       return 0;
+ }
++static int bcm2838_rng200_read(struct hwrng *rng, void *buf, size_t max,
++                             bool wait)
++{
++      struct iproc_rng200_dev *priv = to_rng_priv(rng);
++      u32 max_words = max / sizeof(u32);
++      u32 num_words, count, val;
++
++      /* ensure warm up period has elapsed */
++      while (1) {
++              val = ioread32(priv->base + RNG_TOTAL_BIT_COUNT_OFFSET);
++              if (val > 16)
++                      break;
++              cpu_relax();
++      }
++
++      /* ensure fifo is not empty */
++      while (1) {
++              num_words = ioread32(priv->base + RNG_FIFO_COUNT_OFFSET) &
++                          RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK;
++              if (num_words)
++                      break;
++              if (!wait)
++                      return 0;
++              cpu_relax();
++      }
++
++      if (num_words > max_words)
++              num_words = max_words;
++
++      for (count = 0; count < num_words; count++) {
++              ((u32 *)buf)[count] = ioread32(priv->base +
++                                             RNG_FIFO_DATA_OFFSET);
++      }
++
++      return num_words * sizeof(u32);
++}
++
++static int bcm2838_rng200_init(struct hwrng *rng)
++{
++      struct iproc_rng200_dev *priv = to_rng_priv(rng);
++      uint32_t val;
++
++      if (ioread32(priv->base + RNG_CTRL_OFFSET) & RNG_CTRL_RNG_RBGEN_MASK)
++              return 0;
++
++      /* initial numbers generated are "less random" so will be discarded */
++      val = 0x40000;
++      iowrite32(val, priv->base + RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET);
++      /* min fifo count to generate full interrupt */
++      val = 2 << RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT;
++      iowrite32(val, priv->base + RNG_FIFO_COUNT_OFFSET);
++      /* enable the rng - 1Mhz sample rate */
++      val = (0x3 << RNG_CTRL_RNG_DIV_CTRL_SHIFT) | RNG_CTRL_RNG_RBGEN_MASK;
++      iowrite32(val, priv->base + RNG_CTRL_OFFSET);
++
++      return 0;
++}
++
+ static void iproc_rng200_cleanup(struct hwrng *rng)
+ {
+       struct iproc_rng200_dev *priv = to_rng_priv(rng);
+@@ -202,10 +268,16 @@ static int iproc_rng200_probe(struct pla
+               return PTR_ERR(priv->base);
+       }
+-      priv->rng.name = "iproc-rng200",
+-      priv->rng.read = iproc_rng200_read,
+-      priv->rng.init = iproc_rng200_init,
+-      priv->rng.cleanup = iproc_rng200_cleanup,
++      priv->rng.name = pdev->name;
++      priv->rng.cleanup = iproc_rng200_cleanup;
++
++      if (of_device_is_compatible(dev->of_node, "brcm,bcm2838-rng200")) {
++              priv->rng.init = bcm2838_rng200_init;
++              priv->rng.read = bcm2838_rng200_read;
++      } else {
++              priv->rng.init = iproc_rng200_init;
++              priv->rng.read = iproc_rng200_read;
++      }
+       /* Register driver */
+       ret = devm_hwrng_register(dev, &priv->rng);
+@@ -222,6 +294,7 @@ static int iproc_rng200_probe(struct pla
+ static const struct of_device_id iproc_rng200_of_match[] = {
+       { .compatible = "brcm,bcm7278-rng200", },
+       { .compatible = "brcm,iproc-rng200", },
++      { .compatible = "brcm,bcm2838-rng200"},
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, iproc_rng200_of_match);
diff --git a/target/linux/brcm2708/patches-4.19/950-0465-mmc-sdhci-Mask-spurious-interrupts.patch b/target/linux/brcm2708/patches-4.19/950-0465-mmc-sdhci-Mask-spurious-interrupts.patch
deleted file mode 100644 (file)
index fd5cb52..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From be309b7db77215610d5ac15bf0aacd47ea5b3433 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 28 Sep 2018 16:24:05 +0100
-Subject: [PATCH] mmc: sdhci: Mask "spurious" interrupts
-
-Add a filter for "spurious" Transfer Complete interrupts, attempting
-to make it as specific as possible:
-* INT_DATA_END (transfer complete) is set
-* There is a stop command in progress
-* There is no data transfer in progress
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/sdhci.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/mmc/host/sdhci.c
-+++ b/drivers/mmc/host/sdhci.c
-@@ -2935,6 +2935,10 @@ static irqreturn_t sdhci_irq(int irq, vo
-                       result = IRQ_WAKE_THREAD;
-               }
-+              if ((intmask & SDHCI_INT_DATA_END) && !host->data &&
-+                  host->cmd && (host->cmd == host->cmd->mrq->stop))
-+                      intmask &= ~SDHCI_INT_DATA_END;
-+
-               if (intmask & SDHCI_INT_CMD_MASK)
-                       sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
diff --git a/target/linux/brcm2708/patches-4.19/950-0466-mmc-sdhci-iproc-Add-support-for-emmc2-of-the-BCM2838.patch b/target/linux/brcm2708/patches-4.19/950-0466-mmc-sdhci-iproc-Add-support-for-emmc2-of-the-BCM2838.patch
deleted file mode 100644 (file)
index d960766..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From 0a1c3ff378e60f2a59153cfc1c7529bfe05eb115 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 27 Apr 2019 12:33:57 +0200
-Subject: [PATCH] mmc: sdhci-iproc: Add support for emmc2 of the
- BCM2838
-
-The emmc2 interface of the BCM2838 should be integrated in sdhci-iproc
-to avoid code redundancy. Except 32 bit only access no other quirks are
-known yet. Add an additional compatible string for upstream proposal.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- drivers/mmc/host/sdhci-iproc.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/mmc/host/sdhci-iproc.c
-+++ b/drivers/mmc/host/sdhci-iproc.c
-@@ -250,8 +250,18 @@ static const struct sdhci_iproc_data bcm
-       .mmc_caps = 0x00000000,
- };
-+static const struct sdhci_pltfm_data sdhci_bcm2838_pltfm_data = {
-+      .ops = &sdhci_iproc_32only_ops,
-+};
-+
-+static const struct sdhci_iproc_data bcm2838_data = {
-+      .pdata = &sdhci_bcm2838_pltfm_data,
-+};
-+
- static const struct of_device_id sdhci_iproc_of_match[] = {
-       { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
-+      { .compatible = "brcm,bcm2838-sdhci", .data = &bcm2838_data },
-+      { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2838_data },
-       { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
-       { .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
-       { }
diff --git a/target/linux/brcm2708/patches-4.19/950-0466-thermal-brcmstb_thermal-Add-BCM2838-support.patch b/target/linux/brcm2708/patches-4.19/950-0466-thermal-brcmstb_thermal-Add-BCM2838-support.patch
new file mode 100644 (file)
index 0000000..6bc76ed
--- /dev/null
@@ -0,0 +1,162 @@
+From d49649e2dcf0d5775e92677d37e229e0387fe82a Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 18 May 2019 12:26:11 +0200
+Subject: [PATCH] thermal: brcmstb_thermal: Add BCM2838 support
+
+The BCM2838 has an AVS TMON hardware block. This adds the necessary
+support to the brcmstb_thermal driver ( no trip handling ).
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ drivers/thermal/broadcom/Kconfig           |  2 +-
+ drivers/thermal/broadcom/brcmstb_thermal.c | 65 +++++++++++++++++++---
+ 2 files changed, 58 insertions(+), 9 deletions(-)
+
+--- a/drivers/thermal/broadcom/Kconfig
++++ b/drivers/thermal/broadcom/Kconfig
+@@ -8,7 +8,7 @@ config BCM2835_THERMAL
+ config BRCMSTB_THERMAL
+       tristate "Broadcom STB AVS TMON thermal driver"
+-      depends on ARCH_BRCMSTB || COMPILE_TEST
++      depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
+       help
+         Enable this driver if you have a Broadcom STB SoC and would like
+         thermal framework support.
+--- a/drivers/thermal/broadcom/brcmstb_thermal.c
++++ b/drivers/thermal/broadcom/brcmstb_thermal.c
+@@ -19,6 +19,7 @@
+ #define pr_fmt(fmt)   DRV_NAME ": " fmt
+ #include <linux/bitops.h>
++#include <linux/clk.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
+ #include <linux/io.h>
+@@ -31,9 +32,6 @@
+ #include <linux/thermal.h>
+ #define AVS_TMON_STATUS                       0x00
+- #define AVS_TMON_STATUS_valid_msk    BIT(11)
+- #define AVS_TMON_STATUS_data_msk     GENMASK(10, 1)
+- #define AVS_TMON_STATUS_data_shift   1
+ #define AVS_TMON_EN_OVERTEMP_RESET    0x04
+  #define AVS_TMON_EN_OVERTEMP_RESET_msk       BIT(0)
+@@ -111,10 +109,19 @@ static struct avs_tmon_trip avs_tmon_tri
+       },
+ };
++struct brcmstb_thermal_of_data {
++      const struct thermal_zone_of_device_ops *of_ops;
++      u32 status_valid_mask;
++      u32 status_data_mask;
++      u32 status_data_shift;
++};
++
+ struct brcmstb_thermal_priv {
+       void __iomem *tmon_base;
+       struct device *dev;
+       struct thermal_zone_device *thermal;
++      struct clk *clk;
++      const struct brcmstb_thermal_of_data *socdata;
+ };
+ static void avs_tmon_get_coeffs(struct thermal_zone_device *tz, int *slope,
+@@ -164,17 +171,18 @@ static inline u32 avs_tmon_temp_to_code(
+ static int brcmstb_get_temp(void *data, int *temp)
+ {
+       struct brcmstb_thermal_priv *priv = data;
++      const struct brcmstb_thermal_of_data *socdata = priv->socdata;
+       u32 val;
+       long t;
+       val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS);
+-      if (!(val & AVS_TMON_STATUS_valid_msk)) {
++      if (!(val & socdata->status_valid_mask)) {
+               dev_err(priv->dev, "reading not valid\n");
+               return -EIO;
+       }
+-      val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift;
++      val = (val & socdata->status_data_mask) >> socdata->status_data_shift;
+       t = avs_tmon_code_to_temp(priv->thermal, val);
+       if (t < 0)
+@@ -299,13 +307,34 @@ static int brcmstb_set_trips(void *data,
+       return 0;
+ }
+-static struct thermal_zone_of_device_ops of_ops = {
++static const struct thermal_zone_of_device_ops bcm7445_thermal_of_ops = {
+       .get_temp       = brcmstb_get_temp,
+       .set_trips      = brcmstb_set_trips,
+ };
++static const struct thermal_zone_of_device_ops bcm2838_thermal_of_ops = {
++      .get_temp       = brcmstb_get_temp,
++};
++
++static const struct brcmstb_thermal_of_data bcm7445_thermal_of_data = {
++      .of_ops = &bcm7445_thermal_of_ops,
++      .status_valid_mask = BIT(11),
++      .status_data_mask = GENMASK(10, 1),
++      .status_data_shift = 1,
++};
++
++static const struct brcmstb_thermal_of_data bcm2838_thermal_of_data = {
++      .of_ops = &bcm2838_thermal_of_ops,
++      .status_valid_mask = BIT(10),
++      .status_data_mask = GENMASK(9, 0),
++      .status_data_shift = 0,
++};
++
+ static const struct of_device_id brcmstb_thermal_id_table[] = {
+-      { .compatible = "brcm,avs-tmon" },
++      { .compatible = "brcm,avs-tmon",
++        .data = &bcm7445_thermal_of_data },
++      { .compatible = "brcm,avs-tmon-bcm2838",
++        .data = &bcm2838_thermal_of_data },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table);
+@@ -326,10 +355,27 @@ static int brcmstb_thermal_probe(struct
+       if (IS_ERR(priv->tmon_base))
+               return PTR_ERR(priv->tmon_base);
++      priv->socdata = of_device_get_match_data(&pdev->dev);
++      if (!priv->socdata) {
++              dev_err(&pdev->dev, "no device match found\n");
++              return -ENODEV;
++      }
++
++      priv->clk = devm_clk_get(&pdev->dev, NULL);
++      if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
++              return -EPROBE_DEFER;
++
++      if (!IS_ERR(priv->clk)) {
++              ret = clk_prepare_enable(priv->clk);
++              if (ret)
++                      return ret;
++      }
++
+       priv->dev = &pdev->dev;
+       platform_set_drvdata(pdev, priv);
+-      thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &of_ops);
++      thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv,
++                                                priv->socdata->of_ops);
+       if (IS_ERR(thermal)) {
+               ret = PTR_ERR(thermal);
+               dev_err(&pdev->dev, "could not register sensor: %d\n", ret);
+@@ -369,6 +415,9 @@ static int brcmstb_thermal_exit(struct p
+       if (thermal)
+               thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal);
++      if (!IS_ERR(priv->clk))
++              clk_disable_unprepare(priv->clk);
++
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0467-hwrng-iproc-rng200-Add-BCM2838-support.patch b/target/linux/brcm2708/patches-4.19/950-0467-hwrng-iproc-rng200-Add-BCM2838-support.patch
deleted file mode 100644 (file)
index c2a29a0..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-From e9c0fd87b6169baf5bd10293a85675d505086191 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 4 May 2019 17:06:15 +0200
-Subject: [PATCH] hwrng: iproc-rng200: Add BCM2838 support
-
-The HWRNG on the BCM2838 is compatible to iproc-rng200, so add the
-support to this driver instead of bcm2835-rng.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- drivers/char/hw_random/Kconfig        |  4 +-
- drivers/char/hw_random/iproc-rng200.c | 81 +++++++++++++++++++++++++--
- 2 files changed, 79 insertions(+), 6 deletions(-)
-
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -89,11 +89,11 @@ config HW_RANDOM_BCM2835
- config HW_RANDOM_IPROC_RNG200
-       tristate "Broadcom iProc/STB RNG200 support"
--      depends on ARCH_BCM_IPROC || ARCH_BRCMSTB
-+      depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB
-       default HW_RANDOM
-       ---help---
-         This driver provides kernel-side support for the RNG200
--        hardware found on the Broadcom iProc and STB SoCs.
-+        hardware found on the Broadcom iProc, BCM2838 and STB SoCs.
-         To compile this driver as a module, choose M here: the
-         module will be called iproc-rng200
---- a/drivers/char/hw_random/iproc-rng200.c
-+++ b/drivers/char/hw_random/iproc-rng200.c
-@@ -29,6 +29,7 @@
- #define RNG_CTRL_RNG_RBGEN_MASK                               0x00001FFF
- #define RNG_CTRL_RNG_RBGEN_ENABLE                     0x00000001
- #define RNG_CTRL_RNG_RBGEN_DISABLE                    0x00000000
-+#define RNG_CTRL_RNG_DIV_CTRL_SHIFT                   13
- #define RNG_SOFT_RESET_OFFSET                         0x04
- #define RNG_SOFT_RESET                                        0x00000001
-@@ -36,16 +37,23 @@
- #define RBG_SOFT_RESET_OFFSET                         0x08
- #define RBG_SOFT_RESET                                        0x00000001
-+#define RNG_TOTAL_BIT_COUNT_OFFSET                    0x0C
-+
-+#define RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET          0x10
-+
- #define RNG_INT_STATUS_OFFSET                         0x18
- #define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK   0x80000000
- #define RNG_INT_STATUS_STARTUP_TRANSITIONS_MET_IRQ_MASK       0x00020000
- #define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK             0x00000020
- #define RNG_INT_STATUS_TOTAL_BITS_COUNT_IRQ_MASK      0x00000001
-+#define RNG_INT_ENABLE_OFFSET                         0x1C
-+
- #define RNG_FIFO_DATA_OFFSET                          0x20
- #define RNG_FIFO_COUNT_OFFSET                         0x24
- #define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK            0x000000FF
-+#define RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT               8
- struct iproc_rng200_dev {
-       struct hwrng rng;
-@@ -166,6 +174,64 @@ static int iproc_rng200_init(struct hwrn
-       return 0;
- }
-+static int bcm2838_rng200_read(struct hwrng *rng, void *buf, size_t max,
-+                             bool wait)
-+{
-+      struct iproc_rng200_dev *priv = to_rng_priv(rng);
-+      u32 max_words = max / sizeof(u32);
-+      u32 num_words, count, val;
-+
-+      /* ensure warm up period has elapsed */
-+      while (1) {
-+              val = ioread32(priv->base + RNG_TOTAL_BIT_COUNT_OFFSET);
-+              if (val > 16)
-+                      break;
-+              cpu_relax();
-+      }
-+
-+      /* ensure fifo is not empty */
-+      while (1) {
-+              num_words = ioread32(priv->base + RNG_FIFO_COUNT_OFFSET) &
-+                          RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK;
-+              if (num_words)
-+                      break;
-+              if (!wait)
-+                      return 0;
-+              cpu_relax();
-+      }
-+
-+      if (num_words > max_words)
-+              num_words = max_words;
-+
-+      for (count = 0; count < num_words; count++) {
-+              ((u32 *)buf)[count] = ioread32(priv->base +
-+                                             RNG_FIFO_DATA_OFFSET);
-+      }
-+
-+      return num_words * sizeof(u32);
-+}
-+
-+static int bcm2838_rng200_init(struct hwrng *rng)
-+{
-+      struct iproc_rng200_dev *priv = to_rng_priv(rng);
-+      uint32_t val;
-+
-+      if (ioread32(priv->base + RNG_CTRL_OFFSET) & RNG_CTRL_RNG_RBGEN_MASK)
-+              return 0;
-+
-+      /* initial numbers generated are "less random" so will be discarded */
-+      val = 0x40000;
-+      iowrite32(val, priv->base + RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET);
-+      /* min fifo count to generate full interrupt */
-+      val = 2 << RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT;
-+      iowrite32(val, priv->base + RNG_FIFO_COUNT_OFFSET);
-+      /* enable the rng - 1Mhz sample rate */
-+      val = (0x3 << RNG_CTRL_RNG_DIV_CTRL_SHIFT) | RNG_CTRL_RNG_RBGEN_MASK;
-+      iowrite32(val, priv->base + RNG_CTRL_OFFSET);
-+
-+      return 0;
-+}
-+
- static void iproc_rng200_cleanup(struct hwrng *rng)
- {
-       struct iproc_rng200_dev *priv = to_rng_priv(rng);
-@@ -202,10 +268,16 @@ static int iproc_rng200_probe(struct pla
-               return PTR_ERR(priv->base);
-       }
--      priv->rng.name = "iproc-rng200",
--      priv->rng.read = iproc_rng200_read,
--      priv->rng.init = iproc_rng200_init,
--      priv->rng.cleanup = iproc_rng200_cleanup,
-+      priv->rng.name = pdev->name;
-+      priv->rng.cleanup = iproc_rng200_cleanup;
-+
-+      if (of_device_is_compatible(dev->of_node, "brcm,bcm2838-rng200")) {
-+              priv->rng.init = bcm2838_rng200_init;
-+              priv->rng.read = bcm2838_rng200_read;
-+      } else {
-+              priv->rng.init = iproc_rng200_init;
-+              priv->rng.read = iproc_rng200_read;
-+      }
-       /* Register driver */
-       ret = devm_hwrng_register(dev, &priv->rng);
-@@ -222,6 +294,7 @@ static int iproc_rng200_probe(struct pla
- static const struct of_device_id iproc_rng200_of_match[] = {
-       { .compatible = "brcm,bcm7278-rng200", },
-       { .compatible = "brcm,iproc-rng200", },
-+      { .compatible = "brcm,bcm2838-rng200"},
-       {},
- };
- MODULE_DEVICE_TABLE(of, iproc_rng200_of_match);
diff --git a/target/linux/brcm2708/patches-4.19/950-0467-vchiq-Add-36-bit-address-support.patch b/target/linux/brcm2708/patches-4.19/950-0467-vchiq-Add-36-bit-address-support.patch
new file mode 100644 (file)
index 0000000..e1eec5d
--- /dev/null
@@ -0,0 +1,196 @@
+From d5c6191cc94b358de183cc8c88a5722a79445202 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 1 Nov 2018 17:31:37 +0000
+Subject: [PATCH] vchiq: Add 36-bit address support
+
+Conditional on a new compatible string, change the pagelist encoding
+such that the top 24 bits are the pfn, leaving 8 bits for run length
+(-1).
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../interface/vchiq_arm/vchiq_2835_arm.c      | 90 ++++++++++++++-----
+ .../interface/vchiq_arm/vchiq_arm.c           |  6 ++
+ .../interface/vchiq_arm/vchiq_arm.h           |  1 +
+ 3 files changed, 75 insertions(+), 22 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+@@ -47,6 +47,8 @@
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+ #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
++#define VC_SAFE(x) (g_use_36bit_addrs ? ((u32)(x) | 0xc0000000) : (u32)(x))
++#define IS_VC_SAFE(x) (g_use_36bit_addrs ? !((x) & ~0x3fffffffull) : 1)
+ #include "vchiq_arm.h"
+ #include "vchiq_connected.h"
+@@ -96,6 +98,7 @@ static void __iomem *g_regs;
+  */
+ static unsigned int g_cache_line_size;
+ static struct dma_pool *g_dma_pool;
++static unsigned int g_use_36bit_addrs = 0;
+ static unsigned int g_fragments_size;
+ static char *g_fragments_base;
+ static char *g_free_fragments;
+@@ -139,6 +142,8 @@ int vchiq_platform_init(struct platform_
+       g_cache_line_size = drvdata->cache_line_size;
+       g_fragments_size = 2 * g_cache_line_size;
++      g_use_36bit_addrs = (dev->dma_pfn_offset == 0);
++
+       /* Allocate space for the channels in coherent memory */
+       slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
+       frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);
+@@ -150,14 +155,21 @@ int vchiq_platform_init(struct platform_
+               return -ENOMEM;
+       }
++      if (!IS_VC_SAFE(slot_phys)) {
++              dev_err(dev, "allocated DMA memory %pad is not VC-safe\n",
++                      &slot_phys);
++              return -ENOMEM;
++      }
++
+       WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0);
++      channelbase = VC_SAFE(slot_phys);
+       vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
+       if (!vchiq_slot_zero)
+               return -EINVAL;
+       vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
+-              (int)slot_phys + slot_mem_size;
++              channelbase + slot_mem_size;
+       vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
+               MAX_FRAGMENTS;
+@@ -193,7 +205,6 @@ int vchiq_platform_init(struct platform_
+       }
+       /* Send the base address of the slots to VideoCore */
+-      channelbase = slot_phys;
+       err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT,
+                                   &channelbase, sizeof(channelbase));
+       if (err || channelbase) {
+@@ -282,7 +293,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
+               return VCHIQ_ERROR;
+       bulk->handle = memhandle;
+-      bulk->data = (void *)(unsigned long)pagelistinfo->dma_addr;
++      bulk->data = (void *)VC_SAFE(pagelistinfo->dma_addr);
+       /*
+        * Store the pagelistinfo address in remote_data,
+@@ -570,25 +581,60 @@ create_pagelist(char __user *buf, size_t
+       /* Combine adjacent blocks for performance */
+       k = 0;
+-      for_each_sg(scatterlist, sg, dma_buffers, i) {
+-              u32 len = sg_dma_len(sg);
+-              u32 addr = sg_dma_address(sg);
+-
+-              /* Note: addrs is the address + page_count - 1
+-               * The firmware expects blocks after the first to be page-
+-               * aligned and a multiple of the page size
+-               */
+-              WARN_ON(len == 0);
+-              WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
+-              WARN_ON(i && (addr & ~PAGE_MASK));
+-              if (k > 0 &&
+-                  ((addrs[k - 1] & PAGE_MASK) +
+-                   (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
+-                  == (addr & PAGE_MASK))
+-                      addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
+-              else
+-                      addrs[k++] = (addr & PAGE_MASK) |
+-                              (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
++      if (g_use_36bit_addrs) {
++              for_each_sg(scatterlist, sg, dma_buffers, i) {
++                      u32 len = sg_dma_len(sg);
++                      u64 addr = sg_dma_address(sg);
++                      u32 page_id = (u32)((addr >> 4) & ~0xff);
++                      u32 sg_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++                      /* Note: addrs is the address + page_count - 1
++                       * The firmware expects blocks after the first to be page-
++                       * aligned and a multiple of the page size
++                       */
++                      WARN_ON(len == 0);
++                      WARN_ON(i &&
++                              (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
++                      WARN_ON(i && (addr & ~PAGE_MASK));
++                      WARN_ON(upper_32_bits(addr) > 0xf);
++                      if (k > 0 &&
++                          ((addrs[k - 1] & ~0xff) +
++                           (((addrs[k - 1] & 0xff) + 1) << 8)
++                           == page_id)) {
++                              u32 inc_pages = min(sg_pages,
++                                                  0xff - (addrs[k - 1] & 0xff));
++                              addrs[k - 1] += inc_pages;
++                              page_id += inc_pages << 8;
++                              sg_pages -= inc_pages;
++                      }
++                      while (sg_pages) {
++                              u32 inc_pages = min(sg_pages, 0x100u);
++                              addrs[k++] = page_id | (inc_pages - 1);
++                              page_id += inc_pages << 8;
++                              sg_pages -= inc_pages;
++                      }
++              }
++      } else {
++              for_each_sg(scatterlist, sg, dma_buffers, i) {
++                      u32 len = sg_dma_len(sg);
++                      u32 addr = VC_SAFE(sg_dma_address(sg));
++                      u32 new_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++                      /* Note: addrs is the address + page_count - 1
++                       * The firmware expects blocks after the first to be page-
++                       * aligned and a multiple of the page size
++                       */
++                      WARN_ON(len == 0);
++                      WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
++                      WARN_ON(i && (addr & ~PAGE_MASK));
++                      if (k > 0 &&
++                          ((addrs[k - 1] & PAGE_MASK) +
++                           (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
++                          == (addr & PAGE_MASK))
++                              addrs[k - 1] += new_pages;
++                      else
++                              addrs[k++] = (addr & PAGE_MASK) | (new_pages - 1);
++              }
+       }
+       /* Partial cache lines (fragments) require special measures */
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -181,6 +181,11 @@ static struct vchiq_drvdata bcm2836_drvd
+       .cache_line_size = 64,
+ };
++static struct vchiq_drvdata bcm2838_drvdata = {
++      .cache_line_size = 64,
++      .use_36bit_addrs = true,
++};
++
+ static const char *const ioctl_names[] = {
+       "CONNECT",
+       "SHUTDOWN",
+@@ -3618,6 +3623,7 @@ vchiq_register_child(struct platform_dev
+ static const struct of_device_id vchiq_of_match[] = {
+       { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
+       { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
++      { .compatible = "brcm,bcm2838-vchiq", .data = &bcm2838_drvdata },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, vchiq_of_match);
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+@@ -125,6 +125,7 @@ typedef struct vchiq_arm_state_struct {
+ struct vchiq_drvdata {
+       const unsigned int cache_line_size;
++      const bool use_36bit_addrs;
+       struct rpi_firmware *fw;
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0468-bcm2835-pcm.c-Support-multichannel-audio.patch b/target/linux/brcm2708/patches-4.19/950-0468-bcm2835-pcm.c-Support-multichannel-audio.patch
new file mode 100644 (file)
index 0000000..47898db
--- /dev/null
@@ -0,0 +1,46 @@
+From 69d7e7d0f958186a0f7667ebeefdb50d1c5c3bd3 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 30 Apr 2019 19:15:30 +0100
+Subject: [PATCH] bcm2835-pcm.c: Support multichannel audio
+
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c   | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -14,9 +14,9 @@ static const struct snd_pcm_hardware snd
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+       .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+-      .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
++      .rates = SNDRV_PCM_RATE_CONTINUOUS |  SNDRV_PCM_RATE_8000_192000,
+       .rate_min = 8000,
+-      .rate_max = 48000,
++      .rate_max = 192000,
+       .channels_min = 1,
+       .channels_max = 2,
+       .buffer_bytes_max = 128 * 1024,
+@@ -31,15 +31,16 @@ static const struct snd_pcm_hardware snd
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+-      .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
+-      SNDRV_PCM_RATE_48000,
++      .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,
+       .rate_min = 44100,
+-      .rate_max = 48000,
++      .rate_max = 192000,
+       .channels_min = 2,
+-      .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,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0468-thermal-brcmstb_thermal-Add-BCM2838-support.patch b/target/linux/brcm2708/patches-4.19/950-0468-thermal-brcmstb_thermal-Add-BCM2838-support.patch
deleted file mode 100644 (file)
index 6bc76ed..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-From d49649e2dcf0d5775e92677d37e229e0387fe82a Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 18 May 2019 12:26:11 +0200
-Subject: [PATCH] thermal: brcmstb_thermal: Add BCM2838 support
-
-The BCM2838 has an AVS TMON hardware block. This adds the necessary
-support to the brcmstb_thermal driver ( no trip handling ).
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- drivers/thermal/broadcom/Kconfig           |  2 +-
- drivers/thermal/broadcom/brcmstb_thermal.c | 65 +++++++++++++++++++---
- 2 files changed, 58 insertions(+), 9 deletions(-)
-
---- a/drivers/thermal/broadcom/Kconfig
-+++ b/drivers/thermal/broadcom/Kconfig
-@@ -8,7 +8,7 @@ config BCM2835_THERMAL
- config BRCMSTB_THERMAL
-       tristate "Broadcom STB AVS TMON thermal driver"
--      depends on ARCH_BRCMSTB || COMPILE_TEST
-+      depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
-       help
-         Enable this driver if you have a Broadcom STB SoC and would like
-         thermal framework support.
---- a/drivers/thermal/broadcom/brcmstb_thermal.c
-+++ b/drivers/thermal/broadcom/brcmstb_thermal.c
-@@ -19,6 +19,7 @@
- #define pr_fmt(fmt)   DRV_NAME ": " fmt
- #include <linux/bitops.h>
-+#include <linux/clk.h>
- #include <linux/device.h>
- #include <linux/err.h>
- #include <linux/io.h>
-@@ -31,9 +32,6 @@
- #include <linux/thermal.h>
- #define AVS_TMON_STATUS                       0x00
-- #define AVS_TMON_STATUS_valid_msk    BIT(11)
-- #define AVS_TMON_STATUS_data_msk     GENMASK(10, 1)
-- #define AVS_TMON_STATUS_data_shift   1
- #define AVS_TMON_EN_OVERTEMP_RESET    0x04
-  #define AVS_TMON_EN_OVERTEMP_RESET_msk       BIT(0)
-@@ -111,10 +109,19 @@ static struct avs_tmon_trip avs_tmon_tri
-       },
- };
-+struct brcmstb_thermal_of_data {
-+      const struct thermal_zone_of_device_ops *of_ops;
-+      u32 status_valid_mask;
-+      u32 status_data_mask;
-+      u32 status_data_shift;
-+};
-+
- struct brcmstb_thermal_priv {
-       void __iomem *tmon_base;
-       struct device *dev;
-       struct thermal_zone_device *thermal;
-+      struct clk *clk;
-+      const struct brcmstb_thermal_of_data *socdata;
- };
- static void avs_tmon_get_coeffs(struct thermal_zone_device *tz, int *slope,
-@@ -164,17 +171,18 @@ static inline u32 avs_tmon_temp_to_code(
- static int brcmstb_get_temp(void *data, int *temp)
- {
-       struct brcmstb_thermal_priv *priv = data;
-+      const struct brcmstb_thermal_of_data *socdata = priv->socdata;
-       u32 val;
-       long t;
-       val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS);
--      if (!(val & AVS_TMON_STATUS_valid_msk)) {
-+      if (!(val & socdata->status_valid_mask)) {
-               dev_err(priv->dev, "reading not valid\n");
-               return -EIO;
-       }
--      val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift;
-+      val = (val & socdata->status_data_mask) >> socdata->status_data_shift;
-       t = avs_tmon_code_to_temp(priv->thermal, val);
-       if (t < 0)
-@@ -299,13 +307,34 @@ static int brcmstb_set_trips(void *data,
-       return 0;
- }
--static struct thermal_zone_of_device_ops of_ops = {
-+static const struct thermal_zone_of_device_ops bcm7445_thermal_of_ops = {
-       .get_temp       = brcmstb_get_temp,
-       .set_trips      = brcmstb_set_trips,
- };
-+static const struct thermal_zone_of_device_ops bcm2838_thermal_of_ops = {
-+      .get_temp       = brcmstb_get_temp,
-+};
-+
-+static const struct brcmstb_thermal_of_data bcm7445_thermal_of_data = {
-+      .of_ops = &bcm7445_thermal_of_ops,
-+      .status_valid_mask = BIT(11),
-+      .status_data_mask = GENMASK(10, 1),
-+      .status_data_shift = 1,
-+};
-+
-+static const struct brcmstb_thermal_of_data bcm2838_thermal_of_data = {
-+      .of_ops = &bcm2838_thermal_of_ops,
-+      .status_valid_mask = BIT(10),
-+      .status_data_mask = GENMASK(9, 0),
-+      .status_data_shift = 0,
-+};
-+
- static const struct of_device_id brcmstb_thermal_id_table[] = {
--      { .compatible = "brcm,avs-tmon" },
-+      { .compatible = "brcm,avs-tmon",
-+        .data = &bcm7445_thermal_of_data },
-+      { .compatible = "brcm,avs-tmon-bcm2838",
-+        .data = &bcm2838_thermal_of_data },
-       {},
- };
- MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table);
-@@ -326,10 +355,27 @@ static int brcmstb_thermal_probe(struct
-       if (IS_ERR(priv->tmon_base))
-               return PTR_ERR(priv->tmon_base);
-+      priv->socdata = of_device_get_match_data(&pdev->dev);
-+      if (!priv->socdata) {
-+              dev_err(&pdev->dev, "no device match found\n");
-+              return -ENODEV;
-+      }
-+
-+      priv->clk = devm_clk_get(&pdev->dev, NULL);
-+      if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
-+              return -EPROBE_DEFER;
-+
-+      if (!IS_ERR(priv->clk)) {
-+              ret = clk_prepare_enable(priv->clk);
-+              if (ret)
-+                      return ret;
-+      }
-+
-       priv->dev = &pdev->dev;
-       platform_set_drvdata(pdev, priv);
--      thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &of_ops);
-+      thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv,
-+                                                priv->socdata->of_ops);
-       if (IS_ERR(thermal)) {
-               ret = PTR_ERR(thermal);
-               dev_err(&pdev->dev, "could not register sensor: %d\n", ret);
-@@ -369,6 +415,9 @@ static int brcmstb_thermal_exit(struct p
-       if (thermal)
-               thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal);
-+      if (!IS_ERR(priv->clk))
-+              clk_disable_unprepare(priv->clk);
-+
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0469-bcmgenet-constrain-max-DMA-burst-length.patch b/target/linux/brcm2708/patches-4.19/950-0469-bcmgenet-constrain-max-DMA-burst-length.patch
new file mode 100644 (file)
index 0000000..54ead87
--- /dev/null
@@ -0,0 +1,20 @@
+From 12865021c91e21ca7189c6a84688459d400de204 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 12 Sep 2018 14:44:53 +0100
+Subject: [PATCH] bcmgenet: constrain max DMA burst length
+
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+@@ -31,7 +31,7 @@
+ #define ENET_PAD              8
+ #define ENET_MAX_MTU_SIZE     (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
+                                ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
+-#define DMA_MAX_BURST_LENGTH    0x10
++#define DMA_MAX_BURST_LENGTH    0x08
+ /* misc. configuration */
+ #define CLEAR_ALL_HFB                 0xFF
diff --git a/target/linux/brcm2708/patches-4.19/950-0469-vchiq-Add-36-bit-address-support.patch b/target/linux/brcm2708/patches-4.19/950-0469-vchiq-Add-36-bit-address-support.patch
deleted file mode 100644 (file)
index e1eec5d..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-From d5c6191cc94b358de183cc8c88a5722a79445202 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 1 Nov 2018 17:31:37 +0000
-Subject: [PATCH] vchiq: Add 36-bit address support
-
-Conditional on a new compatible string, change the pagelist encoding
-such that the top 24 bits are the pfn, leaving 8 bits for run length
-(-1).
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../interface/vchiq_arm/vchiq_2835_arm.c      | 90 ++++++++++++++-----
- .../interface/vchiq_arm/vchiq_arm.c           |  6 ++
- .../interface/vchiq_arm/vchiq_arm.h           |  1 +
- 3 files changed, 75 insertions(+), 22 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-@@ -47,6 +47,8 @@
- #include <soc/bcm2835/raspberrypi-firmware.h>
- #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
-+#define VC_SAFE(x) (g_use_36bit_addrs ? ((u32)(x) | 0xc0000000) : (u32)(x))
-+#define IS_VC_SAFE(x) (g_use_36bit_addrs ? !((x) & ~0x3fffffffull) : 1)
- #include "vchiq_arm.h"
- #include "vchiq_connected.h"
-@@ -96,6 +98,7 @@ static void __iomem *g_regs;
-  */
- static unsigned int g_cache_line_size;
- static struct dma_pool *g_dma_pool;
-+static unsigned int g_use_36bit_addrs = 0;
- static unsigned int g_fragments_size;
- static char *g_fragments_base;
- static char *g_free_fragments;
-@@ -139,6 +142,8 @@ int vchiq_platform_init(struct platform_
-       g_cache_line_size = drvdata->cache_line_size;
-       g_fragments_size = 2 * g_cache_line_size;
-+      g_use_36bit_addrs = (dev->dma_pfn_offset == 0);
-+
-       /* Allocate space for the channels in coherent memory */
-       slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
-       frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);
-@@ -150,14 +155,21 @@ int vchiq_platform_init(struct platform_
-               return -ENOMEM;
-       }
-+      if (!IS_VC_SAFE(slot_phys)) {
-+              dev_err(dev, "allocated DMA memory %pad is not VC-safe\n",
-+                      &slot_phys);
-+              return -ENOMEM;
-+      }
-+
-       WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0);
-+      channelbase = VC_SAFE(slot_phys);
-       vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
-       if (!vchiq_slot_zero)
-               return -EINVAL;
-       vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
--              (int)slot_phys + slot_mem_size;
-+              channelbase + slot_mem_size;
-       vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
-               MAX_FRAGMENTS;
-@@ -193,7 +205,6 @@ int vchiq_platform_init(struct platform_
-       }
-       /* Send the base address of the slots to VideoCore */
--      channelbase = slot_phys;
-       err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT,
-                                   &channelbase, sizeof(channelbase));
-       if (err || channelbase) {
-@@ -282,7 +293,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
-               return VCHIQ_ERROR;
-       bulk->handle = memhandle;
--      bulk->data = (void *)(unsigned long)pagelistinfo->dma_addr;
-+      bulk->data = (void *)VC_SAFE(pagelistinfo->dma_addr);
-       /*
-        * Store the pagelistinfo address in remote_data,
-@@ -570,25 +581,60 @@ create_pagelist(char __user *buf, size_t
-       /* Combine adjacent blocks for performance */
-       k = 0;
--      for_each_sg(scatterlist, sg, dma_buffers, i) {
--              u32 len = sg_dma_len(sg);
--              u32 addr = sg_dma_address(sg);
--
--              /* Note: addrs is the address + page_count - 1
--               * The firmware expects blocks after the first to be page-
--               * aligned and a multiple of the page size
--               */
--              WARN_ON(len == 0);
--              WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
--              WARN_ON(i && (addr & ~PAGE_MASK));
--              if (k > 0 &&
--                  ((addrs[k - 1] & PAGE_MASK) +
--                   (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
--                  == (addr & PAGE_MASK))
--                      addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
--              else
--                      addrs[k++] = (addr & PAGE_MASK) |
--                              (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
-+      if (g_use_36bit_addrs) {
-+              for_each_sg(scatterlist, sg, dma_buffers, i) {
-+                      u32 len = sg_dma_len(sg);
-+                      u64 addr = sg_dma_address(sg);
-+                      u32 page_id = (u32)((addr >> 4) & ~0xff);
-+                      u32 sg_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-+
-+                      /* Note: addrs is the address + page_count - 1
-+                       * The firmware expects blocks after the first to be page-
-+                       * aligned and a multiple of the page size
-+                       */
-+                      WARN_ON(len == 0);
-+                      WARN_ON(i &&
-+                              (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
-+                      WARN_ON(i && (addr & ~PAGE_MASK));
-+                      WARN_ON(upper_32_bits(addr) > 0xf);
-+                      if (k > 0 &&
-+                          ((addrs[k - 1] & ~0xff) +
-+                           (((addrs[k - 1] & 0xff) + 1) << 8)
-+                           == page_id)) {
-+                              u32 inc_pages = min(sg_pages,
-+                                                  0xff - (addrs[k - 1] & 0xff));
-+                              addrs[k - 1] += inc_pages;
-+                              page_id += inc_pages << 8;
-+                              sg_pages -= inc_pages;
-+                      }
-+                      while (sg_pages) {
-+                              u32 inc_pages = min(sg_pages, 0x100u);
-+                              addrs[k++] = page_id | (inc_pages - 1);
-+                              page_id += inc_pages << 8;
-+                              sg_pages -= inc_pages;
-+                      }
-+              }
-+      } else {
-+              for_each_sg(scatterlist, sg, dma_buffers, i) {
-+                      u32 len = sg_dma_len(sg);
-+                      u32 addr = VC_SAFE(sg_dma_address(sg));
-+                      u32 new_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-+
-+                      /* Note: addrs is the address + page_count - 1
-+                       * The firmware expects blocks after the first to be page-
-+                       * aligned and a multiple of the page size
-+                       */
-+                      WARN_ON(len == 0);
-+                      WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
-+                      WARN_ON(i && (addr & ~PAGE_MASK));
-+                      if (k > 0 &&
-+                          ((addrs[k - 1] & PAGE_MASK) +
-+                           (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
-+                          == (addr & PAGE_MASK))
-+                              addrs[k - 1] += new_pages;
-+                      else
-+                              addrs[k++] = (addr & PAGE_MASK) | (new_pages - 1);
-+              }
-       }
-       /* Partial cache lines (fragments) require special measures */
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -181,6 +181,11 @@ static struct vchiq_drvdata bcm2836_drvd
-       .cache_line_size = 64,
- };
-+static struct vchiq_drvdata bcm2838_drvdata = {
-+      .cache_line_size = 64,
-+      .use_36bit_addrs = true,
-+};
-+
- static const char *const ioctl_names[] = {
-       "CONNECT",
-       "SHUTDOWN",
-@@ -3618,6 +3623,7 @@ vchiq_register_child(struct platform_dev
- static const struct of_device_id vchiq_of_match[] = {
-       { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
-       { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
-+      { .compatible = "brcm,bcm2838-vchiq", .data = &bcm2838_drvdata },
-       {},
- };
- MODULE_DEVICE_TABLE(of, vchiq_of_match);
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-@@ -125,6 +125,7 @@ typedef struct vchiq_arm_state_struct {
- struct vchiq_drvdata {
-       const unsigned int cache_line_size;
-+      const bool use_36bit_addrs;
-       struct rpi_firmware *fw;
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0470-bcm2835-pcm.c-Support-multichannel-audio.patch b/target/linux/brcm2708/patches-4.19/950-0470-bcm2835-pcm.c-Support-multichannel-audio.patch
deleted file mode 100644 (file)
index 47898db..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From 69d7e7d0f958186a0f7667ebeefdb50d1c5c3bd3 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 30 Apr 2019 19:15:30 +0100
-Subject: [PATCH] bcm2835-pcm.c: Support multichannel audio
-
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c   | 17 +++++++++--------
- 1 file changed, 9 insertions(+), 8 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -14,9 +14,9 @@ static const struct snd_pcm_hardware snd
-                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-                SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
-       .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
--      .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-+      .rates = SNDRV_PCM_RATE_CONTINUOUS |  SNDRV_PCM_RATE_8000_192000,
-       .rate_min = 8000,
--      .rate_max = 48000,
-+      .rate_max = 192000,
-       .channels_min = 1,
-       .channels_max = 2,
-       .buffer_bytes_max = 128 * 1024,
-@@ -31,15 +31,16 @@ static const struct snd_pcm_hardware snd
-                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-                SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
--      .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
--      SNDRV_PCM_RATE_48000,
-+      .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,
-       .rate_min = 44100,
--      .rate_max = 48000,
-+      .rate_max = 192000,
-       .channels_min = 2,
--      .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,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0470-bcmgenet-Better-coalescing-parameter-defaults.patch b/target/linux/brcm2708/patches-4.19/950-0470-bcmgenet-Better-coalescing-parameter-defaults.patch
new file mode 100644 (file)
index 0000000..e045886
--- /dev/null
@@ -0,0 +1,43 @@
+From bb3075a2edb5c55d0ea7470da8bb44cc9f36aa02 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 27 Mar 2019 13:45:46 +0000
+Subject: [PATCH] bcmgenet: Better coalescing parameter defaults
+
+Set defaults for TX and RX packet coalescing to be equivalent to:
+
+  # ethtool -C eth0 tx-frames 10
+  # ethtool -C eth0 rx-usecs 50
+
+This may be something we want to set via DT parameters in the
+future.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -2147,7 +2147,7 @@ static void bcmgenet_init_tx_ring(struct
+       bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);
+       bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX);
+-      bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
++      bcmgenet_tdma_ring_writel(priv, index, 10, DMA_MBUF_DONE_THRESH);
+       /* Disable rate control for now */
+       bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
+                                 TDMA_FLOW_PERIOD);
+@@ -3576,9 +3576,12 @@ static int bcmgenet_probe(struct platfor
+       netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
+       /* Set default coalescing parameters */
+-      for (i = 0; i < priv->hw_params->rx_queues; i++)
++      for (i = 0; i < priv->hw_params->rx_queues; i++) {
+               priv->rx_rings[i].rx_max_coalesced_frames = 1;
++              priv->rx_rings[i].rx_coalesce_usecs = 50;
++      }
+       priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
++      priv->rx_rings[DESC_INDEX].rx_coalesce_usecs = 50;
+       /* libphy will determine the link state */
+       netif_carrier_off(dev);
diff --git a/target/linux/brcm2708/patches-4.19/950-0471-bcmgenet-constrain-max-DMA-burst-length.patch b/target/linux/brcm2708/patches-4.19/950-0471-bcmgenet-constrain-max-DMA-burst-length.patch
deleted file mode 100644 (file)
index 54ead87..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From 12865021c91e21ca7189c6a84688459d400de204 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Wed, 12 Sep 2018 14:44:53 +0100
-Subject: [PATCH] bcmgenet: constrain max DMA burst length
-
----
- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
-+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
-@@ -31,7 +31,7 @@
- #define ENET_PAD              8
- #define ENET_MAX_MTU_SIZE     (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
-                                ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
--#define DMA_MAX_BURST_LENGTH    0x10
-+#define DMA_MAX_BURST_LENGTH    0x08
- /* misc. configuration */
- #define CLEAR_ALL_HFB                 0xFF
diff --git a/target/linux/brcm2708/patches-4.19/950-0471-net-genet-enable-link-energy-detect-powerdown-for-ex.patch b/target/linux/brcm2708/patches-4.19/950-0471-net-genet-enable-link-energy-detect-powerdown-for-ex.patch
new file mode 100644 (file)
index 0000000..2c0557b
--- /dev/null
@@ -0,0 +1,31 @@
+From d8b59e9245f8b2a231eeaa35b4a42f30cdbd5304 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 14 May 2019 17:17:59 +0100
+Subject: [PATCH] net: genet: enable link energy detect powerdown for
+ external PHYs
+
+There are several warts surrounding bcmgenet_mii_probe() as this
+function is called from ndo_open, but it's calling registration-type
+functions. The probe should be called at probe time and refactored
+such that the PHY device data can be extracted to limit the scope
+of this flag to Broadcom PHYs.
+
+For now, pass this flag in as it puts our attached PHY into a low-power
+state when disconnected.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmmii.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
+@@ -318,6 +318,8 @@ int bcmgenet_mii_probe(struct net_device
+       /* Communicate the integrated PHY revision */
+       if (priv->internal_phy)
+               phy_flags = priv->gphy_rev;
++      else
++              phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE;
+       /* Initialize link state variables that bcmgenet_mii_setup() uses */
+       priv->old_link = -1;
diff --git a/target/linux/brcm2708/patches-4.19/950-0472-bcmgenet-Better-coalescing-parameter-defaults.patch b/target/linux/brcm2708/patches-4.19/950-0472-bcmgenet-Better-coalescing-parameter-defaults.patch
deleted file mode 100644 (file)
index e045886..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-From bb3075a2edb5c55d0ea7470da8bb44cc9f36aa02 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 27 Mar 2019 13:45:46 +0000
-Subject: [PATCH] bcmgenet: Better coalescing parameter defaults
-
-Set defaults for TX and RX packet coalescing to be equivalent to:
-
-  # ethtool -C eth0 tx-frames 10
-  # ethtool -C eth0 rx-usecs 50
-
-This may be something we want to set via DT parameters in the
-future.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-@@ -2147,7 +2147,7 @@ static void bcmgenet_init_tx_ring(struct
-       bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);
-       bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX);
--      bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
-+      bcmgenet_tdma_ring_writel(priv, index, 10, DMA_MBUF_DONE_THRESH);
-       /* Disable rate control for now */
-       bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
-                                 TDMA_FLOW_PERIOD);
-@@ -3576,9 +3576,12 @@ static int bcmgenet_probe(struct platfor
-       netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
-       /* Set default coalescing parameters */
--      for (i = 0; i < priv->hw_params->rx_queues; i++)
-+      for (i = 0; i < priv->hw_params->rx_queues; i++) {
-               priv->rx_rings[i].rx_max_coalesced_frames = 1;
-+              priv->rx_rings[i].rx_coalesce_usecs = 50;
-+      }
-       priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
-+      priv->rx_rings[DESC_INDEX].rx_coalesce_usecs = 50;
-       /* libphy will determine the link state */
-       netif_carrier_off(dev);
diff --git a/target/linux/brcm2708/patches-4.19/950-0472-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch b/target/linux/brcm2708/patches-4.19/950-0472-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch
new file mode 100644 (file)
index 0000000..354cd08
--- /dev/null
@@ -0,0 +1,73 @@
+From 8eb54bbd5e6ebb929d390432163589f4c3dc0c14 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 | 17 ++++++++++++++---
+ include/linux/brcmphy.h    |  1 +
+ 2 files changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -222,7 +222,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);
+@@ -604,7 +605,7 @@ 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",
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+@@ -612,6 +613,15 @@ static struct phy_driver broadcom_driver
+       .ack_interrupt  = bcm_phy_ack_intr,
+       .config_intr    = bcm_phy_config_intr,
+ }, {
++      .phy_id         = PHY_ID_BCM54213PE,
++      .phy_id_mask    = 0xffffffff,
++      .name           = "Broadcom BCM54213PE",
++      .features       = PHY_GBIT_FEATURES,
++      .flags          = PHY_HAS_INTERRUPT,
++      .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",
+@@ -748,7 +758,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/brcm2708/patches-4.19/950-0473-net-genet-enable-link-energy-detect-powerdown-for-ex.patch b/target/linux/brcm2708/patches-4.19/950-0473-net-genet-enable-link-energy-detect-powerdown-for-ex.patch
deleted file mode 100644 (file)
index 2c0557b..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From d8b59e9245f8b2a231eeaa35b4a42f30cdbd5304 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 14 May 2019 17:17:59 +0100
-Subject: [PATCH] net: genet: enable link energy detect powerdown for
- external PHYs
-
-There are several warts surrounding bcmgenet_mii_probe() as this
-function is called from ndo_open, but it's calling registration-type
-functions. The probe should be called at probe time and refactored
-such that the PHY device data can be extracted to limit the scope
-of this flag to Broadcom PHYs.
-
-For now, pass this flag in as it puts our attached PHY into a low-power
-state when disconnected.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/net/ethernet/broadcom/genet/bcmmii.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
-+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
-@@ -318,6 +318,8 @@ int bcmgenet_mii_probe(struct net_device
-       /* Communicate the integrated PHY revision */
-       if (priv->internal_phy)
-               phy_flags = priv->gphy_rev;
-+      else
-+              phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE;
-       /* Initialize link state variables that bcmgenet_mii_setup() uses */
-       priv->old_link = -1;
diff --git a/target/linux/brcm2708/patches-4.19/950-0473-phy-bcm54213pe-configure-the-LED-outputs-to-be-more-.patch b/target/linux/brcm2708/patches-4.19/950-0473-phy-bcm54213pe-configure-the-LED-outputs-to-be-more-.patch
new file mode 100644 (file)
index 0000000..15af5a7
--- /dev/null
@@ -0,0 +1,64 @@
+From dc2550fdfd0a46c3ec67e5003b3d69c29141406b Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Fri, 17 May 2019 13:31:21 +0100
+Subject: [PATCH] phy: bcm54213pe: configure the LED outputs to be more
+ user-friendly
+
+The default state was both LEDs indicating link speed.
+
+Change the default configuration to
+- Amber: 1000/100 link speed indication
+- Green: link present + activity indication
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/net/phy/broadcom.c | 17 +++++++++++++++++
+ include/linux/brcmphy.h    |  4 ++++
+ 2 files changed, 21 insertions(+)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -52,6 +52,21 @@ static int bcm54210e_config_init(struct
+       return 0;
+ }
++static void bcm54213pe_config_init(struct phy_device *phydev)
++{
++      u16 val;
++
++      /* Enable ACT+LINK indication on ACTIVITY trigger */
++      val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_LEDCTL);
++      val |= BCM54XX_SHD_LEDCTL_ACTLINK_EN;
++      bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDCTL, val);
++
++      /* Set ACTIVITY on LED "1" output, LINKSPD[1] on LED "3" output */
++      val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
++              BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD1);
++      bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
++}
++
+ static int bcm54612e_config_init(struct phy_device *phydev)
+ {
+       int reg;
+@@ -310,6 +325,8 @@ 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) {
++              bcm54213pe_config_init(phydev);
+       } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
+               err = bcm54612e_config_init(phydev);
+               if (err)
+--- a/include/linux/brcmphy.h
++++ b/include/linux/brcmphy.h
+@@ -168,6 +168,10 @@
+ #define  BCM54XX_SHD_SCR3_DLLAPD_DIS  0x0002
+ #define  BCM54XX_SHD_SCR3_TRDDAPD     0x0004
++/* 01001: Additional LED trigger options */
++#define BCM54XX_SHD_LEDCTL            0x09
++#define  BCM54XX_SHD_LEDCTL_ACTLINK_EN        0x0010
++
+ /* 01010: Auto Power-Down */
+ #define BCM54XX_SHD_APD                       0x0a
+ #define  BCM_APD_CLR_MASK             0xFE9F /* clear bits 5, 6 & 8 */
diff --git a/target/linux/brcm2708/patches-4.19/950-0474-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch b/target/linux/brcm2708/patches-4.19/950-0474-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch
new file mode 100644 (file)
index 0000000..083e0c7
--- /dev/null
@@ -0,0 +1,181 @@
+From 856c8fdf68e589c89ed0518aab727c54fdff5afa Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 21 May 2019 13:36:52 +0100
+Subject: [PATCH] dwc_otg: Choose appropriate IRQ handover strategy
+
+2711 has no MPHI peripheral, but the ARM Control block can fake
+interrupts. Use the size of the DTB "mphi" reg block to determine
+which is required.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c    |  9 +++--
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c   | 21 ++++++----
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h   |  2 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c  | 12 ++++--
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 41 +++++++++++++-------
+ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h    |  3 ++
+ 6 files changed, 60 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+@@ -806,14 +806,15 @@ static int dwc_otg_driver_probe(
+               if (!request_mem_region(_dev->resource[1].start,
+                                       _dev->resource[1].end - _dev->resource[1].start + 1,
+                                       "dwc_otg")) {
+-                dev_dbg(&_dev->dev, "error reserving mapped memory\n");
+-                retval = -EFAULT;
+-                goto fail;
+-      }
++                      dev_dbg(&_dev->dev, "error reserving mapped memory\n");
++                      retval = -EFAULT;
++                      goto fail;
++              }
+               dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
+                                                           _dev->resource[1].end -
+                                                           _dev->resource[1].start + 1);
++              dwc_otg_device->os_dep.use_swirq = (_dev->resource[1].end - _dev->resource[1].start) == 0x200;
+       }
+ #else
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -1347,8 +1347,12 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
+       /* We got an interrupt, didn't handle it. */
+       if (kick_irq) {
+               state->mphi_int_count++;
+-              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+-              FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++              if (state->mphi_regs.swirq_set) {
++                      FIQ_WRITE(state->mphi_regs.swirq_set, 1);
++              } else {
++                      FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
++                      FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++              }
+       }
+       state->fiq_done++;
+@@ -1406,11 +1410,14 @@ void notrace dwc_otg_fiq_nop(struct fiq_
+               state->mphi_int_count++;
+               gintmsk.d32 &= state->gintmsk_saved.d32;
+               FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
+-              /* Force a clear before another dummy send */
+-              FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
+-              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+-              FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+-
++              if (state->mphi_regs.swirq_set) {
++                      FIQ_WRITE(state->mphi_regs.swirq_set, 1);
++              } else {
++                      /* Force a clear before another dummy send */
++                      FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
++                      FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
++                      FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++              }
+       }
+       state->fiq_done++;
+       mb();
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+@@ -118,6 +118,8 @@ typedef struct {
+       volatile void* outdda;
+       volatile void* outddb;
+       volatile void* intstat;
++      volatile void* swirq_set;
++      volatile void* swirq_clr;
+ } mphi_regs_t;
+ enum fiq_debug_level {
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+@@ -220,16 +220,20 @@ exit_handler_routine:
+               /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
+               if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
++                      if (dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr) {
++                              DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr, 1);
++                      } else {
+                               DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
+-                              if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
+-                                      fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
++                      }
++                      if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
++                              fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
+                                       DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
+                                       while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
+                                               ;
+                                       DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
+                                       dwc_otg_hcd->fiq_state->mphi_int_count = 0;
+-                              }
+-                              int_done++;
++                      }
++                      int_done++;
+               }
+               haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
+               /* Re-enable interrupts that the FIQ masked (first time round) */
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -474,22 +474,37 @@ static void hcd_init_fiq(void *cookie)
+       set_fiq_regs(&regs);
+ #endif
+-      //Set the mphi periph to  the required registers
+-      dwc_otg_hcd->fiq_state->mphi_regs.base    = otg_dev->os_dep.mphi_base;
+-      dwc_otg_hcd->fiq_state->mphi_regs.ctrl    = otg_dev->os_dep.mphi_base + 0x4c;
+-      dwc_otg_hcd->fiq_state->mphi_regs.outdda  = otg_dev->os_dep.mphi_base + 0x28;
+-      dwc_otg_hcd->fiq_state->mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;
+-      dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
+       dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
+-      DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
+-      //Enable mphi peripheral
+-      writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
++      //Set the mphi periph to the required registers
++      dwc_otg_hcd->fiq_state->mphi_regs.base    = otg_dev->os_dep.mphi_base;
++      if (otg_dev->os_dep.use_swirq) {
++              dwc_otg_hcd->fiq_state->mphi_regs.swirq_set =
++                      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);
++      } else {
++              dwc_otg_hcd->fiq_state->mphi_regs.ctrl =
++                      otg_dev->os_dep.mphi_base + 0x4c;
++              dwc_otg_hcd->fiq_state->mphi_regs.outdda
++                      = otg_dev->os_dep.mphi_base + 0x28;
++              dwc_otg_hcd->fiq_state->mphi_regs.outddb
++                      = otg_dev->os_dep.mphi_base + 0x2c;
++              dwc_otg_hcd->fiq_state->mphi_regs.intstat
++                      = otg_dev->os_dep.mphi_base + 0x50;
++              DWC_WARN("MPHI regs_base at %px",
++                       dwc_otg_hcd->fiq_state->mphi_regs.base);
++
++              //Enable mphi peripheral
++              writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
+ #ifdef DEBUG
+-      if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
+-              DWC_WARN("MPHI periph has been enabled");
+-      else
+-              DWC_WARN("MPHI periph has NOT been enabled");
++              if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
++                      DWC_WARN("MPHI periph has been enabled");
++              else
++                      DWC_WARN("MPHI periph has NOT been enabled");
+ #endif
++      }
+       // Enable FIQ interrupt from USB peripheral
+ #ifdef CONFIG_ARM64
+       irq = otg_dev->os_dep.fiq_num;
+--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+@@ -102,6 +102,9 @@ typedef struct os_dependent {
+       /** Base address for MPHI peripheral */
+       void *mphi_base;
++      /** mphi_base actually points to the SWIRQ block */
++      bool use_swirq;
++
+       /** IRQ number (<0 if not valid) */
+       int irq_num;
diff --git a/target/linux/brcm2708/patches-4.19/950-0474-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch b/target/linux/brcm2708/patches-4.19/950-0474-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch
deleted file mode 100644 (file)
index 354cd08..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From 8eb54bbd5e6ebb929d390432163589f4c3dc0c14 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 | 17 ++++++++++++++---
- include/linux/brcmphy.h    |  1 +
- 2 files changed, 15 insertions(+), 3 deletions(-)
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -222,7 +222,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);
-@@ -604,7 +605,7 @@ 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",
-       .features       = PHY_GBIT_FEATURES,
-       .flags          = PHY_HAS_INTERRUPT,
-@@ -612,6 +613,15 @@ static struct phy_driver broadcom_driver
-       .ack_interrupt  = bcm_phy_ack_intr,
-       .config_intr    = bcm_phy_config_intr,
- }, {
-+      .phy_id         = PHY_ID_BCM54213PE,
-+      .phy_id_mask    = 0xffffffff,
-+      .name           = "Broadcom BCM54213PE",
-+      .features       = PHY_GBIT_FEATURES,
-+      .flags          = PHY_HAS_INTERRUPT,
-+      .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",
-@@ -748,7 +758,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/brcm2708/patches-4.19/950-0475-phy-bcm54213pe-configure-the-LED-outputs-to-be-more-.patch b/target/linux/brcm2708/patches-4.19/950-0475-phy-bcm54213pe-configure-the-LED-outputs-to-be-more-.patch
deleted file mode 100644 (file)
index 15af5a7..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From dc2550fdfd0a46c3ec67e5003b3d69c29141406b Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Fri, 17 May 2019 13:31:21 +0100
-Subject: [PATCH] phy: bcm54213pe: configure the LED outputs to be more
- user-friendly
-
-The default state was both LEDs indicating link speed.
-
-Change the default configuration to
-- Amber: 1000/100 link speed indication
-- Green: link present + activity indication
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/net/phy/broadcom.c | 17 +++++++++++++++++
- include/linux/brcmphy.h    |  4 ++++
- 2 files changed, 21 insertions(+)
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -52,6 +52,21 @@ static int bcm54210e_config_init(struct
-       return 0;
- }
-+static void bcm54213pe_config_init(struct phy_device *phydev)
-+{
-+      u16 val;
-+
-+      /* Enable ACT+LINK indication on ACTIVITY trigger */
-+      val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_LEDCTL);
-+      val |= BCM54XX_SHD_LEDCTL_ACTLINK_EN;
-+      bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDCTL, val);
-+
-+      /* Set ACTIVITY on LED "1" output, LINKSPD[1] on LED "3" output */
-+      val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
-+              BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD1);
-+      bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
-+}
-+
- static int bcm54612e_config_init(struct phy_device *phydev)
- {
-       int reg;
-@@ -310,6 +325,8 @@ 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) {
-+              bcm54213pe_config_init(phydev);
-       } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
-               err = bcm54612e_config_init(phydev);
-               if (err)
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -168,6 +168,10 @@
- #define  BCM54XX_SHD_SCR3_DLLAPD_DIS  0x0002
- #define  BCM54XX_SHD_SCR3_TRDDAPD     0x0004
-+/* 01001: Additional LED trigger options */
-+#define BCM54XX_SHD_LEDCTL            0x09
-+#define  BCM54XX_SHD_LEDCTL_ACTLINK_EN        0x0010
-+
- /* 01010: Auto Power-Down */
- #define BCM54XX_SHD_APD                       0x0a
- #define  BCM_APD_CLR_MASK             0xFE9F /* clear bits 5, 6 & 8 */
diff --git a/target/linux/brcm2708/patches-4.19/950-0475-usb-xhci-Disable-the-XHCI-5-second-timeout.patch b/target/linux/brcm2708/patches-4.19/950-0475-usb-xhci-Disable-the-XHCI-5-second-timeout.patch
new file mode 100644 (file)
index 0000000..abc576d
--- /dev/null
@@ -0,0 +1,29 @@
+From ff7222c0771a5e28666335663571058e560ad32b Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Fri, 22 Mar 2019 09:47:14 +0000
+Subject: [PATCH] usb: xhci: Disable the XHCI 5 second timeout
+
+If the VL805 EEPROM has not been programmed then boot will hang for five
+seconds. The timeout seems to be arbitrary and is an unecessary
+delay on the first boot. Remove the timeout.
+
+This is common code and probably can't be upstreamed unless the timeout
+can be configurable somehow or perhaps the XHCI driver can be skipped
+on the first boot.
+---
+ drivers/usb/host/xhci.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -196,8 +196,9 @@ int xhci_reset(struct xhci_hcd *xhci)
+       if (xhci->quirks & XHCI_INTEL_HOST)
+               udelay(1000);
++      // Hack: reduce handshake timeout from 10s 0.5s due to unprogrammed vl805
+       ret = xhci_handshake(&xhci->op_regs->command,
+-                      CMD_RESET, 0, 10 * 1000 * 1000);
++                      CMD_RESET, 0, 500 * 1000);
+       if (ret)
+               return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0476-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch b/target/linux/brcm2708/patches-4.19/950-0476-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch
deleted file mode 100644 (file)
index 083e0c7..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-From 856c8fdf68e589c89ed0518aab727c54fdff5afa Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 21 May 2019 13:36:52 +0100
-Subject: [PATCH] dwc_otg: Choose appropriate IRQ handover strategy
-
-2711 has no MPHI peripheral, but the ARM Control block can fake
-interrupts. Use the size of the DTB "mphi" reg block to determine
-which is required.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_driver.c    |  9 +++--
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c   | 21 ++++++----
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h   |  2 +
- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c  | 12 ++++--
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 41 +++++++++++++-------
- drivers/usb/host/dwc_otg/dwc_otg_os_dep.h    |  3 ++
- 6 files changed, 60 insertions(+), 28 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-@@ -806,14 +806,15 @@ static int dwc_otg_driver_probe(
-               if (!request_mem_region(_dev->resource[1].start,
-                                       _dev->resource[1].end - _dev->resource[1].start + 1,
-                                       "dwc_otg")) {
--                dev_dbg(&_dev->dev, "error reserving mapped memory\n");
--                retval = -EFAULT;
--                goto fail;
--      }
-+                      dev_dbg(&_dev->dev, "error reserving mapped memory\n");
-+                      retval = -EFAULT;
-+                      goto fail;
-+              }
-               dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
-                                                           _dev->resource[1].end -
-                                                           _dev->resource[1].start + 1);
-+              dwc_otg_device->os_dep.use_swirq = (_dev->resource[1].end - _dev->resource[1].start) == 0x200;
-       }
- #else
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-@@ -1347,8 +1347,12 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
-       /* We got an interrupt, didn't handle it. */
-       if (kick_irq) {
-               state->mphi_int_count++;
--              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
--              FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-+              if (state->mphi_regs.swirq_set) {
-+                      FIQ_WRITE(state->mphi_regs.swirq_set, 1);
-+              } else {
-+                      FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-+                      FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-+              }
-       }
-       state->fiq_done++;
-@@ -1406,11 +1410,14 @@ void notrace dwc_otg_fiq_nop(struct fiq_
-               state->mphi_int_count++;
-               gintmsk.d32 &= state->gintmsk_saved.d32;
-               FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
--              /* Force a clear before another dummy send */
--              FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
--              FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
--              FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
--
-+              if (state->mphi_regs.swirq_set) {
-+                      FIQ_WRITE(state->mphi_regs.swirq_set, 1);
-+              } else {
-+                      /* Force a clear before another dummy send */
-+                      FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
-+                      FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-+                      FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-+              }
-       }
-       state->fiq_done++;
-       mb();
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-@@ -118,6 +118,8 @@ typedef struct {
-       volatile void* outdda;
-       volatile void* outddb;
-       volatile void* intstat;
-+      volatile void* swirq_set;
-+      volatile void* swirq_clr;
- } mphi_regs_t;
- enum fiq_debug_level {
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
-@@ -220,16 +220,20 @@ exit_handler_routine:
-               /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
-               if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
-+                      if (dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr) {
-+                              DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr, 1);
-+                      } else {
-                               DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
--                              if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
--                                      fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
-+                      }
-+                      if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
-+                              fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
-                                       DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
-                                       while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
-                                               ;
-                                       DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
-                                       dwc_otg_hcd->fiq_state->mphi_int_count = 0;
--                              }
--                              int_done++;
-+                      }
-+                      int_done++;
-               }
-               haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
-               /* Re-enable interrupts that the FIQ masked (first time round) */
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -474,22 +474,37 @@ static void hcd_init_fiq(void *cookie)
-       set_fiq_regs(&regs);
- #endif
--      //Set the mphi periph to  the required registers
--      dwc_otg_hcd->fiq_state->mphi_regs.base    = otg_dev->os_dep.mphi_base;
--      dwc_otg_hcd->fiq_state->mphi_regs.ctrl    = otg_dev->os_dep.mphi_base + 0x4c;
--      dwc_otg_hcd->fiq_state->mphi_regs.outdda  = otg_dev->os_dep.mphi_base + 0x28;
--      dwc_otg_hcd->fiq_state->mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;
--      dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
-       dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
--      DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
--      //Enable mphi peripheral
--      writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
-+      //Set the mphi periph to the required registers
-+      dwc_otg_hcd->fiq_state->mphi_regs.base    = otg_dev->os_dep.mphi_base;
-+      if (otg_dev->os_dep.use_swirq) {
-+              dwc_otg_hcd->fiq_state->mphi_regs.swirq_set =
-+                      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);
-+      } else {
-+              dwc_otg_hcd->fiq_state->mphi_regs.ctrl =
-+                      otg_dev->os_dep.mphi_base + 0x4c;
-+              dwc_otg_hcd->fiq_state->mphi_regs.outdda
-+                      = otg_dev->os_dep.mphi_base + 0x28;
-+              dwc_otg_hcd->fiq_state->mphi_regs.outddb
-+                      = otg_dev->os_dep.mphi_base + 0x2c;
-+              dwc_otg_hcd->fiq_state->mphi_regs.intstat
-+                      = otg_dev->os_dep.mphi_base + 0x50;
-+              DWC_WARN("MPHI regs_base at %px",
-+                       dwc_otg_hcd->fiq_state->mphi_regs.base);
-+
-+              //Enable mphi peripheral
-+              writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
- #ifdef DEBUG
--      if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
--              DWC_WARN("MPHI periph has been enabled");
--      else
--              DWC_WARN("MPHI periph has NOT been enabled");
-+              if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
-+                      DWC_WARN("MPHI periph has been enabled");
-+              else
-+                      DWC_WARN("MPHI periph has NOT been enabled");
- #endif
-+      }
-       // Enable FIQ interrupt from USB peripheral
- #ifdef CONFIG_ARM64
-       irq = otg_dev->os_dep.fiq_num;
---- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-@@ -102,6 +102,9 @@ typedef struct os_dependent {
-       /** Base address for MPHI peripheral */
-       void *mphi_base;
-+      /** mphi_base actually points to the SWIRQ block */
-+      bool use_swirq;
-+
-       /** IRQ number (<0 if not valid) */
-       int irq_num;
diff --git a/target/linux/brcm2708/patches-4.19/950-0476-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch b/target/linux/brcm2708/patches-4.19/950-0476-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch
new file mode 100644 (file)
index 0000000..239e142
--- /dev/null
@@ -0,0 +1,23 @@
+From 94a960e8933fb94b979f88c319aa54c304004b35 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 23 May 2019 15:08:30 +0100
+Subject: [PATCH] usb: xhci: Show that the VIA VL805 supports LPM
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/usb/host/xhci-pci.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -222,6 +222,10 @@ static void xhci_pci_quirks(struct devic
+                       pdev->device == 0x3432)
+               xhci->quirks |= XHCI_BROKEN_STREAMS;
++      if (pdev->vendor == PCI_VENDOR_ID_VIA &&
++                      pdev->device == 0x3483)
++              xhci->quirks |= XHCI_LPM_SUPPORT;
++
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+                       pdev->device == 0x1042)
+               xhci->quirks |= XHCI_BROKEN_STREAMS;
diff --git a/target/linux/brcm2708/patches-4.19/950-0477-spi-bcm2835-enable-shared-interrupt-support.patch b/target/linux/brcm2708/patches-4.19/950-0477-spi-bcm2835-enable-shared-interrupt-support.patch
new file mode 100644 (file)
index 0000000..f929b3a
--- /dev/null
@@ -0,0 +1,35 @@
+From 21dd7cd6dc231287b92a8c8b9ecf9d0844c2d325 Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Mon, 13 May 2019 11:05:27 +0000
+Subject: [PATCH] spi: bcm2835: enable shared interrupt support
+
+Add shared interrupt support for this driver.
+
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+---
+ drivers/spi/spi-bcm2835.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -150,6 +150,10 @@ static irqreturn_t bcm2835_spi_interrupt
+       struct spi_master *master = dev_id;
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
++      /* check if we got interrupt enabled */
++      if (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_INTR))
++              return IRQ_NONE;
++
+       /* Read as many bytes as possible from FIFO */
+       bcm2835_rd_fifo(bs);
+       /* Write as many bytes as possible to FIFO */
+@@ -756,7 +760,8 @@ static int bcm2835_spi_probe(struct plat
+       bcm2835_wr(bs, BCM2835_SPI_CS,
+                  BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+-      err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
++      err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt,
++                             IRQF_SHARED,
+                              dev_name(&pdev->dev), master);
+       if (err) {
+               dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
diff --git a/target/linux/brcm2708/patches-4.19/950-0477-usb-xhci-Disable-the-XHCI-5-second-timeout.patch b/target/linux/brcm2708/patches-4.19/950-0477-usb-xhci-Disable-the-XHCI-5-second-timeout.patch
deleted file mode 100644 (file)
index abc576d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From ff7222c0771a5e28666335663571058e560ad32b Mon Sep 17 00:00:00 2001
-From: Tim Gover <tim.gover@raspberrypi.org>
-Date: Fri, 22 Mar 2019 09:47:14 +0000
-Subject: [PATCH] usb: xhci: Disable the XHCI 5 second timeout
-
-If the VL805 EEPROM has not been programmed then boot will hang for five
-seconds. The timeout seems to be arbitrary and is an unecessary
-delay on the first boot. Remove the timeout.
-
-This is common code and probably can't be upstreamed unless the timeout
-can be configurable somehow or perhaps the XHCI driver can be skipped
-on the first boot.
----
- drivers/usb/host/xhci.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -196,8 +196,9 @@ int xhci_reset(struct xhci_hcd *xhci)
-       if (xhci->quirks & XHCI_INTEL_HOST)
-               udelay(1000);
-+      // Hack: reduce handshake timeout from 10s 0.5s due to unprogrammed vl805
-       ret = xhci_handshake(&xhci->op_regs->command,
--                      CMD_RESET, 0, 10 * 1000 * 1000);
-+                      CMD_RESET, 0, 500 * 1000);
-       if (ret)
-               return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0478-drivers-char-add-chardev-for-mmap-ing-Argon-control-.patch b/target/linux/brcm2708/patches-4.19/950-0478-drivers-char-add-chardev-for-mmap-ing-Argon-control-.patch
new file mode 100644 (file)
index 0000000..fb358aa
--- /dev/null
@@ -0,0 +1,320 @@
+From 0be0d6439128366a8d2ac0afaf88f19209171e51 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 9 May 2019 14:30:37 +0100
+Subject: [PATCH] drivers: char: add chardev for mmap'ing Argon control
+ registers
+
+Based on the gpiomem driver, allow mapping of the decoder register
+spaces such that userspace can access control/status registers.
+This driver is intended for use with a custom ffmpeg backend accelerator
+prior to a v4l2 driver being written.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/char/broadcom/Kconfig     |   8 +
+ drivers/char/broadcom/Makefile    |   1 +
+ drivers/char/broadcom/argon-mem.c | 277 ++++++++++++++++++++++++++++++
+ 3 files changed, 286 insertions(+)
+ create mode 100644 drivers/char/broadcom/argon-mem.c
+
+--- a/drivers/char/broadcom/Kconfig
++++ b/drivers/char/broadcom/Kconfig
+@@ -49,3 +49,11 @@ config BCM2835_SMI_DEV
+               This driver provides a character device interface (ioctl + read/write) to
+               Broadcom's Secondary Memory interface. The low-level functionality is provided
+               by the SMI driver itself.
++
++config ARGON_MEM
++      tristate "Character device driver for the Argon decoder hardware"
++      default n
++      help
++              This driver provides a character device interface for memory-map operations
++              so userspace tools can access the control and status registers of the Argon
++              video decoder hardware.
+--- a/drivers/char/broadcom/Makefile
++++ b/drivers/char/broadcom/Makefile
+@@ -4,3 +4,4 @@ obj-$(CONFIG_BCM_VC_SM)         += vc_sm
+ obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
+ obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o
++obj-$(CONFIG_ARGON_MEM)               += argon-mem.o
+--- /dev/null
++++ b/drivers/char/broadcom/argon-mem.c
+@@ -0,0 +1,277 @@
++/**
++ * argon-mem.c - character device access to the Argon decoder registers
++ *
++ * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
++ * register blocks such that ffmpeg plugins can access the hardware.
++ *
++ * Jonathan Bell <jonathan@raspberrypi.org>
++ * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions, and the following disclaimer,
++ *    without modification.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The names of the above-listed copyright holders may not be used
++ *    to endorse or promote products derived from this software without
++ *    specific prior written permission.
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") version 2, as published by the Free
++ * Software Foundation.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
++ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/cdev.h>
++#include <linux/pagemap.h>
++#include <linux/io.h>
++
++#define DRIVER_NAME "argon-mem"
++#define DEVICE_MINOR 0
++
++struct argon_mem_priv {
++      dev_t devid;
++      struct class *class;
++      struct cdev argon_mem_cdev;
++      unsigned long regs_phys;
++      unsigned long mem_window_len;
++      struct device *dev;
++      const char *name;
++};
++
++static int argon_mem_open(struct inode *inode, struct file *file)
++{
++      int dev = iminor(inode);
++      int ret = 0;
++      struct argon_mem_priv *priv;
++      if (dev != DEVICE_MINOR)
++              ret = -ENXIO;
++
++      priv = container_of(inode->i_cdev, struct argon_mem_priv,
++                              argon_mem_cdev);
++      if (!priv)
++              return -EINVAL;
++      file->private_data = priv;
++      return ret;
++}
++
++static int argon_mem_release(struct inode *inode, struct file *file)
++{
++      int dev = iminor(inode);
++      int ret = 0;
++
++      if (dev != DEVICE_MINOR)
++              ret = -ENXIO;
++
++      return ret;
++}
++
++static const struct vm_operations_struct argon_mem_vm_ops = {
++#ifdef CONFIG_HAVE_IOREMAP_PROT
++      .access = generic_access_phys
++#endif
++};
++
++static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
++{
++      struct argon_mem_priv *priv;
++      unsigned long pages;
++
++      priv = file->private_data;
++      pages = priv->regs_phys >> PAGE_SHIFT;
++      /*
++       * The address decode is far larger than the actual number of registers.
++       * Just map the whole lot in.
++       */
++      vma->vm_page_prot = phys_mem_access_prot(file, pages,
++                                               priv->mem_window_len,
++                                               vma->vm_page_prot);
++      vma->vm_ops = &argon_mem_vm_ops;
++      if (remap_pfn_range(vma, vma->vm_start,
++                      pages,
++                      priv->mem_window_len,
++                      vma->vm_page_prot)) {
++              return -EAGAIN;
++      }
++      return 0;
++}
++
++static const struct file_operations
++argon_mem_fops = {
++      .owner = THIS_MODULE,
++      .open = argon_mem_open,
++      .release = argon_mem_release,
++      .mmap = argon_mem_mmap,
++};
++
++static const struct of_device_id argon_mem_of_match[];
++static int argon_mem_probe(struct platform_device *pdev)
++{
++      int err;
++      void *ptr_err;
++      const struct of_device_id *id;
++      struct device *dev = &pdev->dev;
++      struct device *argon_mem_dev;
++      struct resource *ioresource;
++      struct argon_mem_priv *priv;
++
++
++      /* Allocate buffers and instance data */
++
++      priv = kzalloc(sizeof(struct argon_mem_priv), GFP_KERNEL);
++
++      if (!priv) {
++              err = -ENOMEM;
++              goto failed_inst_alloc;
++      }
++      platform_set_drvdata(pdev, priv);
++
++      priv->dev = dev;
++      id = of_match_device(argon_mem_of_match, dev);
++      if (!id)
++              return -EINVAL;
++      priv->name = id->data;
++
++      ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (ioresource) {
++              priv->regs_phys = ioresource->start;
++              priv->mem_window_len = ioresource->end - ioresource->start;
++      } else {
++              dev_err(priv->dev, "failed to get IO resource");
++              err = -ENOENT;
++              goto failed_get_resource;
++      }
++
++      /* Create character device entries */
++
++      err = alloc_chrdev_region(&priv->devid,
++                                DEVICE_MINOR, 1, priv->name);
++      if (err != 0) {
++              dev_err(priv->dev, "unable to allocate device number");
++              goto failed_alloc_chrdev;
++      }
++      cdev_init(&priv->argon_mem_cdev, &argon_mem_fops);
++      priv->argon_mem_cdev.owner = THIS_MODULE;
++      err = cdev_add(&priv->argon_mem_cdev, priv->devid, 1);
++      if (err != 0) {
++              dev_err(priv->dev, "unable to register device");
++              goto failed_cdev_add;
++      }
++
++      /* Create sysfs entries */
++
++      priv->class = class_create(THIS_MODULE, priv->name);
++      ptr_err = priv->class;
++      if (IS_ERR(ptr_err))
++              goto failed_class_create;
++
++      argon_mem_dev = device_create(priv->class, NULL,
++                                      priv->devid, NULL,
++                                      priv->name);
++      ptr_err = argon_mem_dev;
++      if (IS_ERR(ptr_err))
++              goto failed_device_create;
++
++      dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
++              priv->name, priv->regs_phys, priv->mem_window_len);
++
++      return 0;
++
++failed_device_create:
++      class_destroy(priv->class);
++failed_class_create:
++      cdev_del(&priv->argon_mem_cdev);
++      err = PTR_ERR(ptr_err);
++failed_cdev_add:
++      unregister_chrdev_region(priv->devid, 1);
++failed_alloc_chrdev:
++failed_get_resource:
++      kfree(priv);
++failed_inst_alloc:
++      dev_err(priv->dev, "could not load argon_mem");
++      return err;
++}
++
++static int argon_mem_remove(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct argon_mem_priv *priv = platform_get_drvdata(pdev);
++
++      device_destroy(priv->class, priv->devid);
++      class_destroy(priv->class);
++      cdev_del(&priv->argon_mem_cdev);
++      unregister_chrdev_region(priv->devid, 1);
++      kfree(priv);
++
++      dev_info(dev, "%s driver removed - OK", priv->name);
++      return 0;
++}
++
++static const char argon_hevc_name[] = "argon-hevcmem";
++static const char argon_h264_name[] = "argon-h264mem";
++static const char argon_vp9_name[] = "argon-vp9mem";
++static const char argon_intc_name[] = "argon-intcmem";
++
++static const struct of_device_id argon_mem_of_match[] = {
++      {
++              .compatible = "raspberrypi,argon-hevc-decoder",
++              .data = &argon_hevc_name,
++      },
++      {
++              .compatible = "raspberrypi,argon-h264-decoder",
++              .data = &argon_h264_name,
++      },
++      {
++              .compatible = "raspberrypi,argon-vp9-decoder",
++              .data = &argon_vp9_name,
++      },
++      /* The "intc" is included as this block of hardware contains the
++       * "frame done" status flags.
++       */
++      {
++              .compatible = "raspberrypi,argon-local-intc",
++              .data = &argon_intc_name,
++      },
++      { /* sentinel */ },
++};
++
++MODULE_DEVICE_TABLE(of, argon_mem_of_match);
++
++static struct platform_driver argon_mem_driver = {
++      .probe = argon_mem_probe,
++      .remove = argon_mem_remove,
++      .driver = {
++                 .name = DRIVER_NAME,
++                 .owner = THIS_MODULE,
++                 .of_match_table = argon_mem_of_match,
++                 },
++};
++
++module_platform_driver(argon_mem_driver);
++
++MODULE_ALIAS("platform:argon-mem");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Driver for accessing Argon decoder registers from userspace");
++MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
diff --git a/target/linux/brcm2708/patches-4.19/950-0478-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch b/target/linux/brcm2708/patches-4.19/950-0478-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch
deleted file mode 100644 (file)
index 239e142..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 94a960e8933fb94b979f88c319aa54c304004b35 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 23 May 2019 15:08:30 +0100
-Subject: [PATCH] usb: xhci: Show that the VIA VL805 supports LPM
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/usb/host/xhci-pci.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/usb/host/xhci-pci.c
-+++ b/drivers/usb/host/xhci-pci.c
-@@ -222,6 +222,10 @@ static void xhci_pci_quirks(struct devic
-                       pdev->device == 0x3432)
-               xhci->quirks |= XHCI_BROKEN_STREAMS;
-+      if (pdev->vendor == PCI_VENDOR_ID_VIA &&
-+                      pdev->device == 0x3483)
-+              xhci->quirks |= XHCI_LPM_SUPPORT;
-+
-       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
-                       pdev->device == 0x1042)
-               xhci->quirks |= XHCI_BROKEN_STREAMS;
diff --git a/target/linux/brcm2708/patches-4.19/950-0479-clk-bcm2835-Don-t-wait-for-pllh-lock.patch b/target/linux/brcm2708/patches-4.19/950-0479-clk-bcm2835-Don-t-wait-for-pllh-lock.patch
new file mode 100644 (file)
index 0000000..e8ab380
--- /dev/null
@@ -0,0 +1,38 @@
+From 3924edc9bd3c55d48c383c1046d75e163ce3cddb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 23 Jan 2019 16:11:50 +0000
+Subject: [PATCH] clk-bcm2835: Don't wait for pllh lock
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -627,15 +627,17 @@ static int bcm2835_pll_on(struct clk_hw
+       spin_unlock(&cprman->regs_lock);
+       /* Wait for the PLL to lock. */
+-      timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
+-      while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
+-              if (ktime_after(ktime_get(), timeout)) {
+-                      dev_err(cprman->dev, "%s: couldn't lock PLL\n",
+-                              clk_hw_get_name(hw));
+-                      return -ETIMEDOUT;
+-              }
++      if (strcmp(data->name, "pllh")) {
++              timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
++              while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
++                      if (ktime_after(ktime_get(), timeout)) {
++                              dev_err(cprman->dev, "%s: couldn't lock PLL\n",
++                                      clk_hw_get_name(hw));
++                              return -ETIMEDOUT;
++                      }
+-              cpu_relax();
++                      cpu_relax();
++              }
+       }
+       cprman_write(cprman, data->a2w_ctrl_reg,
diff --git a/target/linux/brcm2708/patches-4.19/950-0479-spi-bcm2835-enable-shared-interrupt-support.patch b/target/linux/brcm2708/patches-4.19/950-0479-spi-bcm2835-enable-shared-interrupt-support.patch
deleted file mode 100644 (file)
index f929b3a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From 21dd7cd6dc231287b92a8c8b9ecf9d0844c2d325 Mon Sep 17 00:00:00 2001
-From: Martin Sperl <kernel@martin.sperl.org>
-Date: Mon, 13 May 2019 11:05:27 +0000
-Subject: [PATCH] spi: bcm2835: enable shared interrupt support
-
-Add shared interrupt support for this driver.
-
-Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
----
- drivers/spi/spi-bcm2835.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/spi/spi-bcm2835.c
-+++ b/drivers/spi/spi-bcm2835.c
-@@ -150,6 +150,10 @@ static irqreturn_t bcm2835_spi_interrupt
-       struct spi_master *master = dev_id;
-       struct bcm2835_spi *bs = spi_master_get_devdata(master);
-+      /* check if we got interrupt enabled */
-+      if (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_INTR))
-+              return IRQ_NONE;
-+
-       /* Read as many bytes as possible from FIFO */
-       bcm2835_rd_fifo(bs);
-       /* Write as many bytes as possible to FIFO */
-@@ -756,7 +760,8 @@ static int bcm2835_spi_probe(struct plat
-       bcm2835_wr(bs, BCM2835_SPI_CS,
-                  BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
--      err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
-+      err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt,
-+                             IRQF_SHARED,
-                              dev_name(&pdev->dev), master);
-       if (err) {
-               dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
diff --git a/target/linux/brcm2708/patches-4.19/950-0480-bcm2835-pm-Move-bcm2835-watchdog-s-DT-probe-to-an-MF.patch b/target/linux/brcm2708/patches-4.19/950-0480-bcm2835-pm-Move-bcm2835-watchdog-s-DT-probe-to-an-MF.patch
new file mode 100644 (file)
index 0000000..ff15427
--- /dev/null
@@ -0,0 +1,200 @@
+From 90964ab2d00546a59086ffd08964da3d2a5cefc9 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:47 -0800
+Subject: [PATCH] bcm2835-pm: Move bcm2835-watchdog's DT probe to an
+ MFD.
+
+The PM block that the wdt driver was binding to actually has multiple
+features we want to expose (power domains, reset, watchdog).  Move the
+DT attachment to a MFD driver and make WDT probe against MFD.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+(cherry picked from commit 5e6acc3e678ed3db746ab4fb53a980861cd711b6)
+---
+ drivers/mfd/Makefile           |  1 +
+ drivers/mfd/bcm2835-pm.c       | 64 ++++++++++++++++++++++++++++++++++
+ drivers/watchdog/bcm2835_wdt.c | 26 +++++---------
+ include/linux/mfd/bcm2835-pm.h | 13 +++++++
+ 4 files changed, 87 insertions(+), 17 deletions(-)
+ create mode 100644 drivers/mfd/bcm2835-pm.c
+ create mode 100644 include/linux/mfd/bcm2835-pm.h
+
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805)    += 88pm805.o 8
+ obj-$(CONFIG_MFD_ACT8945A)    += act8945a.o
+ obj-$(CONFIG_MFD_SM501)               += sm501.o
+ obj-$(CONFIG_MFD_ASIC3)               += asic3.o tmio_core.o
++obj-$(CONFIG_ARCH_BCM2835)    += bcm2835-pm.o
+ obj-$(CONFIG_MFD_BCM590XX)    += bcm590xx.o
+ obj-$(CONFIG_MFD_BD9571MWV)   += bd9571mwv.o
+ cros_ec_core-objs             := cros_ec.o
+--- /dev/null
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -0,0 +1,64 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * PM MFD driver for Broadcom BCM2835
++ *
++ * This driver binds to the PM block and creates the MFD device for
++ * the WDT driver.
++ */
++
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/mfd/bcm2835-pm.h>
++#include <linux/mfd/core.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/types.h>
++#include <linux/watchdog.h>
++
++static const struct mfd_cell bcm2835_pm_devs[] = {
++      { .name = "bcm2835-wdt" },
++};
++
++static int bcm2835_pm_probe(struct platform_device *pdev)
++{
++      struct resource *res;
++      struct device *dev = &pdev->dev;
++      struct bcm2835_pm *pm;
++
++      pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
++      if (!pm)
++              return -ENOMEM;
++      platform_set_drvdata(pdev, pm);
++
++      pm->dev = dev;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      pm->base = devm_ioremap_resource(dev, res);
++      if (IS_ERR(pm->base))
++              return PTR_ERR(pm->base);
++
++      return devm_mfd_add_devices(dev, -1,
++                                  bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
++                                  NULL, 0, NULL);
++}
++
++static const struct of_device_id bcm2835_pm_of_match[] = {
++      { .compatible = "brcm,bcm2835-pm-wdt", },
++      {},
++};
++MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
++
++static struct platform_driver bcm2835_pm_driver = {
++      .probe          = bcm2835_pm_probe,
++      .driver = {
++              .name = "bcm2835-pm",
++              .of_match_table = bcm2835_pm_of_match,
++      },
++};
++module_platform_driver(bcm2835_pm_driver);
++
++MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
++MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
++MODULE_LICENSE("GPL");
+--- a/drivers/watchdog/bcm2835_wdt.c
++++ b/drivers/watchdog/bcm2835_wdt.c
+@@ -12,6 +12,7 @@
+ #include <linux/delay.h>
+ #include <linux/types.h>
++#include <linux/mfd/bcm2835-pm.h>
+ #include <linux/module.h>
+ #include <linux/io.h>
+ #include <linux/watchdog.h>
+@@ -41,6 +42,8 @@ struct bcm2835_wdt {
+       spinlock_t              lock;
+ };
++static struct bcm2835_wdt *bcm2835_power_off_wdt;
++
+ static unsigned int heartbeat;
+ static bool nowayout = WATCHDOG_NOWAYOUT;
+@@ -163,10 +166,7 @@ static struct watchdog_device bcm2835_wd
+  */
+ static void bcm2835_power_off(void)
+ {
+-      struct device_node *np =
+-              of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt");
+-      struct platform_device *pdev = of_find_device_by_node(np);
+-      struct bcm2835_wdt *wdt = platform_get_drvdata(pdev);
++      struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
+       /* Partition 63 tells the firmware that this is a halt */
+       __bcm2835_restart(wdt, 63);
+@@ -174,7 +174,7 @@ static void bcm2835_power_off(void)
+ static int bcm2835_wdt_probe(struct platform_device *pdev)
+ {
+-      struct resource *res;
++      struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
+       struct device *dev = &pdev->dev;
+       struct bcm2835_wdt *wdt;
+       int err;
+@@ -186,10 +186,7 @@ static int bcm2835_wdt_probe(struct plat
+       spin_lock_init(&wdt->lock);
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      wdt->base = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(wdt->base))
+-              return PTR_ERR(wdt->base);
++      wdt->base = pm->base;
+       watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
+       watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
+@@ -216,8 +213,10 @@ static int bcm2835_wdt_probe(struct plat
+               return err;
+       }
+-      if (pm_power_off == NULL)
++      if (pm_power_off == NULL) {
+               pm_power_off = bcm2835_power_off;
++              bcm2835_power_off_wdt = wdt;
++      }
+       dev_info(dev, "Broadcom BCM2835 watchdog timer");
+       return 0;
+@@ -231,18 +230,11 @@ static int bcm2835_wdt_remove(struct pla
+       return 0;
+ }
+-static const struct of_device_id bcm2835_wdt_of_match[] = {
+-      { .compatible = "brcm,bcm2835-pm-wdt", },
+-      {},
+-};
+-MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
+-
+ static struct platform_driver bcm2835_wdt_driver = {
+       .probe          = bcm2835_wdt_probe,
+       .remove         = bcm2835_wdt_remove,
+       .driver = {
+               .name =         "bcm2835-wdt",
+-              .of_match_table = bcm2835_wdt_of_match,
+       },
+ };
+ module_platform_driver(bcm2835_wdt_driver);
+--- /dev/null
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -0,0 +1,13 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++
++#ifndef BCM2835_MFD_PM_H
++#define BCM2835_MFD_PM_H
++
++#include <linux/regmap.h>
++
++struct bcm2835_pm {
++      struct device *dev;
++      void __iomem *base;
++};
++
++#endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0480-drivers-char-add-chardev-for-mmap-ing-Argon-control-.patch b/target/linux/brcm2708/patches-4.19/950-0480-drivers-char-add-chardev-for-mmap-ing-Argon-control-.patch
deleted file mode 100644 (file)
index fb358aa..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-From 0be0d6439128366a8d2ac0afaf88f19209171e51 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Thu, 9 May 2019 14:30:37 +0100
-Subject: [PATCH] drivers: char: add chardev for mmap'ing Argon control
- registers
-
-Based on the gpiomem driver, allow mapping of the decoder register
-spaces such that userspace can access control/status registers.
-This driver is intended for use with a custom ffmpeg backend accelerator
-prior to a v4l2 driver being written.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/char/broadcom/Kconfig     |   8 +
- drivers/char/broadcom/Makefile    |   1 +
- drivers/char/broadcom/argon-mem.c | 277 ++++++++++++++++++++++++++++++
- 3 files changed, 286 insertions(+)
- create mode 100644 drivers/char/broadcom/argon-mem.c
-
---- a/drivers/char/broadcom/Kconfig
-+++ b/drivers/char/broadcom/Kconfig
-@@ -49,3 +49,11 @@ config BCM2835_SMI_DEV
-               This driver provides a character device interface (ioctl + read/write) to
-               Broadcom's Secondary Memory interface. The low-level functionality is provided
-               by the SMI driver itself.
-+
-+config ARGON_MEM
-+      tristate "Character device driver for the Argon decoder hardware"
-+      default n
-+      help
-+              This driver provides a character device interface for memory-map operations
-+              so userspace tools can access the control and status registers of the Argon
-+              video decoder hardware.
---- a/drivers/char/broadcom/Makefile
-+++ b/drivers/char/broadcom/Makefile
-@@ -4,3 +4,4 @@ obj-$(CONFIG_BCM_VC_SM)         += vc_sm
- obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
- obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o
-+obj-$(CONFIG_ARGON_MEM)               += argon-mem.o
---- /dev/null
-+++ b/drivers/char/broadcom/argon-mem.c
-@@ -0,0 +1,277 @@
-+/**
-+ * argon-mem.c - character device access to the Argon decoder registers
-+ *
-+ * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
-+ * register blocks such that ffmpeg plugins can access the hardware.
-+ *
-+ * Jonathan Bell <jonathan@raspberrypi.org>
-+ * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions, and the following disclaimer,
-+ *    without modification.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 3. The names of the above-listed copyright holders may not be used
-+ *    to endorse or promote products derived from this software without
-+ *    specific prior written permission.
-+ *
-+ * ALTERNATIVELY, this software may be distributed under the terms of the
-+ * GNU General Public License ("GPL") version 2, as published by the Free
-+ * Software Foundation.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/cdev.h>
-+#include <linux/pagemap.h>
-+#include <linux/io.h>
-+
-+#define DRIVER_NAME "argon-mem"
-+#define DEVICE_MINOR 0
-+
-+struct argon_mem_priv {
-+      dev_t devid;
-+      struct class *class;
-+      struct cdev argon_mem_cdev;
-+      unsigned long regs_phys;
-+      unsigned long mem_window_len;
-+      struct device *dev;
-+      const char *name;
-+};
-+
-+static int argon_mem_open(struct inode *inode, struct file *file)
-+{
-+      int dev = iminor(inode);
-+      int ret = 0;
-+      struct argon_mem_priv *priv;
-+      if (dev != DEVICE_MINOR)
-+              ret = -ENXIO;
-+
-+      priv = container_of(inode->i_cdev, struct argon_mem_priv,
-+                              argon_mem_cdev);
-+      if (!priv)
-+              return -EINVAL;
-+      file->private_data = priv;
-+      return ret;
-+}
-+
-+static int argon_mem_release(struct inode *inode, struct file *file)
-+{
-+      int dev = iminor(inode);
-+      int ret = 0;
-+
-+      if (dev != DEVICE_MINOR)
-+              ret = -ENXIO;
-+
-+      return ret;
-+}
-+
-+static const struct vm_operations_struct argon_mem_vm_ops = {
-+#ifdef CONFIG_HAVE_IOREMAP_PROT
-+      .access = generic_access_phys
-+#endif
-+};
-+
-+static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+      struct argon_mem_priv *priv;
-+      unsigned long pages;
-+
-+      priv = file->private_data;
-+      pages = priv->regs_phys >> PAGE_SHIFT;
-+      /*
-+       * The address decode is far larger than the actual number of registers.
-+       * Just map the whole lot in.
-+       */
-+      vma->vm_page_prot = phys_mem_access_prot(file, pages,
-+                                               priv->mem_window_len,
-+                                               vma->vm_page_prot);
-+      vma->vm_ops = &argon_mem_vm_ops;
-+      if (remap_pfn_range(vma, vma->vm_start,
-+                      pages,
-+                      priv->mem_window_len,
-+                      vma->vm_page_prot)) {
-+              return -EAGAIN;
-+      }
-+      return 0;
-+}
-+
-+static const struct file_operations
-+argon_mem_fops = {
-+      .owner = THIS_MODULE,
-+      .open = argon_mem_open,
-+      .release = argon_mem_release,
-+      .mmap = argon_mem_mmap,
-+};
-+
-+static const struct of_device_id argon_mem_of_match[];
-+static int argon_mem_probe(struct platform_device *pdev)
-+{
-+      int err;
-+      void *ptr_err;
-+      const struct of_device_id *id;
-+      struct device *dev = &pdev->dev;
-+      struct device *argon_mem_dev;
-+      struct resource *ioresource;
-+      struct argon_mem_priv *priv;
-+
-+
-+      /* Allocate buffers and instance data */
-+
-+      priv = kzalloc(sizeof(struct argon_mem_priv), GFP_KERNEL);
-+
-+      if (!priv) {
-+              err = -ENOMEM;
-+              goto failed_inst_alloc;
-+      }
-+      platform_set_drvdata(pdev, priv);
-+
-+      priv->dev = dev;
-+      id = of_match_device(argon_mem_of_match, dev);
-+      if (!id)
-+              return -EINVAL;
-+      priv->name = id->data;
-+
-+      ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (ioresource) {
-+              priv->regs_phys = ioresource->start;
-+              priv->mem_window_len = ioresource->end - ioresource->start;
-+      } else {
-+              dev_err(priv->dev, "failed to get IO resource");
-+              err = -ENOENT;
-+              goto failed_get_resource;
-+      }
-+
-+      /* Create character device entries */
-+
-+      err = alloc_chrdev_region(&priv->devid,
-+                                DEVICE_MINOR, 1, priv->name);
-+      if (err != 0) {
-+              dev_err(priv->dev, "unable to allocate device number");
-+              goto failed_alloc_chrdev;
-+      }
-+      cdev_init(&priv->argon_mem_cdev, &argon_mem_fops);
-+      priv->argon_mem_cdev.owner = THIS_MODULE;
-+      err = cdev_add(&priv->argon_mem_cdev, priv->devid, 1);
-+      if (err != 0) {
-+              dev_err(priv->dev, "unable to register device");
-+              goto failed_cdev_add;
-+      }
-+
-+      /* Create sysfs entries */
-+
-+      priv->class = class_create(THIS_MODULE, priv->name);
-+      ptr_err = priv->class;
-+      if (IS_ERR(ptr_err))
-+              goto failed_class_create;
-+
-+      argon_mem_dev = device_create(priv->class, NULL,
-+                                      priv->devid, NULL,
-+                                      priv->name);
-+      ptr_err = argon_mem_dev;
-+      if (IS_ERR(ptr_err))
-+              goto failed_device_create;
-+
-+      dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
-+              priv->name, priv->regs_phys, priv->mem_window_len);
-+
-+      return 0;
-+
-+failed_device_create:
-+      class_destroy(priv->class);
-+failed_class_create:
-+      cdev_del(&priv->argon_mem_cdev);
-+      err = PTR_ERR(ptr_err);
-+failed_cdev_add:
-+      unregister_chrdev_region(priv->devid, 1);
-+failed_alloc_chrdev:
-+failed_get_resource:
-+      kfree(priv);
-+failed_inst_alloc:
-+      dev_err(priv->dev, "could not load argon_mem");
-+      return err;
-+}
-+
-+static int argon_mem_remove(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct argon_mem_priv *priv = platform_get_drvdata(pdev);
-+
-+      device_destroy(priv->class, priv->devid);
-+      class_destroy(priv->class);
-+      cdev_del(&priv->argon_mem_cdev);
-+      unregister_chrdev_region(priv->devid, 1);
-+      kfree(priv);
-+
-+      dev_info(dev, "%s driver removed - OK", priv->name);
-+      return 0;
-+}
-+
-+static const char argon_hevc_name[] = "argon-hevcmem";
-+static const char argon_h264_name[] = "argon-h264mem";
-+static const char argon_vp9_name[] = "argon-vp9mem";
-+static const char argon_intc_name[] = "argon-intcmem";
-+
-+static const struct of_device_id argon_mem_of_match[] = {
-+      {
-+              .compatible = "raspberrypi,argon-hevc-decoder",
-+              .data = &argon_hevc_name,
-+      },
-+      {
-+              .compatible = "raspberrypi,argon-h264-decoder",
-+              .data = &argon_h264_name,
-+      },
-+      {
-+              .compatible = "raspberrypi,argon-vp9-decoder",
-+              .data = &argon_vp9_name,
-+      },
-+      /* The "intc" is included as this block of hardware contains the
-+       * "frame done" status flags.
-+       */
-+      {
-+              .compatible = "raspberrypi,argon-local-intc",
-+              .data = &argon_intc_name,
-+      },
-+      { /* sentinel */ },
-+};
-+
-+MODULE_DEVICE_TABLE(of, argon_mem_of_match);
-+
-+static struct platform_driver argon_mem_driver = {
-+      .probe = argon_mem_probe,
-+      .remove = argon_mem_remove,
-+      .driver = {
-+                 .name = DRIVER_NAME,
-+                 .owner = THIS_MODULE,
-+                 .of_match_table = argon_mem_of_match,
-+                 },
-+};
-+
-+module_platform_driver(argon_mem_driver);
-+
-+MODULE_ALIAS("platform:argon-mem");
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Driver for accessing Argon decoder registers from userspace");
-+MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
diff --git a/target/linux/brcm2708/patches-4.19/950-0481-clk-bcm2835-Don-t-wait-for-pllh-lock.patch b/target/linux/brcm2708/patches-4.19/950-0481-clk-bcm2835-Don-t-wait-for-pllh-lock.patch
deleted file mode 100644 (file)
index e8ab380..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 3924edc9bd3c55d48c383c1046d75e163ce3cddb Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 23 Jan 2019 16:11:50 +0000
-Subject: [PATCH] clk-bcm2835: Don't wait for pllh lock
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 18 ++++++++++--------
- 1 file changed, 10 insertions(+), 8 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -627,15 +627,17 @@ static int bcm2835_pll_on(struct clk_hw
-       spin_unlock(&cprman->regs_lock);
-       /* Wait for the PLL to lock. */
--      timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
--      while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
--              if (ktime_after(ktime_get(), timeout)) {
--                      dev_err(cprman->dev, "%s: couldn't lock PLL\n",
--                              clk_hw_get_name(hw));
--                      return -ETIMEDOUT;
--              }
-+      if (strcmp(data->name, "pllh")) {
-+              timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
-+              while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
-+                      if (ktime_after(ktime_get(), timeout)) {
-+                              dev_err(cprman->dev, "%s: couldn't lock PLL\n",
-+                                      clk_hw_get_name(hw));
-+                              return -ETIMEDOUT;
-+                      }
--              cpu_relax();
-+                      cpu_relax();
-+              }
-       }
-       cprman_write(cprman, data->a2w_ctrl_reg,
diff --git a/target/linux/brcm2708/patches-4.19/950-0481-soc-bcm-bcm2835-pm-Add-support-for-power-domains-und.patch b/target/linux/brcm2708/patches-4.19/950-0481-soc-bcm-bcm2835-pm-Add-support-for-power-domains-und.patch
new file mode 100644 (file)
index 0000000..229dbe5
--- /dev/null
@@ -0,0 +1,825 @@
+From fd8ca458728baabe9cae37836088a33c8642d420 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:48 -0800
+Subject: [PATCH] soc: bcm: bcm2835-pm: Add support for power domains
+ under a new binding.
+
+This provides a free software alternative to raspberrypi-power.c's
+firmware calls to manage power domains.  It also exposes a reset line,
+where previously the vc4 driver had to try to force power off the
+domain in order to trigger a reset.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+(cherry picked from commit 670c672608a1ffcbc7ac0f872734843593bb8b15)
+---
+ drivers/mfd/bcm2835-pm.c             |  36 +-
+ drivers/soc/bcm/Kconfig              |  11 +
+ drivers/soc/bcm/Makefile             |   1 +
+ drivers/soc/bcm/bcm2835-power.c      | 661 +++++++++++++++++++++++++++
+ include/dt-bindings/soc/bcm2835-pm.h |  28 ++
+ include/linux/mfd/bcm2835-pm.h       |   1 +
+ 6 files changed, 734 insertions(+), 4 deletions(-)
+ create mode 100644 drivers/soc/bcm/bcm2835-power.c
+ create mode 100644 include/dt-bindings/soc/bcm2835-pm.h
+
+--- a/drivers/mfd/bcm2835-pm.c
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -3,7 +3,7 @@
+  * PM MFD driver for Broadcom BCM2835
+  *
+  * This driver binds to the PM block and creates the MFD device for
+- * the WDT driver.
++ * the WDT and power drivers.
+  */
+ #include <linux/delay.h>
+@@ -21,11 +21,16 @@ static const struct mfd_cell bcm2835_pm_
+       { .name = "bcm2835-wdt" },
+ };
++static const struct mfd_cell bcm2835_power_devs[] = {
++      { .name = "bcm2835-power" },
++};
++
+ static int bcm2835_pm_probe(struct platform_device *pdev)
+ {
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       struct bcm2835_pm *pm;
++      int ret;
+       pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
+       if (!pm)
+@@ -39,13 +44,36 @@ static int bcm2835_pm_probe(struct platf
+       if (IS_ERR(pm->base))
+               return PTR_ERR(pm->base);
+-      return devm_mfd_add_devices(dev, -1,
+-                                  bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
+-                                  NULL, 0, NULL);
++      ret = devm_mfd_add_devices(dev, -1,
++                                 bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
++                                 NULL, 0, NULL);
++      if (ret)
++              return ret;
++
++      /* We'll use the presence of the AXI ASB regs in the
++       * bcm2835-pm binding as the key for whether we can reference
++       * the full PM register range and support power domains.
++       */
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++      if (res) {
++              pm->asb = devm_ioremap_resource(dev, res);
++              if (IS_ERR(pm->asb))
++                      return PTR_ERR(pm->asb);
++
++              ret = devm_mfd_add_devices(dev, -1,
++                                         bcm2835_power_devs,
++                                         ARRAY_SIZE(bcm2835_power_devs),
++                                         NULL, 0, NULL);
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
+ }
+ static const struct of_device_id bcm2835_pm_of_match[] = {
+       { .compatible = "brcm,bcm2835-pm-wdt", },
++      { .compatible = "brcm,bcm2835-pm", },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
+--- a/drivers/soc/bcm/Kconfig
++++ b/drivers/soc/bcm/Kconfig
+@@ -1,5 +1,16 @@
+ menu "Broadcom SoC drivers"
++config BCM2835_POWER
++      bool "BCM2835 power domain driver"
++      depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
++      select PM_GENERIC_DOMAINS if PM
++      select RESET_CONTROLLER
++      help
++        This enables support for the BCM2835 power domains and reset
++        controller.  Any usage of power domains by the Raspberry Pi
++        firmware means that Linux usage of the same power domain
++        must be accessed using the RASPBERRYPI_POWER driver
++
+ config RASPBERRYPI_POWER
+       bool "Raspberry Pi power domain driver"
+       depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
+--- a/drivers/soc/bcm/Makefile
++++ b/drivers/soc/bcm/Makefile
+@@ -1,2 +1,3 @@
++obj-$(CONFIG_BCM2835_POWER)   += bcm2835-power.o
+ obj-$(CONFIG_RASPBERRYPI_POWER)       += raspberrypi-power.o
+ obj-$(CONFIG_SOC_BRCMSTB)     += brcmstb/
+--- /dev/null
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -0,0 +1,661 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Power domain driver for Broadcom BCM2835
++ *
++ * Copyright (C) 2018 Broadcom
++ */
++
++#include <dt-bindings/soc/bcm2835-pm.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/mfd/bcm2835-pm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm_domain.h>
++#include <linux/reset-controller.h>
++#include <linux/types.h>
++
++#define PM_GNRIC                        0x00
++#define PM_AUDIO                        0x04
++#define PM_STATUS                       0x18
++#define PM_RSTC                               0x1c
++#define PM_RSTS                               0x20
++#define PM_WDOG                               0x24
++#define PM_PADS0                      0x28
++#define PM_PADS2                      0x2c
++#define PM_PADS3                      0x30
++#define PM_PADS4                      0x34
++#define PM_PADS5                      0x38
++#define PM_PADS6                      0x3c
++#define PM_CAM0                               0x44
++#define PM_CAM0_LDOHPEN                       BIT(2)
++#define PM_CAM0_LDOLPEN                       BIT(1)
++#define PM_CAM0_CTRLEN                        BIT(0)
++
++#define PM_CAM1                               0x48
++#define PM_CAM1_LDOHPEN                       BIT(2)
++#define PM_CAM1_LDOLPEN                       BIT(1)
++#define PM_CAM1_CTRLEN                        BIT(0)
++
++#define PM_CCP2TX                     0x4c
++#define PM_CCP2TX_LDOEN                       BIT(1)
++#define PM_CCP2TX_CTRLEN              BIT(0)
++
++#define PM_DSI0                               0x50
++#define PM_DSI0_LDOHPEN                       BIT(2)
++#define PM_DSI0_LDOLPEN                       BIT(1)
++#define PM_DSI0_CTRLEN                        BIT(0)
++
++#define PM_DSI1                               0x54
++#define PM_DSI1_LDOHPEN                       BIT(2)
++#define PM_DSI1_LDOLPEN                       BIT(1)
++#define PM_DSI1_CTRLEN                        BIT(0)
++
++#define PM_HDMI                               0x58
++#define PM_HDMI_RSTDR                 BIT(19)
++#define PM_HDMI_LDOPD                 BIT(1)
++#define PM_HDMI_CTRLEN                        BIT(0)
++
++#define PM_USB                                0x5c
++/* The power gates must be enabled with this bit before enabling the LDO in the
++ * USB block.
++ */
++#define PM_USB_CTRLEN                 BIT(0)
++
++#define PM_PXLDO                      0x60
++#define PM_PXBG                               0x64
++#define PM_DFT                                0x68
++#define PM_SMPS                               0x6c
++#define PM_XOSC                               0x70
++#define PM_SPAREW                     0x74
++#define PM_SPARER                     0x78
++#define PM_AVS_RSTDR                  0x7c
++#define PM_AVS_STAT                   0x80
++#define PM_AVS_EVENT                  0x84
++#define PM_AVS_INTEN                  0x88
++#define PM_DUMMY                      0xfc
++
++#define PM_IMAGE                      0x108
++#define PM_GRAFX                      0x10c
++#define PM_PROC                               0x110
++#define PM_ENAB                               BIT(12)
++#define PM_ISPRSTN                    BIT(8)
++#define PM_H264RSTN                   BIT(7)
++#define PM_PERIRSTN                   BIT(6)
++#define PM_V3DRSTN                    BIT(6)
++#define PM_ISFUNC                     BIT(5)
++#define PM_MRDONE                     BIT(4)
++#define PM_MEMREP                     BIT(3)
++#define PM_ISPOW                      BIT(2)
++#define PM_POWOK                      BIT(1)
++#define PM_POWUP                      BIT(0)
++#define PM_INRUSH_SHIFT                       13
++#define PM_INRUSH_3_5_MA              0
++#define PM_INRUSH_5_MA                        1
++#define PM_INRUSH_10_MA                       2
++#define PM_INRUSH_20_MA                       3
++#define PM_INRUSH_MASK                        (3 << PM_INRUSH_SHIFT)
++
++#define PM_PASSWORD                   0x5a000000
++
++#define PM_WDOG_TIME_SET              0x000fffff
++#define PM_RSTC_WRCFG_CLR             0xffffffcf
++#define PM_RSTS_HADWRH_SET            0x00000040
++#define PM_RSTC_WRCFG_SET             0x00000030
++#define PM_RSTC_WRCFG_FULL_RESET      0x00000020
++#define PM_RSTC_RESET                 0x00000102
++
++#define PM_READ(reg) readl(power->base + (reg))
++#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
++
++#define ASB_BRDG_VERSION                0x00
++#define ASB_CPR_CTRL                    0x04
++
++#define ASB_V3D_S_CTRL                        0x08
++#define ASB_V3D_M_CTRL                        0x0c
++#define ASB_ISP_S_CTRL                        0x10
++#define ASB_ISP_M_CTRL                        0x14
++#define ASB_H264_S_CTRL                       0x18
++#define ASB_H264_M_CTRL                       0x1c
++
++#define ASB_REQ_STOP                    BIT(0)
++#define ASB_ACK                         BIT(1)
++#define ASB_EMPTY                       BIT(2)
++#define ASB_FULL                        BIT(3)
++
++#define ASB_AXI_BRDG_ID                       0x20
++
++#define ASB_READ(reg) readl(power->asb + (reg))
++#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
++
++struct bcm2835_power_domain {
++      struct generic_pm_domain base;
++      struct bcm2835_power *power;
++      u32 domain;
++      struct clk *clk;
++};
++
++struct bcm2835_power {
++      struct device           *dev;
++      /* PM registers. */
++      void __iomem            *base;
++      /* AXI Async bridge registers. */
++      void __iomem            *asb;
++
++      struct genpd_onecell_data pd_xlate;
++      struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
++      struct reset_controller_dev reset;
++};
++
++static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
++{
++      u64 start = ktime_get_ns();
++
++      /* Enable the module's async AXI bridges. */
++      ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
++      while (ASB_READ(reg) & ASB_ACK) {
++              cpu_relax();
++              if (ktime_get_ns() - start >= 1000)
++                      return -ETIMEDOUT;
++      }
++
++      return 0;
++}
++
++static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
++{
++      u64 start = ktime_get_ns();
++
++      /* Enable the module's async AXI bridges. */
++      ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
++      while (!(ASB_READ(reg) & ASB_ACK)) {
++              cpu_relax();
++              if (ktime_get_ns() - start >= 1000)
++                      return -ETIMEDOUT;
++      }
++
++      return 0;
++}
++
++static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
++{
++      struct bcm2835_power *power = pd->power;
++
++      /* Enable functional isolation */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
++
++      /* Enable electrical isolation */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
++
++      /* Open the power switches. */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
++
++      return 0;
++}
++
++static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
++{
++      struct bcm2835_power *power = pd->power;
++      struct device *dev = power->dev;
++      u64 start;
++      int ret;
++      int inrush;
++      bool powok;
++
++      /* If it was already powered on by the fw, leave it that way. */
++      if (PM_READ(pm_reg) & PM_POWUP)
++              return 0;
++
++      /* Enable power.  Allowing too much current at once may result
++       * in POWOK never getting set, so start low and ramp it up as
++       * necessary to succeed.
++       */
++      powok = false;
++      for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
++              PM_WRITE(pm_reg,
++                       (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
++                       (inrush << PM_INRUSH_SHIFT) |
++                       PM_POWUP);
++
++              start = ktime_get_ns();
++              while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
++                      cpu_relax();
++                      if (ktime_get_ns() - start >= 3000)
++                              break;
++              }
++      }
++      if (!powok) {
++              dev_err(dev, "Timeout waiting for %s power OK\n",
++                      pd->base.name);
++              ret = -ETIMEDOUT;
++              goto err_disable_powup;
++      }
++
++      /* Disable electrical isolation */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
++
++      /* Repair memory */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
++      start = ktime_get_ns();
++      while (!(PM_READ(pm_reg) & PM_MRDONE)) {
++              cpu_relax();
++              if (ktime_get_ns() - start >= 1000) {
++                      dev_err(dev, "Timeout waiting for %s memory repair\n",
++                              pd->base.name);
++                      ret = -ETIMEDOUT;
++                      goto err_disable_ispow;
++              }
++      }
++
++      /* Disable functional isolation */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
++
++      return 0;
++
++err_disable_ispow:
++      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
++err_disable_powup:
++      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
++      return ret;
++}
++
++static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
++                              u32 pm_reg,
++                              u32 asb_m_reg,
++                              u32 asb_s_reg,
++                              u32 reset_flags)
++{
++      struct bcm2835_power *power = pd->power;
++      int ret;
++
++      ret = clk_prepare_enable(pd->clk);
++      if (ret) {
++              dev_err(power->dev, "Failed to enable clock for %s\n",
++                      pd->base.name);
++              return ret;
++      }
++
++      /* Wait 32 clocks for reset to propagate, 1 us will be enough */
++      udelay(1);
++
++      clk_disable_unprepare(pd->clk);
++
++      /* Deassert the resets. */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
++
++      ret = clk_prepare_enable(pd->clk);
++      if (ret) {
++              dev_err(power->dev, "Failed to enable clock for %s\n",
++                      pd->base.name);
++              goto err_enable_resets;
++      }
++
++      ret = bcm2835_asb_enable(power, asb_m_reg);
++      if (ret) {
++              dev_err(power->dev, "Failed to enable ASB master for %s\n",
++                      pd->base.name);
++              goto err_disable_clk;
++      }
++      ret = bcm2835_asb_enable(power, asb_s_reg);
++      if (ret) {
++              dev_err(power->dev, "Failed to enable ASB slave for %s\n",
++                      pd->base.name);
++              goto err_disable_asb_master;
++      }
++
++      return 0;
++
++err_disable_asb_master:
++      bcm2835_asb_disable(power, asb_m_reg);
++err_disable_clk:
++      clk_disable_unprepare(pd->clk);
++err_enable_resets:
++      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
++      return ret;
++}
++
++static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
++                               u32 pm_reg,
++                               u32 asb_m_reg,
++                               u32 asb_s_reg,
++                               u32 reset_flags)
++{
++      struct bcm2835_power *power = pd->power;
++      int ret;
++
++      ret = bcm2835_asb_disable(power, asb_s_reg);
++      if (ret) {
++              dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
++                       pd->base.name);
++              return ret;
++      }
++      ret = bcm2835_asb_disable(power, asb_m_reg);
++      if (ret) {
++              dev_warn(power->dev, "Failed to disable ASB master for %s\n",
++                       pd->base.name);
++              bcm2835_asb_enable(power, asb_s_reg);
++              return ret;
++      }
++
++      clk_disable_unprepare(pd->clk);
++
++      /* Assert the resets. */
++      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
++
++      return 0;
++}
++
++static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
++{
++      struct bcm2835_power_domain *pd =
++              container_of(domain, struct bcm2835_power_domain, base);
++      struct bcm2835_power *power = pd->power;
++
++      switch (pd->domain) {
++      case BCM2835_POWER_DOMAIN_GRAFX:
++              return bcm2835_power_power_on(pd, PM_GRAFX);
++
++      case BCM2835_POWER_DOMAIN_GRAFX_V3D:
++              return bcm2835_asb_power_on(pd, PM_GRAFX,
++                                          ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
++                                          PM_V3DRSTN);
++
++      case BCM2835_POWER_DOMAIN_IMAGE:
++              return bcm2835_power_power_on(pd, PM_IMAGE);
++
++      case BCM2835_POWER_DOMAIN_IMAGE_PERI:
++              return bcm2835_asb_power_on(pd, PM_IMAGE,
++                                          0, 0,
++                                          PM_PERIRSTN);
++
++      case BCM2835_POWER_DOMAIN_IMAGE_ISP:
++              return bcm2835_asb_power_on(pd, PM_IMAGE,
++                                          ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
++                                          PM_ISPRSTN);
++
++      case BCM2835_POWER_DOMAIN_IMAGE_H264:
++              return bcm2835_asb_power_on(pd, PM_IMAGE,
++                                          ASB_H264_M_CTRL, ASB_H264_S_CTRL,
++                                          PM_H264RSTN);
++
++      case BCM2835_POWER_DOMAIN_USB:
++              PM_WRITE(PM_USB, PM_USB_CTRLEN);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_DSI0:
++              PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
++              PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_DSI1:
++              PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
++              PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_CCP2TX:
++              PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
++              PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_HDMI:
++              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
++              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
++              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
++              usleep_range(100, 200);
++              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
++              return 0;
++
++      default:
++              dev_err(power->dev, "Invalid domain %d\n", pd->domain);
++              return -EINVAL;
++      }
++}
++
++static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
++{
++      struct bcm2835_power_domain *pd =
++              container_of(domain, struct bcm2835_power_domain, base);
++      struct bcm2835_power *power = pd->power;
++
++      switch (pd->domain) {
++      case BCM2835_POWER_DOMAIN_GRAFX:
++              return bcm2835_power_power_off(pd, PM_GRAFX);
++
++      case BCM2835_POWER_DOMAIN_GRAFX_V3D:
++              return bcm2835_asb_power_off(pd, PM_GRAFX,
++                                           ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
++                                           PM_V3DRSTN);
++
++      case BCM2835_POWER_DOMAIN_IMAGE:
++              return bcm2835_power_power_off(pd, PM_IMAGE);
++
++      case BCM2835_POWER_DOMAIN_IMAGE_PERI:
++              return bcm2835_asb_power_off(pd, PM_IMAGE,
++                                           0, 0,
++                                           PM_PERIRSTN);
++
++      case BCM2835_POWER_DOMAIN_IMAGE_ISP:
++              return bcm2835_asb_power_off(pd, PM_IMAGE,
++                                           ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
++                                           PM_ISPRSTN);
++
++      case BCM2835_POWER_DOMAIN_IMAGE_H264:
++              return bcm2835_asb_power_off(pd, PM_IMAGE,
++                                           ASB_H264_M_CTRL, ASB_H264_S_CTRL,
++                                           PM_H264RSTN);
++
++      case BCM2835_POWER_DOMAIN_USB:
++              PM_WRITE(PM_USB, 0);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_DSI0:
++              PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
++              PM_WRITE(PM_DSI0, 0);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_DSI1:
++              PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
++              PM_WRITE(PM_DSI1, 0);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_CCP2TX:
++              PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
++              PM_WRITE(PM_CCP2TX, 0);
++              return 0;
++
++      case BCM2835_POWER_DOMAIN_HDMI:
++              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
++              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
++              return 0;
++
++      default:
++              dev_err(power->dev, "Invalid domain %d\n", pd->domain);
++              return -EINVAL;
++      }
++}
++
++static void
++bcm2835_init_power_domain(struct bcm2835_power *power,
++                        int pd_xlate_index, const char *name)
++{
++      struct device *dev = power->dev;
++      struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
++
++      dom->clk = devm_clk_get(dev->parent, name);
++
++      dom->base.name = name;
++      dom->base.power_on = bcm2835_power_pd_power_on;
++      dom->base.power_off = bcm2835_power_pd_power_off;
++
++      dom->domain = pd_xlate_index;
++      dom->power = power;
++
++      /* XXX: on/off at boot? */
++      pm_genpd_init(&dom->base, NULL, true);
++
++      power->pd_xlate.domains[pd_xlate_index] = &dom->base;
++}
++
++/** bcm2835_reset_reset - Resets a block that has a reset line in the
++ * PM block.
++ *
++ * The consumer of the reset controller must have the power domain up
++ * -- there's no reset ability with the power domain down.  To reset
++ * the sub-block, we just disable its access to memory through the
++ * ASB, reset, and re-enable.
++ */
++static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
++                             unsigned long id)
++{
++      struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
++                                                 reset);
++      struct bcm2835_power_domain *pd;
++      int ret;
++
++      switch (id) {
++      case BCM2835_RESET_V3D:
++              pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
++              break;
++      case BCM2835_RESET_H264:
++              pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
++              break;
++      case BCM2835_RESET_ISP:
++              pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
++              break;
++      default:
++              dev_err(power->dev, "Bad reset id %ld\n", id);
++              return -EINVAL;
++      }
++
++      ret = bcm2835_power_pd_power_off(&pd->base);
++      if (ret)
++              return ret;
++
++      return bcm2835_power_pd_power_on(&pd->base);
++}
++
++static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
++                              unsigned long id)
++{
++      struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
++                                                 reset);
++
++      switch (id) {
++      case BCM2835_RESET_V3D:
++              return !PM_READ(PM_GRAFX & PM_V3DRSTN);
++      case BCM2835_RESET_H264:
++              return !PM_READ(PM_IMAGE & PM_H264RSTN);
++      case BCM2835_RESET_ISP:
++              return !PM_READ(PM_IMAGE & PM_ISPRSTN);
++      default:
++              return -EINVAL;
++      }
++}
++
++const struct reset_control_ops bcm2835_reset_ops = {
++      .reset = bcm2835_reset_reset,
++      .status = bcm2835_reset_status,
++};
++
++static const char *const power_domain_names[] = {
++      [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
++      [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
++
++      [BCM2835_POWER_DOMAIN_IMAGE] = "image",
++      [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
++      [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
++      [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
++
++      [BCM2835_POWER_DOMAIN_USB] = "usb",
++      [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
++      [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
++      [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
++      [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
++      [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
++      [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
++};
++
++static int bcm2835_power_probe(struct platform_device *pdev)
++{
++      struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
++      struct device *dev = &pdev->dev;
++      struct bcm2835_power *power;
++      static const struct {
++              int parent, child;
++      } domain_deps[] = {
++              { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
++              { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
++              { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
++              { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
++              { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
++              { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
++              { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
++      };
++      int ret, i;
++      u32 id;
++
++      power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
++      if (!power)
++              return -ENOMEM;
++      platform_set_drvdata(pdev, power);
++
++      power->dev = dev;
++      power->base = pm->base;
++      power->asb = pm->asb;
++
++      id = ASB_READ(ASB_AXI_BRDG_ID);
++      if (id != 0x62726467 /* "BRDG" */) {
++              dev_err(dev, "ASB register ID returned 0x%08x\n", id);
++              return -ENODEV;
++      }
++
++      power->pd_xlate.domains = devm_kcalloc(dev,
++                                             ARRAY_SIZE(power_domain_names),
++                                             sizeof(*power->pd_xlate.domains),
++                                             GFP_KERNEL);
++      if (!power->pd_xlate.domains)
++              return -ENOMEM;
++
++      power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
++
++      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
++              bcm2835_init_power_domain(power, i, power_domain_names[i]);
++
++      for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
++              pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
++                                     &power->domains[domain_deps[i].child].base);
++      }
++
++      power->reset.owner = THIS_MODULE;
++      power->reset.nr_resets = BCM2835_RESET_COUNT;
++      power->reset.ops = &bcm2835_reset_ops;
++      power->reset.of_node = dev->parent->of_node;
++
++      ret = devm_reset_controller_register(dev, &power->reset);
++      if (ret)
++              return ret;
++
++      of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
++
++      dev_info(dev, "Broadcom BCM2835 power domains driver");
++      return 0;
++}
++
++static int bcm2835_power_remove(struct platform_device *pdev)
++{
++      return 0;
++}
++
++static struct platform_driver bcm2835_power_driver = {
++      .probe          = bcm2835_power_probe,
++      .remove         = bcm2835_power_remove,
++      .driver = {
++              .name = "bcm2835-power",
++      },
++};
++module_platform_driver(bcm2835_power_driver);
++
++MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
++MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/include/dt-bindings/soc/bcm2835-pm.h
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
++
++#ifndef _DT_BINDINGS_ARM_BCM2835_PM_H
++#define _DT_BINDINGS_ARM_BCM2835_PM_H
++
++#define BCM2835_POWER_DOMAIN_GRAFX            0
++#define BCM2835_POWER_DOMAIN_GRAFX_V3D                1
++#define BCM2835_POWER_DOMAIN_IMAGE            2
++#define BCM2835_POWER_DOMAIN_IMAGE_PERI               3
++#define BCM2835_POWER_DOMAIN_IMAGE_ISP                4
++#define BCM2835_POWER_DOMAIN_IMAGE_H264               5
++#define BCM2835_POWER_DOMAIN_USB              6
++#define BCM2835_POWER_DOMAIN_DSI0             7
++#define BCM2835_POWER_DOMAIN_DSI1             8
++#define BCM2835_POWER_DOMAIN_CAM0             9
++#define BCM2835_POWER_DOMAIN_CAM1             10
++#define BCM2835_POWER_DOMAIN_CCP2TX           11
++#define BCM2835_POWER_DOMAIN_HDMI             12
++
++#define BCM2835_POWER_DOMAIN_COUNT            13
++
++#define BCM2835_RESET_V3D                     0
++#define BCM2835_RESET_ISP                     1
++#define BCM2835_RESET_H264                    2
++
++#define BCM2835_RESET_COUNT                   3
++
++#endif /* _DT_BINDINGS_ARM_BCM2835_PM_H */
+--- a/include/linux/mfd/bcm2835-pm.h
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -8,6 +8,7 @@
+ struct bcm2835_pm {
+       struct device *dev;
+       void __iomem *base;
++      void __iomem *asb;
+ };
+ #endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0482-bcm2835-pm-Move-bcm2835-watchdog-s-DT-probe-to-an-MF.patch b/target/linux/brcm2708/patches-4.19/950-0482-bcm2835-pm-Move-bcm2835-watchdog-s-DT-probe-to-an-MF.patch
deleted file mode 100644 (file)
index ff15427..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-From 90964ab2d00546a59086ffd08964da3d2a5cefc9 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 12 Dec 2018 15:51:47 -0800
-Subject: [PATCH] bcm2835-pm: Move bcm2835-watchdog's DT probe to an
- MFD.
-
-The PM block that the wdt driver was binding to actually has multiple
-features we want to expose (power domains, reset, watchdog).  Move the
-DT attachment to a MFD driver and make WDT probe against MFD.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Guenter Roeck <linux@roeck-us.net>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-(cherry picked from commit 5e6acc3e678ed3db746ab4fb53a980861cd711b6)
----
- drivers/mfd/Makefile           |  1 +
- drivers/mfd/bcm2835-pm.c       | 64 ++++++++++++++++++++++++++++++++++
- drivers/watchdog/bcm2835_wdt.c | 26 +++++---------
- include/linux/mfd/bcm2835-pm.h | 13 +++++++
- 4 files changed, 87 insertions(+), 17 deletions(-)
- create mode 100644 drivers/mfd/bcm2835-pm.c
- create mode 100644 include/linux/mfd/bcm2835-pm.h
-
---- a/drivers/mfd/Makefile
-+++ b/drivers/mfd/Makefile
-@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805)    += 88pm805.o 8
- obj-$(CONFIG_MFD_ACT8945A)    += act8945a.o
- obj-$(CONFIG_MFD_SM501)               += sm501.o
- obj-$(CONFIG_MFD_ASIC3)               += asic3.o tmio_core.o
-+obj-$(CONFIG_ARCH_BCM2835)    += bcm2835-pm.o
- obj-$(CONFIG_MFD_BCM590XX)    += bcm590xx.o
- obj-$(CONFIG_MFD_BD9571MWV)   += bd9571mwv.o
- cros_ec_core-objs             := cros_ec.o
---- /dev/null
-+++ b/drivers/mfd/bcm2835-pm.c
-@@ -0,0 +1,64 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * PM MFD driver for Broadcom BCM2835
-+ *
-+ * This driver binds to the PM block and creates the MFD device for
-+ * the WDT driver.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/mfd/bcm2835-pm.h>
-+#include <linux/mfd/core.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/of_platform.h>
-+#include <linux/platform_device.h>
-+#include <linux/types.h>
-+#include <linux/watchdog.h>
-+
-+static const struct mfd_cell bcm2835_pm_devs[] = {
-+      { .name = "bcm2835-wdt" },
-+};
-+
-+static int bcm2835_pm_probe(struct platform_device *pdev)
-+{
-+      struct resource *res;
-+      struct device *dev = &pdev->dev;
-+      struct bcm2835_pm *pm;
-+
-+      pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
-+      if (!pm)
-+              return -ENOMEM;
-+      platform_set_drvdata(pdev, pm);
-+
-+      pm->dev = dev;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      pm->base = devm_ioremap_resource(dev, res);
-+      if (IS_ERR(pm->base))
-+              return PTR_ERR(pm->base);
-+
-+      return devm_mfd_add_devices(dev, -1,
-+                                  bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
-+                                  NULL, 0, NULL);
-+}
-+
-+static const struct of_device_id bcm2835_pm_of_match[] = {
-+      { .compatible = "brcm,bcm2835-pm-wdt", },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
-+
-+static struct platform_driver bcm2835_pm_driver = {
-+      .probe          = bcm2835_pm_probe,
-+      .driver = {
-+              .name = "bcm2835-pm",
-+              .of_match_table = bcm2835_pm_of_match,
-+      },
-+};
-+module_platform_driver(bcm2835_pm_driver);
-+
-+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
-+MODULE_LICENSE("GPL");
---- a/drivers/watchdog/bcm2835_wdt.c
-+++ b/drivers/watchdog/bcm2835_wdt.c
-@@ -12,6 +12,7 @@
- #include <linux/delay.h>
- #include <linux/types.h>
-+#include <linux/mfd/bcm2835-pm.h>
- #include <linux/module.h>
- #include <linux/io.h>
- #include <linux/watchdog.h>
-@@ -41,6 +42,8 @@ struct bcm2835_wdt {
-       spinlock_t              lock;
- };
-+static struct bcm2835_wdt *bcm2835_power_off_wdt;
-+
- static unsigned int heartbeat;
- static bool nowayout = WATCHDOG_NOWAYOUT;
-@@ -163,10 +166,7 @@ static struct watchdog_device bcm2835_wd
-  */
- static void bcm2835_power_off(void)
- {
--      struct device_node *np =
--              of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt");
--      struct platform_device *pdev = of_find_device_by_node(np);
--      struct bcm2835_wdt *wdt = platform_get_drvdata(pdev);
-+      struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
-       /* Partition 63 tells the firmware that this is a halt */
-       __bcm2835_restart(wdt, 63);
-@@ -174,7 +174,7 @@ static void bcm2835_power_off(void)
- static int bcm2835_wdt_probe(struct platform_device *pdev)
- {
--      struct resource *res;
-+      struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
-       struct device *dev = &pdev->dev;
-       struct bcm2835_wdt *wdt;
-       int err;
-@@ -186,10 +186,7 @@ static int bcm2835_wdt_probe(struct plat
-       spin_lock_init(&wdt->lock);
--      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--      wdt->base = devm_ioremap_resource(dev, res);
--      if (IS_ERR(wdt->base))
--              return PTR_ERR(wdt->base);
-+      wdt->base = pm->base;
-       watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
-       watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
-@@ -216,8 +213,10 @@ static int bcm2835_wdt_probe(struct plat
-               return err;
-       }
--      if (pm_power_off == NULL)
-+      if (pm_power_off == NULL) {
-               pm_power_off = bcm2835_power_off;
-+              bcm2835_power_off_wdt = wdt;
-+      }
-       dev_info(dev, "Broadcom BCM2835 watchdog timer");
-       return 0;
-@@ -231,18 +230,11 @@ static int bcm2835_wdt_remove(struct pla
-       return 0;
- }
--static const struct of_device_id bcm2835_wdt_of_match[] = {
--      { .compatible = "brcm,bcm2835-pm-wdt", },
--      {},
--};
--MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
--
- static struct platform_driver bcm2835_wdt_driver = {
-       .probe          = bcm2835_wdt_probe,
-       .remove         = bcm2835_wdt_remove,
-       .driver = {
-               .name =         "bcm2835-wdt",
--              .of_match_table = bcm2835_wdt_of_match,
-       },
- };
- module_platform_driver(bcm2835_wdt_driver);
---- /dev/null
-+++ b/include/linux/mfd/bcm2835-pm.h
-@@ -0,0 +1,13 @@
-+/* SPDX-License-Identifier: GPL-2.0+ */
-+
-+#ifndef BCM2835_MFD_PM_H
-+#define BCM2835_MFD_PM_H
-+
-+#include <linux/regmap.h>
-+
-+struct bcm2835_pm {
-+      struct device *dev;
-+      void __iomem *base;
-+};
-+
-+#endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0482-soc-bcm-bcm2835-pm-Fix-PM_IMAGE_PERI-power-domain-su.patch b/target/linux/brcm2708/patches-4.19/950-0482-soc-bcm-bcm2835-pm-Fix-PM_IMAGE_PERI-power-domain-su.patch
new file mode 100644 (file)
index 0000000..05ae67a
--- /dev/null
@@ -0,0 +1,45 @@
+From ea44a81b7daf511788aecaee7575feff359c5d19 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 11 Jan 2019 17:29:10 -0800
+Subject: [PATCH] soc: bcm: bcm2835-pm: Fix PM_IMAGE_PERI power domain
+ support.
+
+We don't have ASB master/slave regs for this domain, so just skip that
+step.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
+---
+ drivers/soc/bcm/bcm2835-power.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -150,7 +150,12 @@ struct bcm2835_power {
+ static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
+ {
+-      u64 start = ktime_get_ns();
++      u64 start;
++
++      if (!reg)
++              return 0;
++
++      start = ktime_get_ns();
+       /* Enable the module's async AXI bridges. */
+       ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
+@@ -165,7 +170,12 @@ static int bcm2835_asb_enable(struct bcm
+ static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
+ {
+-      u64 start = ktime_get_ns();
++      u64 start;
++
++      if (!reg)
++              return 0;
++
++      start = ktime_get_ns();
+       /* Enable the module's async AXI bridges. */
+       ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
diff --git a/target/linux/brcm2708/patches-4.19/950-0483-soc-bcm-bcm2835-pm-Add-support-for-power-domains-und.patch b/target/linux/brcm2708/patches-4.19/950-0483-soc-bcm-bcm2835-pm-Add-support-for-power-domains-und.patch
deleted file mode 100644 (file)
index 229dbe5..0000000
+++ /dev/null
@@ -1,825 +0,0 @@
-From fd8ca458728baabe9cae37836088a33c8642d420 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 12 Dec 2018 15:51:48 -0800
-Subject: [PATCH] soc: bcm: bcm2835-pm: Add support for power domains
- under a new binding.
-
-This provides a free software alternative to raspberrypi-power.c's
-firmware calls to manage power domains.  It also exposes a reset line,
-where previously the vc4 driver had to try to force power off the
-domain in order to trigger a reset.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Rob Herring <robh@kernel.org>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-(cherry picked from commit 670c672608a1ffcbc7ac0f872734843593bb8b15)
----
- drivers/mfd/bcm2835-pm.c             |  36 +-
- drivers/soc/bcm/Kconfig              |  11 +
- drivers/soc/bcm/Makefile             |   1 +
- drivers/soc/bcm/bcm2835-power.c      | 661 +++++++++++++++++++++++++++
- include/dt-bindings/soc/bcm2835-pm.h |  28 ++
- include/linux/mfd/bcm2835-pm.h       |   1 +
- 6 files changed, 734 insertions(+), 4 deletions(-)
- create mode 100644 drivers/soc/bcm/bcm2835-power.c
- create mode 100644 include/dt-bindings/soc/bcm2835-pm.h
-
---- a/drivers/mfd/bcm2835-pm.c
-+++ b/drivers/mfd/bcm2835-pm.c
-@@ -3,7 +3,7 @@
-  * PM MFD driver for Broadcom BCM2835
-  *
-  * This driver binds to the PM block and creates the MFD device for
-- * the WDT driver.
-+ * the WDT and power drivers.
-  */
- #include <linux/delay.h>
-@@ -21,11 +21,16 @@ static const struct mfd_cell bcm2835_pm_
-       { .name = "bcm2835-wdt" },
- };
-+static const struct mfd_cell bcm2835_power_devs[] = {
-+      { .name = "bcm2835-power" },
-+};
-+
- static int bcm2835_pm_probe(struct platform_device *pdev)
- {
-       struct resource *res;
-       struct device *dev = &pdev->dev;
-       struct bcm2835_pm *pm;
-+      int ret;
-       pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
-       if (!pm)
-@@ -39,13 +44,36 @@ static int bcm2835_pm_probe(struct platf
-       if (IS_ERR(pm->base))
-               return PTR_ERR(pm->base);
--      return devm_mfd_add_devices(dev, -1,
--                                  bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
--                                  NULL, 0, NULL);
-+      ret = devm_mfd_add_devices(dev, -1,
-+                                 bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
-+                                 NULL, 0, NULL);
-+      if (ret)
-+              return ret;
-+
-+      /* We'll use the presence of the AXI ASB regs in the
-+       * bcm2835-pm binding as the key for whether we can reference
-+       * the full PM register range and support power domains.
-+       */
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+      if (res) {
-+              pm->asb = devm_ioremap_resource(dev, res);
-+              if (IS_ERR(pm->asb))
-+                      return PTR_ERR(pm->asb);
-+
-+              ret = devm_mfd_add_devices(dev, -1,
-+                                         bcm2835_power_devs,
-+                                         ARRAY_SIZE(bcm2835_power_devs),
-+                                         NULL, 0, NULL);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      return 0;
- }
- static const struct of_device_id bcm2835_pm_of_match[] = {
-       { .compatible = "brcm,bcm2835-pm-wdt", },
-+      { .compatible = "brcm,bcm2835-pm", },
-       {},
- };
- MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
---- a/drivers/soc/bcm/Kconfig
-+++ b/drivers/soc/bcm/Kconfig
-@@ -1,5 +1,16 @@
- menu "Broadcom SoC drivers"
-+config BCM2835_POWER
-+      bool "BCM2835 power domain driver"
-+      depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
-+      select PM_GENERIC_DOMAINS if PM
-+      select RESET_CONTROLLER
-+      help
-+        This enables support for the BCM2835 power domains and reset
-+        controller.  Any usage of power domains by the Raspberry Pi
-+        firmware means that Linux usage of the same power domain
-+        must be accessed using the RASPBERRYPI_POWER driver
-+
- config RASPBERRYPI_POWER
-       bool "Raspberry Pi power domain driver"
-       depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
---- a/drivers/soc/bcm/Makefile
-+++ b/drivers/soc/bcm/Makefile
-@@ -1,2 +1,3 @@
-+obj-$(CONFIG_BCM2835_POWER)   += bcm2835-power.o
- obj-$(CONFIG_RASPBERRYPI_POWER)       += raspberrypi-power.o
- obj-$(CONFIG_SOC_BRCMSTB)     += brcmstb/
---- /dev/null
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -0,0 +1,661 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * Power domain driver for Broadcom BCM2835
-+ *
-+ * Copyright (C) 2018 Broadcom
-+ */
-+
-+#include <dt-bindings/soc/bcm2835-pm.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/mfd/bcm2835-pm.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_domain.h>
-+#include <linux/reset-controller.h>
-+#include <linux/types.h>
-+
-+#define PM_GNRIC                        0x00
-+#define PM_AUDIO                        0x04
-+#define PM_STATUS                       0x18
-+#define PM_RSTC                               0x1c
-+#define PM_RSTS                               0x20
-+#define PM_WDOG                               0x24
-+#define PM_PADS0                      0x28
-+#define PM_PADS2                      0x2c
-+#define PM_PADS3                      0x30
-+#define PM_PADS4                      0x34
-+#define PM_PADS5                      0x38
-+#define PM_PADS6                      0x3c
-+#define PM_CAM0                               0x44
-+#define PM_CAM0_LDOHPEN                       BIT(2)
-+#define PM_CAM0_LDOLPEN                       BIT(1)
-+#define PM_CAM0_CTRLEN                        BIT(0)
-+
-+#define PM_CAM1                               0x48
-+#define PM_CAM1_LDOHPEN                       BIT(2)
-+#define PM_CAM1_LDOLPEN                       BIT(1)
-+#define PM_CAM1_CTRLEN                        BIT(0)
-+
-+#define PM_CCP2TX                     0x4c
-+#define PM_CCP2TX_LDOEN                       BIT(1)
-+#define PM_CCP2TX_CTRLEN              BIT(0)
-+
-+#define PM_DSI0                               0x50
-+#define PM_DSI0_LDOHPEN                       BIT(2)
-+#define PM_DSI0_LDOLPEN                       BIT(1)
-+#define PM_DSI0_CTRLEN                        BIT(0)
-+
-+#define PM_DSI1                               0x54
-+#define PM_DSI1_LDOHPEN                       BIT(2)
-+#define PM_DSI1_LDOLPEN                       BIT(1)
-+#define PM_DSI1_CTRLEN                        BIT(0)
-+
-+#define PM_HDMI                               0x58
-+#define PM_HDMI_RSTDR                 BIT(19)
-+#define PM_HDMI_LDOPD                 BIT(1)
-+#define PM_HDMI_CTRLEN                        BIT(0)
-+
-+#define PM_USB                                0x5c
-+/* The power gates must be enabled with this bit before enabling the LDO in the
-+ * USB block.
-+ */
-+#define PM_USB_CTRLEN                 BIT(0)
-+
-+#define PM_PXLDO                      0x60
-+#define PM_PXBG                               0x64
-+#define PM_DFT                                0x68
-+#define PM_SMPS                               0x6c
-+#define PM_XOSC                               0x70
-+#define PM_SPAREW                     0x74
-+#define PM_SPARER                     0x78
-+#define PM_AVS_RSTDR                  0x7c
-+#define PM_AVS_STAT                   0x80
-+#define PM_AVS_EVENT                  0x84
-+#define PM_AVS_INTEN                  0x88
-+#define PM_DUMMY                      0xfc
-+
-+#define PM_IMAGE                      0x108
-+#define PM_GRAFX                      0x10c
-+#define PM_PROC                               0x110
-+#define PM_ENAB                               BIT(12)
-+#define PM_ISPRSTN                    BIT(8)
-+#define PM_H264RSTN                   BIT(7)
-+#define PM_PERIRSTN                   BIT(6)
-+#define PM_V3DRSTN                    BIT(6)
-+#define PM_ISFUNC                     BIT(5)
-+#define PM_MRDONE                     BIT(4)
-+#define PM_MEMREP                     BIT(3)
-+#define PM_ISPOW                      BIT(2)
-+#define PM_POWOK                      BIT(1)
-+#define PM_POWUP                      BIT(0)
-+#define PM_INRUSH_SHIFT                       13
-+#define PM_INRUSH_3_5_MA              0
-+#define PM_INRUSH_5_MA                        1
-+#define PM_INRUSH_10_MA                       2
-+#define PM_INRUSH_20_MA                       3
-+#define PM_INRUSH_MASK                        (3 << PM_INRUSH_SHIFT)
-+
-+#define PM_PASSWORD                   0x5a000000
-+
-+#define PM_WDOG_TIME_SET              0x000fffff
-+#define PM_RSTC_WRCFG_CLR             0xffffffcf
-+#define PM_RSTS_HADWRH_SET            0x00000040
-+#define PM_RSTC_WRCFG_SET             0x00000030
-+#define PM_RSTC_WRCFG_FULL_RESET      0x00000020
-+#define PM_RSTC_RESET                 0x00000102
-+
-+#define PM_READ(reg) readl(power->base + (reg))
-+#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
-+
-+#define ASB_BRDG_VERSION                0x00
-+#define ASB_CPR_CTRL                    0x04
-+
-+#define ASB_V3D_S_CTRL                        0x08
-+#define ASB_V3D_M_CTRL                        0x0c
-+#define ASB_ISP_S_CTRL                        0x10
-+#define ASB_ISP_M_CTRL                        0x14
-+#define ASB_H264_S_CTRL                       0x18
-+#define ASB_H264_M_CTRL                       0x1c
-+
-+#define ASB_REQ_STOP                    BIT(0)
-+#define ASB_ACK                         BIT(1)
-+#define ASB_EMPTY                       BIT(2)
-+#define ASB_FULL                        BIT(3)
-+
-+#define ASB_AXI_BRDG_ID                       0x20
-+
-+#define ASB_READ(reg) readl(power->asb + (reg))
-+#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
-+
-+struct bcm2835_power_domain {
-+      struct generic_pm_domain base;
-+      struct bcm2835_power *power;
-+      u32 domain;
-+      struct clk *clk;
-+};
-+
-+struct bcm2835_power {
-+      struct device           *dev;
-+      /* PM registers. */
-+      void __iomem            *base;
-+      /* AXI Async bridge registers. */
-+      void __iomem            *asb;
-+
-+      struct genpd_onecell_data pd_xlate;
-+      struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
-+      struct reset_controller_dev reset;
-+};
-+
-+static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
-+{
-+      u64 start = ktime_get_ns();
-+
-+      /* Enable the module's async AXI bridges. */
-+      ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
-+      while (ASB_READ(reg) & ASB_ACK) {
-+              cpu_relax();
-+              if (ktime_get_ns() - start >= 1000)
-+                      return -ETIMEDOUT;
-+      }
-+
-+      return 0;
-+}
-+
-+static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
-+{
-+      u64 start = ktime_get_ns();
-+
-+      /* Enable the module's async AXI bridges. */
-+      ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
-+      while (!(ASB_READ(reg) & ASB_ACK)) {
-+              cpu_relax();
-+              if (ktime_get_ns() - start >= 1000)
-+                      return -ETIMEDOUT;
-+      }
-+
-+      return 0;
-+}
-+
-+static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
-+{
-+      struct bcm2835_power *power = pd->power;
-+
-+      /* Enable functional isolation */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
-+
-+      /* Enable electrical isolation */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-+
-+      /* Open the power switches. */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
-+
-+      return 0;
-+}
-+
-+static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
-+{
-+      struct bcm2835_power *power = pd->power;
-+      struct device *dev = power->dev;
-+      u64 start;
-+      int ret;
-+      int inrush;
-+      bool powok;
-+
-+      /* If it was already powered on by the fw, leave it that way. */
-+      if (PM_READ(pm_reg) & PM_POWUP)
-+              return 0;
-+
-+      /* Enable power.  Allowing too much current at once may result
-+       * in POWOK never getting set, so start low and ramp it up as
-+       * necessary to succeed.
-+       */
-+      powok = false;
-+      for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
-+              PM_WRITE(pm_reg,
-+                       (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
-+                       (inrush << PM_INRUSH_SHIFT) |
-+                       PM_POWUP);
-+
-+              start = ktime_get_ns();
-+              while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
-+                      cpu_relax();
-+                      if (ktime_get_ns() - start >= 3000)
-+                              break;
-+              }
-+      }
-+      if (!powok) {
-+              dev_err(dev, "Timeout waiting for %s power OK\n",
-+                      pd->base.name);
-+              ret = -ETIMEDOUT;
-+              goto err_disable_powup;
-+      }
-+
-+      /* Disable electrical isolation */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
-+
-+      /* Repair memory */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
-+      start = ktime_get_ns();
-+      while (!(PM_READ(pm_reg) & PM_MRDONE)) {
-+              cpu_relax();
-+              if (ktime_get_ns() - start >= 1000) {
-+                      dev_err(dev, "Timeout waiting for %s memory repair\n",
-+                              pd->base.name);
-+                      ret = -ETIMEDOUT;
-+                      goto err_disable_ispow;
-+              }
-+      }
-+
-+      /* Disable functional isolation */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
-+
-+      return 0;
-+
-+err_disable_ispow:
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-+err_disable_powup:
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
-+      return ret;
-+}
-+
-+static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
-+                              u32 pm_reg,
-+                              u32 asb_m_reg,
-+                              u32 asb_s_reg,
-+                              u32 reset_flags)
-+{
-+      struct bcm2835_power *power = pd->power;
-+      int ret;
-+
-+      ret = clk_prepare_enable(pd->clk);
-+      if (ret) {
-+              dev_err(power->dev, "Failed to enable clock for %s\n",
-+                      pd->base.name);
-+              return ret;
-+      }
-+
-+      /* Wait 32 clocks for reset to propagate, 1 us will be enough */
-+      udelay(1);
-+
-+      clk_disable_unprepare(pd->clk);
-+
-+      /* Deassert the resets. */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
-+
-+      ret = clk_prepare_enable(pd->clk);
-+      if (ret) {
-+              dev_err(power->dev, "Failed to enable clock for %s\n",
-+                      pd->base.name);
-+              goto err_enable_resets;
-+      }
-+
-+      ret = bcm2835_asb_enable(power, asb_m_reg);
-+      if (ret) {
-+              dev_err(power->dev, "Failed to enable ASB master for %s\n",
-+                      pd->base.name);
-+              goto err_disable_clk;
-+      }
-+      ret = bcm2835_asb_enable(power, asb_s_reg);
-+      if (ret) {
-+              dev_err(power->dev, "Failed to enable ASB slave for %s\n",
-+                      pd->base.name);
-+              goto err_disable_asb_master;
-+      }
-+
-+      return 0;
-+
-+err_disable_asb_master:
-+      bcm2835_asb_disable(power, asb_m_reg);
-+err_disable_clk:
-+      clk_disable_unprepare(pd->clk);
-+err_enable_resets:
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
-+      return ret;
-+}
-+
-+static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
-+                               u32 pm_reg,
-+                               u32 asb_m_reg,
-+                               u32 asb_s_reg,
-+                               u32 reset_flags)
-+{
-+      struct bcm2835_power *power = pd->power;
-+      int ret;
-+
-+      ret = bcm2835_asb_disable(power, asb_s_reg);
-+      if (ret) {
-+              dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
-+                       pd->base.name);
-+              return ret;
-+      }
-+      ret = bcm2835_asb_disable(power, asb_m_reg);
-+      if (ret) {
-+              dev_warn(power->dev, "Failed to disable ASB master for %s\n",
-+                       pd->base.name);
-+              bcm2835_asb_enable(power, asb_s_reg);
-+              return ret;
-+      }
-+
-+      clk_disable_unprepare(pd->clk);
-+
-+      /* Assert the resets. */
-+      PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
-+
-+      return 0;
-+}
-+
-+static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
-+{
-+      struct bcm2835_power_domain *pd =
-+              container_of(domain, struct bcm2835_power_domain, base);
-+      struct bcm2835_power *power = pd->power;
-+
-+      switch (pd->domain) {
-+      case BCM2835_POWER_DOMAIN_GRAFX:
-+              return bcm2835_power_power_on(pd, PM_GRAFX);
-+
-+      case BCM2835_POWER_DOMAIN_GRAFX_V3D:
-+              return bcm2835_asb_power_on(pd, PM_GRAFX,
-+                                          ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
-+                                          PM_V3DRSTN);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE:
-+              return bcm2835_power_power_on(pd, PM_IMAGE);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE_PERI:
-+              return bcm2835_asb_power_on(pd, PM_IMAGE,
-+                                          0, 0,
-+                                          PM_PERIRSTN);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE_ISP:
-+              return bcm2835_asb_power_on(pd, PM_IMAGE,
-+                                          ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
-+                                          PM_ISPRSTN);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE_H264:
-+              return bcm2835_asb_power_on(pd, PM_IMAGE,
-+                                          ASB_H264_M_CTRL, ASB_H264_S_CTRL,
-+                                          PM_H264RSTN);
-+
-+      case BCM2835_POWER_DOMAIN_USB:
-+              PM_WRITE(PM_USB, PM_USB_CTRLEN);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_DSI0:
-+              PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
-+              PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_DSI1:
-+              PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
-+              PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_CCP2TX:
-+              PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
-+              PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_HDMI:
-+              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
-+              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
-+              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
-+              usleep_range(100, 200);
-+              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
-+              return 0;
-+
-+      default:
-+              dev_err(power->dev, "Invalid domain %d\n", pd->domain);
-+              return -EINVAL;
-+      }
-+}
-+
-+static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
-+{
-+      struct bcm2835_power_domain *pd =
-+              container_of(domain, struct bcm2835_power_domain, base);
-+      struct bcm2835_power *power = pd->power;
-+
-+      switch (pd->domain) {
-+      case BCM2835_POWER_DOMAIN_GRAFX:
-+              return bcm2835_power_power_off(pd, PM_GRAFX);
-+
-+      case BCM2835_POWER_DOMAIN_GRAFX_V3D:
-+              return bcm2835_asb_power_off(pd, PM_GRAFX,
-+                                           ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
-+                                           PM_V3DRSTN);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE:
-+              return bcm2835_power_power_off(pd, PM_IMAGE);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE_PERI:
-+              return bcm2835_asb_power_off(pd, PM_IMAGE,
-+                                           0, 0,
-+                                           PM_PERIRSTN);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE_ISP:
-+              return bcm2835_asb_power_off(pd, PM_IMAGE,
-+                                           ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
-+                                           PM_ISPRSTN);
-+
-+      case BCM2835_POWER_DOMAIN_IMAGE_H264:
-+              return bcm2835_asb_power_off(pd, PM_IMAGE,
-+                                           ASB_H264_M_CTRL, ASB_H264_S_CTRL,
-+                                           PM_H264RSTN);
-+
-+      case BCM2835_POWER_DOMAIN_USB:
-+              PM_WRITE(PM_USB, 0);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_DSI0:
-+              PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
-+              PM_WRITE(PM_DSI0, 0);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_DSI1:
-+              PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
-+              PM_WRITE(PM_DSI1, 0);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_CCP2TX:
-+              PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
-+              PM_WRITE(PM_CCP2TX, 0);
-+              return 0;
-+
-+      case BCM2835_POWER_DOMAIN_HDMI:
-+              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
-+              PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
-+              return 0;
-+
-+      default:
-+              dev_err(power->dev, "Invalid domain %d\n", pd->domain);
-+              return -EINVAL;
-+      }
-+}
-+
-+static void
-+bcm2835_init_power_domain(struct bcm2835_power *power,
-+                        int pd_xlate_index, const char *name)
-+{
-+      struct device *dev = power->dev;
-+      struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
-+
-+      dom->clk = devm_clk_get(dev->parent, name);
-+
-+      dom->base.name = name;
-+      dom->base.power_on = bcm2835_power_pd_power_on;
-+      dom->base.power_off = bcm2835_power_pd_power_off;
-+
-+      dom->domain = pd_xlate_index;
-+      dom->power = power;
-+
-+      /* XXX: on/off at boot? */
-+      pm_genpd_init(&dom->base, NULL, true);
-+
-+      power->pd_xlate.domains[pd_xlate_index] = &dom->base;
-+}
-+
-+/** bcm2835_reset_reset - Resets a block that has a reset line in the
-+ * PM block.
-+ *
-+ * The consumer of the reset controller must have the power domain up
-+ * -- there's no reset ability with the power domain down.  To reset
-+ * the sub-block, we just disable its access to memory through the
-+ * ASB, reset, and re-enable.
-+ */
-+static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
-+                             unsigned long id)
-+{
-+      struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
-+                                                 reset);
-+      struct bcm2835_power_domain *pd;
-+      int ret;
-+
-+      switch (id) {
-+      case BCM2835_RESET_V3D:
-+              pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
-+              break;
-+      case BCM2835_RESET_H264:
-+              pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
-+              break;
-+      case BCM2835_RESET_ISP:
-+              pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
-+              break;
-+      default:
-+              dev_err(power->dev, "Bad reset id %ld\n", id);
-+              return -EINVAL;
-+      }
-+
-+      ret = bcm2835_power_pd_power_off(&pd->base);
-+      if (ret)
-+              return ret;
-+
-+      return bcm2835_power_pd_power_on(&pd->base);
-+}
-+
-+static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
-+                              unsigned long id)
-+{
-+      struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
-+                                                 reset);
-+
-+      switch (id) {
-+      case BCM2835_RESET_V3D:
-+              return !PM_READ(PM_GRAFX & PM_V3DRSTN);
-+      case BCM2835_RESET_H264:
-+              return !PM_READ(PM_IMAGE & PM_H264RSTN);
-+      case BCM2835_RESET_ISP:
-+              return !PM_READ(PM_IMAGE & PM_ISPRSTN);
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+const struct reset_control_ops bcm2835_reset_ops = {
-+      .reset = bcm2835_reset_reset,
-+      .status = bcm2835_reset_status,
-+};
-+
-+static const char *const power_domain_names[] = {
-+      [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
-+      [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
-+
-+      [BCM2835_POWER_DOMAIN_IMAGE] = "image",
-+      [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
-+      [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
-+      [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
-+
-+      [BCM2835_POWER_DOMAIN_USB] = "usb",
-+      [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
-+      [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
-+      [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
-+      [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
-+      [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
-+      [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
-+};
-+
-+static int bcm2835_power_probe(struct platform_device *pdev)
-+{
-+      struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
-+      struct device *dev = &pdev->dev;
-+      struct bcm2835_power *power;
-+      static const struct {
-+              int parent, child;
-+      } domain_deps[] = {
-+              { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
-+              { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
-+              { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
-+              { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
-+              { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
-+              { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
-+              { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
-+      };
-+      int ret, i;
-+      u32 id;
-+
-+      power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
-+      if (!power)
-+              return -ENOMEM;
-+      platform_set_drvdata(pdev, power);
-+
-+      power->dev = dev;
-+      power->base = pm->base;
-+      power->asb = pm->asb;
-+
-+      id = ASB_READ(ASB_AXI_BRDG_ID);
-+      if (id != 0x62726467 /* "BRDG" */) {
-+              dev_err(dev, "ASB register ID returned 0x%08x\n", id);
-+              return -ENODEV;
-+      }
-+
-+      power->pd_xlate.domains = devm_kcalloc(dev,
-+                                             ARRAY_SIZE(power_domain_names),
-+                                             sizeof(*power->pd_xlate.domains),
-+                                             GFP_KERNEL);
-+      if (!power->pd_xlate.domains)
-+              return -ENOMEM;
-+
-+      power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
-+
-+      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
-+              bcm2835_init_power_domain(power, i, power_domain_names[i]);
-+
-+      for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
-+              pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
-+                                     &power->domains[domain_deps[i].child].base);
-+      }
-+
-+      power->reset.owner = THIS_MODULE;
-+      power->reset.nr_resets = BCM2835_RESET_COUNT;
-+      power->reset.ops = &bcm2835_reset_ops;
-+      power->reset.of_node = dev->parent->of_node;
-+
-+      ret = devm_reset_controller_register(dev, &power->reset);
-+      if (ret)
-+              return ret;
-+
-+      of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
-+
-+      dev_info(dev, "Broadcom BCM2835 power domains driver");
-+      return 0;
-+}
-+
-+static int bcm2835_power_remove(struct platform_device *pdev)
-+{
-+      return 0;
-+}
-+
-+static struct platform_driver bcm2835_power_driver = {
-+      .probe          = bcm2835_power_probe,
-+      .remove         = bcm2835_power_remove,
-+      .driver = {
-+              .name = "bcm2835-power",
-+      },
-+};
-+module_platform_driver(bcm2835_power_driver);
-+
-+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/include/dt-bindings/soc/bcm2835-pm.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
-+
-+#ifndef _DT_BINDINGS_ARM_BCM2835_PM_H
-+#define _DT_BINDINGS_ARM_BCM2835_PM_H
-+
-+#define BCM2835_POWER_DOMAIN_GRAFX            0
-+#define BCM2835_POWER_DOMAIN_GRAFX_V3D                1
-+#define BCM2835_POWER_DOMAIN_IMAGE            2
-+#define BCM2835_POWER_DOMAIN_IMAGE_PERI               3
-+#define BCM2835_POWER_DOMAIN_IMAGE_ISP                4
-+#define BCM2835_POWER_DOMAIN_IMAGE_H264               5
-+#define BCM2835_POWER_DOMAIN_USB              6
-+#define BCM2835_POWER_DOMAIN_DSI0             7
-+#define BCM2835_POWER_DOMAIN_DSI1             8
-+#define BCM2835_POWER_DOMAIN_CAM0             9
-+#define BCM2835_POWER_DOMAIN_CAM1             10
-+#define BCM2835_POWER_DOMAIN_CCP2TX           11
-+#define BCM2835_POWER_DOMAIN_HDMI             12
-+
-+#define BCM2835_POWER_DOMAIN_COUNT            13
-+
-+#define BCM2835_RESET_V3D                     0
-+#define BCM2835_RESET_ISP                     1
-+#define BCM2835_RESET_H264                    2
-+
-+#define BCM2835_RESET_COUNT                   3
-+
-+#endif /* _DT_BINDINGS_ARM_BCM2835_PM_H */
---- a/include/linux/mfd/bcm2835-pm.h
-+++ b/include/linux/mfd/bcm2835-pm.h
-@@ -8,6 +8,7 @@
- struct bcm2835_pm {
-       struct device *dev;
-       void __iomem *base;
-+      void __iomem *asb;
- };
- #endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0483-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch b/target/linux/brcm2708/patches-4.19/950-0483-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch
new file mode 100644 (file)
index 0000000..0f3ea9a
--- /dev/null
@@ -0,0 +1,103 @@
+From 8d9f3526529d857376c661c21820a0049c2e62de Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Sat, 12 Jan 2019 08:07:43 -0800
+Subject: [PATCH] soc: bcm: bcm2835-pm: Fix error paths of
+ initialization.
+
+The clock driver may probe after ours and so we need to pass the
+-EPROBE_DEFER out.  Fix the other error path while we're here.
+
+v2: Use dom->name instead of dom->gov as the flag for initialized
+    domains, since we aren't setting up a governor.  Make sure to
+    clear ->clk when no clk is present in the DT.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
+---
+ drivers/soc/bcm/bcm2835-power.c | 35 ++++++++++++++++++++++++++++-----
+ 1 file changed, 30 insertions(+), 5 deletions(-)
+
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -485,7 +485,7 @@ static int bcm2835_power_pd_power_off(st
+       }
+ }
+-static void
++static int
+ bcm2835_init_power_domain(struct bcm2835_power *power,
+                         int pd_xlate_index, const char *name)
+ {
+@@ -493,6 +493,17 @@ bcm2835_init_power_domain(struct bcm2835
+       struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
+       dom->clk = devm_clk_get(dev->parent, name);
++      if (IS_ERR(dom->clk)) {
++              int ret = PTR_ERR(dom->clk);
++
++              if (ret == -EPROBE_DEFER)
++                      return ret;
++
++              /* Some domains don't have a clk, so make sure that we
++               * don't deref an error pointer later.
++               */
++              dom->clk = NULL;
++      }
+       dom->base.name = name;
+       dom->base.power_on = bcm2835_power_pd_power_on;
+@@ -505,6 +516,8 @@ bcm2835_init_power_domain(struct bcm2835
+       pm_genpd_init(&dom->base, NULL, true);
+       power->pd_xlate.domains[pd_xlate_index] = &dom->base;
++
++      return 0;
+ }
+ /** bcm2835_reset_reset - Resets a block that has a reset line in the
+@@ -602,7 +615,7 @@ static int bcm2835_power_probe(struct pl
+               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
+               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
+       };
+-      int ret, i;
++      int ret = 0, i;
+       u32 id;
+       power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
+@@ -629,8 +642,11 @@ static int bcm2835_power_probe(struct pl
+       power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
+-      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
+-              bcm2835_init_power_domain(power, i, power_domain_names[i]);
++      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
++              ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
++              if (ret)
++                      goto fail;
++      }
+       for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
+               pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
+@@ -644,12 +660,21 @@ static int bcm2835_power_probe(struct pl
+       ret = devm_reset_controller_register(dev, &power->reset);
+       if (ret)
+-              return ret;
++              goto fail;
+       of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
+       dev_info(dev, "Broadcom BCM2835 power domains driver");
+       return 0;
++
++fail:
++      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
++              struct generic_pm_domain *dom = &power->domains[i].base;
++
++              if (dom->name)
++                      pm_genpd_remove(dom);
++      }
++      return ret;
+ }
+ static int bcm2835_power_remove(struct platform_device *pdev)
diff --git a/target/linux/brcm2708/patches-4.19/950-0484-soc-bcm-bcm2835-pm-Add-support-for-2711.patch b/target/linux/brcm2708/patches-4.19/950-0484-soc-bcm-bcm2835-pm-Add-support-for-2711.patch
new file mode 100644 (file)
index 0000000..4c87289
--- /dev/null
@@ -0,0 +1,102 @@
+From f3470769d4e64084fc7f3060d634aff8fdf8f75d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 11 Jan 2019 17:31:07 -0800
+Subject: [PATCH] soc: bcm: bcm2835-pm: Add support for 2711.
+
+Without the actual power management part any more, there's a lot less
+to set up for V3D.  We just need to clear the RSTN field for the power
+domain, and expose the reset controller for toggling it again.
+
+This is definitely incomplete -- the old ISP and H264 is in the old
+bridge, but since we have no consumers of it I've just done the
+minimum to get V3D working.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/mfd/bcm2835-pm.c        | 11 +++++++++++
+ drivers/soc/bcm/bcm2835-power.c | 22 ++++++++++++++++++++++
+ include/linux/mfd/bcm2835-pm.h  |  1 +
+ 3 files changed, 34 insertions(+)
+
+--- a/drivers/mfd/bcm2835-pm.c
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -50,6 +50,17 @@ static int bcm2835_pm_probe(struct platf
+       if (ret)
+               return ret;
++      /* Map the ARGON ASB regs if present. */
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
++      if (res) {
++              pm->arg_asb = devm_ioremap_resource(dev, res);
++              if (IS_ERR(pm->arg_asb)) {
++                      dev_err(dev, "Failed to map ARGON ASB: %ld\n",
++                              PTR_ERR(pm->arg_asb));
++                      return PTR_ERR(pm->arg_asb);
++              }
++      }
++
+       /* We'll use the presence of the AXI ASB regs in the
+        * bcm2835-pm binding as the key for whether we can reference
+        * the full PM register range and support power domains.
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -143,6 +143,8 @@ struct bcm2835_power {
+       /* AXI Async bridge registers. */
+       void __iomem            *asb;
++      bool is_2711;
++
+       struct genpd_onecell_data pd_xlate;
+       struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
+       struct reset_controller_dev reset;
+@@ -192,6 +194,10 @@ static int bcm2835_power_power_off(struc
+ {
+       struct bcm2835_power *power = pd->power;
++      /* 2711 has no power domains above the reset controller. */
++      if (power->is_2711)
++              return 0;
++
+       /* Enable functional isolation */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
+@@ -213,6 +219,10 @@ static int bcm2835_power_power_on(struct
+       int inrush;
+       bool powok;
++      /* 2711 has no power domains above the reset controller. */
++      if (power->is_2711)
++              return 0;
++
+       /* If it was already powered on by the fw, leave it that way. */
+       if (PM_READ(pm_reg) & PM_POWUP)
+               return 0;
+@@ -627,6 +637,18 @@ static int bcm2835_power_probe(struct pl
+       power->base = pm->base;
+       power->asb = pm->asb;
++      /* 2711 hack: the new ARGON ASB took over V3D, which is our
++       * only consumer of this driver so far.  The old ASB seems to
++       * still be present with ISP and H264 bits but no V3D, but I
++       * don't know if that's real or not.  The V3D is in the same
++       * place in the new ASB as the old one, so just poke the new
++       * one for now.
++       */
++      if (pm->arg_asb) {
++              power->asb = pm->arg_asb;
++              power->is_2711 = true;
++      }
++
+       id = ASB_READ(ASB_AXI_BRDG_ID);
+       if (id != 0x62726467 /* "BRDG" */) {
+               dev_err(dev, "ASB register ID returned 0x%08x\n", id);
+--- a/include/linux/mfd/bcm2835-pm.h
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -9,6 +9,7 @@ struct bcm2835_pm {
+       struct device *dev;
+       void __iomem *base;
+       void __iomem *asb;
++      void __iomem *arg_asb;
+ };
+ #endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0484-soc-bcm-bcm2835-pm-Fix-PM_IMAGE_PERI-power-domain-su.patch b/target/linux/brcm2708/patches-4.19/950-0484-soc-bcm-bcm2835-pm-Fix-PM_IMAGE_PERI-power-domain-su.patch
deleted file mode 100644 (file)
index 05ae67a..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From ea44a81b7daf511788aecaee7575feff359c5d19 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 11 Jan 2019 17:29:10 -0800
-Subject: [PATCH] soc: bcm: bcm2835-pm: Fix PM_IMAGE_PERI power domain
- support.
-
-We don't have ASB master/slave regs for this domain, so just skip that
-step.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
----
- drivers/soc/bcm/bcm2835-power.c | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
-
---- a/drivers/soc/bcm/bcm2835-power.c
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -150,7 +150,12 @@ struct bcm2835_power {
- static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
- {
--      u64 start = ktime_get_ns();
-+      u64 start;
-+
-+      if (!reg)
-+              return 0;
-+
-+      start = ktime_get_ns();
-       /* Enable the module's async AXI bridges. */
-       ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
-@@ -165,7 +170,12 @@ static int bcm2835_asb_enable(struct bcm
- static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
- {
--      u64 start = ktime_get_ns();
-+      u64 start;
-+
-+      if (!reg)
-+              return 0;
-+
-+      start = ktime_get_ns();
-       /* Enable the module's async AXI bridges. */
-       ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
diff --git a/target/linux/brcm2708/patches-4.19/950-0485-drm-expand-drm_syncobj_find_fence-to-support-timelin.patch b/target/linux/brcm2708/patches-4.19/950-0485-drm-expand-drm_syncobj_find_fence-to-support-timelin.patch
new file mode 100644 (file)
index 0000000..2b4d34e
--- /dev/null
@@ -0,0 +1,104 @@
+From 7e891cb1f9f57c87706b1292f186d65e1640e0e7 Mon Sep 17 00:00:00 2001
+From: Chunming Zhou <david1.zhou@amd.com>
+Date: Thu, 30 Aug 2018 14:48:29 +0800
+Subject: [PATCH] drm: expand drm_syncobj_find_fence to support
+ timeline point v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+we can fetch timeline point fence after expanded.
+v2: The parameter fence is the result of the function and should come last.
+
+Signed-off-by: Chunming Zhou <david1.zhou@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Link: https://patchwork.freedesktop.org/patch/246541/
+(cherry picked from commit 0a6730ea27b68c7ac4171c29a816c29d26a9637a)
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
+ drivers/gpu/drm/drm_syncobj.c          | 5 +++--
+ drivers/gpu/drm/v3d/v3d_gem.c          | 4 ++--
+ drivers/gpu/drm/vc4/vc4_gem.c          | 2 +-
+ include/drm/drm_syncobj.h              | 2 +-
+ 5 files changed, 8 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -1105,7 +1105,7 @@ static int amdgpu_syncobj_lookup_and_add
+ {
+       int r;
+       struct dma_fence *fence;
+-      r = drm_syncobj_find_fence(p->filp, handle, &fence);
++      r = drm_syncobj_find_fence(p->filp, handle, 0, &fence);
+       if (r)
+               return r;
+--- a/drivers/gpu/drm/drm_syncobj.c
++++ b/drivers/gpu/drm/drm_syncobj.c
+@@ -235,6 +235,7 @@ static int drm_syncobj_assign_null_handl
+  * drm_syncobj_find_fence - lookup and reference the fence in a sync object
+  * @file_private: drm file private pointer
+  * @handle: sync object handle to lookup.
++ * @point: timeline point
+  * @fence: out parameter for the fence
+  *
+  * This is just a convenience function that combines drm_syncobj_find() and
+@@ -245,7 +246,7 @@ static int drm_syncobj_assign_null_handl
+  * dma_fence_put().
+  */
+ int drm_syncobj_find_fence(struct drm_file *file_private,
+-                         u32 handle,
++                         u32 handle, u64 point,
+                          struct dma_fence **fence)
+ {
+       struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
+@@ -516,7 +517,7 @@ static int drm_syncobj_export_sync_file(
+       if (fd < 0)
+               return fd;
+-      ret = drm_syncobj_find_fence(file_private, handle, &fence);
++      ret = drm_syncobj_find_fence(file_private, handle, 0, &fence);
+       if (ret)
+               goto err_put_fd;
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -521,12 +521,12 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       kref_init(&exec->refcount);
+       ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
+-                                   &exec->bin.in_fence);
++                                   0, &exec->bin.in_fence);
+       if (ret == -EINVAL)
+               goto fail;
+       ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
+-                                   &exec->render.in_fence);
++                                   0, &exec->render.in_fence);
+       if (ret == -EINVAL)
+               goto fail;
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d
+       if (args->in_sync) {
+               ret = drm_syncobj_find_fence(file_priv, args->in_sync,
+-                                           &in_fence);
++                                           0, &in_fence);
+               if (ret)
+                       goto fail;
+--- a/include/drm/drm_syncobj.h
++++ b/include/drm/drm_syncobj.h
+@@ -139,7 +139,7 @@ void drm_syncobj_remove_callback(struct
+ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
+                              struct dma_fence *fence);
+ int drm_syncobj_find_fence(struct drm_file *file_private,
+-                         u32 handle,
++                         u32 handle, u64 point,
+                          struct dma_fence **fence);
+ void drm_syncobj_free(struct kref *kref);
+ int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
diff --git a/target/linux/brcm2708/patches-4.19/950-0485-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch b/target/linux/brcm2708/patches-4.19/950-0485-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch
deleted file mode 100644 (file)
index 0f3ea9a..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-From 8d9f3526529d857376c661c21820a0049c2e62de Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Sat, 12 Jan 2019 08:07:43 -0800
-Subject: [PATCH] soc: bcm: bcm2835-pm: Fix error paths of
- initialization.
-
-The clock driver may probe after ours and so we need to pass the
--EPROBE_DEFER out.  Fix the other error path while we're here.
-
-v2: Use dom->name instead of dom->gov as the flag for initialized
-    domains, since we aren't setting up a governor.  Make sure to
-    clear ->clk when no clk is present in the DT.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
----
- drivers/soc/bcm/bcm2835-power.c | 35 ++++++++++++++++++++++++++++-----
- 1 file changed, 30 insertions(+), 5 deletions(-)
-
---- a/drivers/soc/bcm/bcm2835-power.c
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -485,7 +485,7 @@ static int bcm2835_power_pd_power_off(st
-       }
- }
--static void
-+static int
- bcm2835_init_power_domain(struct bcm2835_power *power,
-                         int pd_xlate_index, const char *name)
- {
-@@ -493,6 +493,17 @@ bcm2835_init_power_domain(struct bcm2835
-       struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
-       dom->clk = devm_clk_get(dev->parent, name);
-+      if (IS_ERR(dom->clk)) {
-+              int ret = PTR_ERR(dom->clk);
-+
-+              if (ret == -EPROBE_DEFER)
-+                      return ret;
-+
-+              /* Some domains don't have a clk, so make sure that we
-+               * don't deref an error pointer later.
-+               */
-+              dom->clk = NULL;
-+      }
-       dom->base.name = name;
-       dom->base.power_on = bcm2835_power_pd_power_on;
-@@ -505,6 +516,8 @@ bcm2835_init_power_domain(struct bcm2835
-       pm_genpd_init(&dom->base, NULL, true);
-       power->pd_xlate.domains[pd_xlate_index] = &dom->base;
-+
-+      return 0;
- }
- /** bcm2835_reset_reset - Resets a block that has a reset line in the
-@@ -602,7 +615,7 @@ static int bcm2835_power_probe(struct pl
-               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
-               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
-       };
--      int ret, i;
-+      int ret = 0, i;
-       u32 id;
-       power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
-@@ -629,8 +642,11 @@ static int bcm2835_power_probe(struct pl
-       power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
--      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
--              bcm2835_init_power_domain(power, i, power_domain_names[i]);
-+      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
-+              ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
-+              if (ret)
-+                      goto fail;
-+      }
-       for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
-               pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
-@@ -644,12 +660,21 @@ static int bcm2835_power_probe(struct pl
-       ret = devm_reset_controller_register(dev, &power->reset);
-       if (ret)
--              return ret;
-+              goto fail;
-       of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
-       dev_info(dev, "Broadcom BCM2835 power domains driver");
-       return 0;
-+
-+fail:
-+      for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
-+              struct generic_pm_domain *dom = &power->domains[i].base;
-+
-+              if (dom->name)
-+                      pm_genpd_remove(dom);
-+      }
-+      return ret;
- }
- static int bcm2835_power_remove(struct platform_device *pdev)
diff --git a/target/linux/brcm2708/patches-4.19/950-0486-drm-v3d-Fix-a-use-after-free-race-accessing-the-sche.patch b/target/linux/brcm2708/patches-4.19/950-0486-drm-v3d-Fix-a-use-after-free-race-accessing-the-sche.patch
new file mode 100644 (file)
index 0000000..126452f
--- /dev/null
@@ -0,0 +1,73 @@
+From f5f3df2b1746a9ba9420ae11988fc37a7b93691d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 28 Sep 2018 16:21:23 -0700
+Subject: [PATCH] drm/v3d: Fix a use-after-free race accessing the
+ scheduler's fences.
+
+Once we push the job, the scheduler could run it and free it.  So, if
+we want to reference their fences, we need to grab them before then.
+I haven't seen this happen in many days of conformance test runtime,
+but let's still close the race.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
+Link: https://patchwork.freedesktop.org/patch/254119/
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
+(cherry picked from commit 34c2c4f632f232ed2fdb66d4e42cc72d322273fe)
+---
+ drivers/gpu/drm/v3d/v3d_drv.h | 5 +++++
+ drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -198,6 +198,11 @@ struct v3d_exec_info {
+        */
+       struct dma_fence *bin_done_fence;
++      /* Fence for when the scheduler considers the render to be
++       * done, for when the BOs reservations should be complete.
++       */
++      struct dma_fence *render_done_fence;
++
+       struct kref refcount;
+       /* This is the array of BOs that were looked up at the start of exec. */
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -209,7 +209,7 @@ v3d_flush_caches(struct v3d_dev *v3d)
+ static void
+ v3d_attach_object_fences(struct v3d_exec_info *exec)
+ {
+-      struct dma_fence *out_fence = &exec->render.base.s_fence->finished;
++      struct dma_fence *out_fence = exec->render_done_fence;
+       struct v3d_bo *bo;
+       int i;
+@@ -409,6 +409,7 @@ v3d_exec_cleanup(struct kref *ref)
+       dma_fence_put(exec->render.done_fence);
+       dma_fence_put(exec->bin_done_fence);
++      dma_fence_put(exec->render_done_fence);
+       for (i = 0; i < exec->bo_count; i++)
+               drm_gem_object_put_unlocked(&exec->bo[i]->base);
+@@ -572,6 +573,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       if (ret)
+               goto fail_unreserve;
++      exec->render_done_fence =
++              dma_fence_get(&exec->render.base.s_fence->finished);
++
+       kref_get(&exec->refcount); /* put by scheduler job completion */
+       drm_sched_entity_push_job(&exec->render.base,
+                                 &v3d_priv->sched_entity[V3D_RENDER]);
+@@ -585,7 +589,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       sync_out = drm_syncobj_find(file_priv, args->out_sync);
+       if (sync_out) {
+               drm_syncobj_replace_fence(sync_out,
+-                                        &exec->render.base.s_fence->finished);
++                                        exec->render_done_fence);
+               drm_syncobj_put(sync_out);
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0486-soc-bcm-bcm2835-pm-Add-support-for-2711.patch b/target/linux/brcm2708/patches-4.19/950-0486-soc-bcm-bcm2835-pm-Add-support-for-2711.patch
deleted file mode 100644 (file)
index 4c87289..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From f3470769d4e64084fc7f3060d634aff8fdf8f75d Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 11 Jan 2019 17:31:07 -0800
-Subject: [PATCH] soc: bcm: bcm2835-pm: Add support for 2711.
-
-Without the actual power management part any more, there's a lot less
-to set up for V3D.  We just need to clear the RSTN field for the power
-domain, and expose the reset controller for toggling it again.
-
-This is definitely incomplete -- the old ISP and H264 is in the old
-bridge, but since we have no consumers of it I've just done the
-minimum to get V3D working.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/mfd/bcm2835-pm.c        | 11 +++++++++++
- drivers/soc/bcm/bcm2835-power.c | 22 ++++++++++++++++++++++
- include/linux/mfd/bcm2835-pm.h  |  1 +
- 3 files changed, 34 insertions(+)
-
---- a/drivers/mfd/bcm2835-pm.c
-+++ b/drivers/mfd/bcm2835-pm.c
-@@ -50,6 +50,17 @@ static int bcm2835_pm_probe(struct platf
-       if (ret)
-               return ret;
-+      /* Map the ARGON ASB regs if present. */
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-+      if (res) {
-+              pm->arg_asb = devm_ioremap_resource(dev, res);
-+              if (IS_ERR(pm->arg_asb)) {
-+                      dev_err(dev, "Failed to map ARGON ASB: %ld\n",
-+                              PTR_ERR(pm->arg_asb));
-+                      return PTR_ERR(pm->arg_asb);
-+              }
-+      }
-+
-       /* We'll use the presence of the AXI ASB regs in the
-        * bcm2835-pm binding as the key for whether we can reference
-        * the full PM register range and support power domains.
---- a/drivers/soc/bcm/bcm2835-power.c
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -143,6 +143,8 @@ struct bcm2835_power {
-       /* AXI Async bridge registers. */
-       void __iomem            *asb;
-+      bool is_2711;
-+
-       struct genpd_onecell_data pd_xlate;
-       struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
-       struct reset_controller_dev reset;
-@@ -192,6 +194,10 @@ static int bcm2835_power_power_off(struc
- {
-       struct bcm2835_power *power = pd->power;
-+      /* 2711 has no power domains above the reset controller. */
-+      if (power->is_2711)
-+              return 0;
-+
-       /* Enable functional isolation */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
-@@ -213,6 +219,10 @@ static int bcm2835_power_power_on(struct
-       int inrush;
-       bool powok;
-+      /* 2711 has no power domains above the reset controller. */
-+      if (power->is_2711)
-+              return 0;
-+
-       /* If it was already powered on by the fw, leave it that way. */
-       if (PM_READ(pm_reg) & PM_POWUP)
-               return 0;
-@@ -627,6 +637,18 @@ static int bcm2835_power_probe(struct pl
-       power->base = pm->base;
-       power->asb = pm->asb;
-+      /* 2711 hack: the new ARGON ASB took over V3D, which is our
-+       * only consumer of this driver so far.  The old ASB seems to
-+       * still be present with ISP and H264 bits but no V3D, but I
-+       * don't know if that's real or not.  The V3D is in the same
-+       * place in the new ASB as the old one, so just poke the new
-+       * one for now.
-+       */
-+      if (pm->arg_asb) {
-+              power->asb = pm->arg_asb;
-+              power->is_2711 = true;
-+      }
-+
-       id = ASB_READ(ASB_AXI_BRDG_ID);
-       if (id != 0x62726467 /* "BRDG" */) {
-               dev_err(dev, "ASB register ID returned 0x%08x\n", id);
---- a/include/linux/mfd/bcm2835-pm.h
-+++ b/include/linux/mfd/bcm2835-pm.h
-@@ -9,6 +9,7 @@ struct bcm2835_pm {
-       struct device *dev;
-       void __iomem *base;
-       void __iomem *asb;
-+      void __iomem *arg_asb;
- };
- #endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0487-drm-expand-drm_syncobj_find_fence-to-support-timelin.patch b/target/linux/brcm2708/patches-4.19/950-0487-drm-expand-drm_syncobj_find_fence-to-support-timelin.patch
deleted file mode 100644 (file)
index 2b4d34e..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-From 7e891cb1f9f57c87706b1292f186d65e1640e0e7 Mon Sep 17 00:00:00 2001
-From: Chunming Zhou <david1.zhou@amd.com>
-Date: Thu, 30 Aug 2018 14:48:29 +0800
-Subject: [PATCH] drm: expand drm_syncobj_find_fence to support
- timeline point v2
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-we can fetch timeline point fence after expanded.
-v2: The parameter fence is the result of the function and should come last.
-
-Signed-off-by: Chunming Zhou <david1.zhou@amd.com>
-Reviewed-by: Christian König <christian.koenig@amd.com>
-Signed-off-by: Christian König <christian.koenig@amd.com>
-Link: https://patchwork.freedesktop.org/patch/246541/
-(cherry picked from commit 0a6730ea27b68c7ac4171c29a816c29d26a9637a)
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
- drivers/gpu/drm/drm_syncobj.c          | 5 +++--
- drivers/gpu/drm/v3d/v3d_gem.c          | 4 ++--
- drivers/gpu/drm/vc4/vc4_gem.c          | 2 +-
- include/drm/drm_syncobj.h              | 2 +-
- 5 files changed, 8 insertions(+), 7 deletions(-)
-
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
-@@ -1105,7 +1105,7 @@ static int amdgpu_syncobj_lookup_and_add
- {
-       int r;
-       struct dma_fence *fence;
--      r = drm_syncobj_find_fence(p->filp, handle, &fence);
-+      r = drm_syncobj_find_fence(p->filp, handle, 0, &fence);
-       if (r)
-               return r;
---- a/drivers/gpu/drm/drm_syncobj.c
-+++ b/drivers/gpu/drm/drm_syncobj.c
-@@ -235,6 +235,7 @@ static int drm_syncobj_assign_null_handl
-  * drm_syncobj_find_fence - lookup and reference the fence in a sync object
-  * @file_private: drm file private pointer
-  * @handle: sync object handle to lookup.
-+ * @point: timeline point
-  * @fence: out parameter for the fence
-  *
-  * This is just a convenience function that combines drm_syncobj_find() and
-@@ -245,7 +246,7 @@ static int drm_syncobj_assign_null_handl
-  * dma_fence_put().
-  */
- int drm_syncobj_find_fence(struct drm_file *file_private,
--                         u32 handle,
-+                         u32 handle, u64 point,
-                          struct dma_fence **fence)
- {
-       struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
-@@ -516,7 +517,7 @@ static int drm_syncobj_export_sync_file(
-       if (fd < 0)
-               return fd;
--      ret = drm_syncobj_find_fence(file_private, handle, &fence);
-+      ret = drm_syncobj_find_fence(file_private, handle, 0, &fence);
-       if (ret)
-               goto err_put_fd;
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -521,12 +521,12 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       kref_init(&exec->refcount);
-       ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
--                                   &exec->bin.in_fence);
-+                                   0, &exec->bin.in_fence);
-       if (ret == -EINVAL)
-               goto fail;
-       ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
--                                   &exec->render.in_fence);
-+                                   0, &exec->render.in_fence);
-       if (ret == -EINVAL)
-               goto fail;
---- a/drivers/gpu/drm/vc4/vc4_gem.c
-+++ b/drivers/gpu/drm/vc4/vc4_gem.c
-@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d
-       if (args->in_sync) {
-               ret = drm_syncobj_find_fence(file_priv, args->in_sync,
--                                           &in_fence);
-+                                           0, &in_fence);
-               if (ret)
-                       goto fail;
---- a/include/drm/drm_syncobj.h
-+++ b/include/drm/drm_syncobj.h
-@@ -139,7 +139,7 @@ void drm_syncobj_remove_callback(struct
- void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
-                              struct dma_fence *fence);
- int drm_syncobj_find_fence(struct drm_file *file_private,
--                         u32 handle,
-+                         u32 handle, u64 point,
-                          struct dma_fence **fence);
- void drm_syncobj_free(struct kref *kref);
- int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
diff --git a/target/linux/brcm2708/patches-4.19/950-0487-drm-v3d-Add-a-little-debugfs-entry-for-measuring-the.patch b/target/linux/brcm2708/patches-4.19/950-0487-drm-v3d-Add-a-little-debugfs-entry-for-measuring-the.patch
new file mode 100644 (file)
index 0000000..847bb20
--- /dev/null
@@ -0,0 +1,106 @@
+From 18f93916e42ea25fc77cab20d1e038620e33d741 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 28 Sep 2018 16:21:24 -0700
+Subject: [PATCH] drm/v3d: Add a little debugfs entry for measuring the
+ core clock.
+
+This adds just enough performance counter support to measure the
+clock.  We don't have linux kernel drivers for the clock driving the
+HW, and this was useful for determining that the V3D HW is running on
+a slow clock, not that the driver was slow.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180928232126.4332-2-eric@anholt.net
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
+(cherry picked from commit 6915c9a525e575732429c22b28eb11871a29374b)
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c | 35 +++++++++++++++++++++++++++++++
+ drivers/gpu/drm/v3d/v3d_regs.h    | 30 ++++++++++++++++++++++++++
+ 2 files changed, 65 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -179,9 +179,44 @@ static int v3d_debugfs_bo_stats(struct s
+       return 0;
+ }
++static int v3d_measure_clock(struct seq_file *m, void *unused)
++{
++      struct drm_info_node *node = (struct drm_info_node *)m->private;
++      struct drm_device *dev = node->minor->dev;
++      struct v3d_dev *v3d = to_v3d_dev(dev);
++      uint32_t cycles;
++      int core = 0;
++      int measure_ms = 1000;
++
++      if (v3d->ver >= 40) {
++              V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
++                             V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT,
++                                           V3D_PCTR_S0));
++              V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1);
++              V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1);
++      } else {
++              V3D_CORE_WRITE(core, V3D_V3_PCTR_0_PCTRS0,
++                             V3D_PCTR_CYCLE_COUNT);
++              V3D_CORE_WRITE(core, V3D_V3_PCTR_0_CLR, 1);
++              V3D_CORE_WRITE(core, V3D_V3_PCTR_0_EN,
++                             V3D_V3_PCTR_0_EN_ENABLE |
++                             1);
++      }
++      msleep(measure_ms);
++      cycles = V3D_CORE_READ(core, V3D_PCTR_0_PCTR0);
++
++      seq_printf(m, "cycles: %d (%d.%d Mhz)\n",
++                 cycles,
++                 cycles / (measure_ms * 1000),
++                 (cycles / (measure_ms * 100)) % 10);
++
++      return 0;
++}
++
+ static const struct drm_info_list v3d_debugfs_list[] = {
+       {"v3d_ident", v3d_v3d_debugfs_ident, 0},
+       {"v3d_regs", v3d_v3d_debugfs_regs, 0},
++      {"measure_clock", v3d_measure_clock, 0},
+       {"bo_stats", v3d_debugfs_bo_stats, 0},
+ };
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -267,6 +267,36 @@
+ # define V3D_PTB_BXCF_RWORDERDISA                      BIT(1)
+ # define V3D_PTB_BXCF_CLIPDISA                         BIT(0)
++#define V3D_V3_PCTR_0_EN                               0x00674
++#define V3D_V3_PCTR_0_EN_ENABLE                        BIT(31)
++#define V3D_V4_PCTR_0_EN                               0x00650
++/* When a bit is set, resets the counter to 0. */
++#define V3D_V3_PCTR_0_CLR                              0x00670
++#define V3D_V4_PCTR_0_CLR                              0x00654
++#define V3D_PCTR_0_OVERFLOW                            0x00658
++
++#define V3D_V3_PCTR_0_PCTRS0                           0x00684
++#define V3D_V3_PCTR_0_PCTRS15                          0x00660
++#define V3D_V3_PCTR_0_PCTRSX(x)                        (V3D_V3_PCTR_0_PCTRS0 + \
++                                                      4 * (x))
++/* Each src reg muxes four counters each. */
++#define V3D_V4_PCTR_0_SRC_0_3                          0x00660
++#define V3D_V4_PCTR_0_SRC_28_31                        0x0067c
++# define V3D_PCTR_S0_MASK                              V3D_MASK(6, 0)
++# define V3D_PCTR_S0_SHIFT                             0
++# define V3D_PCTR_S1_MASK                              V3D_MASK(14, 8)
++# define V3D_PCTR_S1_SHIFT                             8
++# define V3D_PCTR_S2_MASK                              V3D_MASK(22, 16)
++# define V3D_PCTR_S2_SHIFT                             16
++# define V3D_PCTR_S3_MASK                              V3D_MASK(30, 24)
++# define V3D_PCTR_S3_SHIFT                             24
++# define V3D_PCTR_CYCLE_COUNT                          32
++
++/* Output values of the counters. */
++#define V3D_PCTR_0_PCTR0                               0x00680
++#define V3D_PCTR_0_PCTR31                              0x006fc
++#define V3D_PCTR_0_PCTRX(x)                            (V3D_PCTR_0_PCTR0 + \
++                                                      4 * (x))
+ #define V3D_GMP_STATUS                                 0x00800
+ # define V3D_GMP_STATUS_GMPRST                         BIT(31)
+ # define V3D_GMP_STATUS_WR_COUNT_MASK                  V3D_MASK(30, 24)
diff --git a/target/linux/brcm2708/patches-4.19/950-0488-drm-v3d-Fix-a-use-after-free-race-accessing-the-sche.patch b/target/linux/brcm2708/patches-4.19/950-0488-drm-v3d-Fix-a-use-after-free-race-accessing-the-sche.patch
deleted file mode 100644 (file)
index 126452f..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From f5f3df2b1746a9ba9420ae11988fc37a7b93691d Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 28 Sep 2018 16:21:23 -0700
-Subject: [PATCH] drm/v3d: Fix a use-after-free race accessing the
- scheduler's fences.
-
-Once we push the job, the scheduler could run it and free it.  So, if
-we want to reference their fences, we need to grab them before then.
-I haven't seen this happen in many days of conformance test runtime,
-but let's still close the race.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
-Link: https://patchwork.freedesktop.org/patch/254119/
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-(cherry picked from commit 34c2c4f632f232ed2fdb66d4e42cc72d322273fe)
----
- drivers/gpu/drm/v3d/v3d_drv.h | 5 +++++
- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
- 2 files changed, 11 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -198,6 +198,11 @@ struct v3d_exec_info {
-        */
-       struct dma_fence *bin_done_fence;
-+      /* Fence for when the scheduler considers the render to be
-+       * done, for when the BOs reservations should be complete.
-+       */
-+      struct dma_fence *render_done_fence;
-+
-       struct kref refcount;
-       /* This is the array of BOs that were looked up at the start of exec. */
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -209,7 +209,7 @@ v3d_flush_caches(struct v3d_dev *v3d)
- static void
- v3d_attach_object_fences(struct v3d_exec_info *exec)
- {
--      struct dma_fence *out_fence = &exec->render.base.s_fence->finished;
-+      struct dma_fence *out_fence = exec->render_done_fence;
-       struct v3d_bo *bo;
-       int i;
-@@ -409,6 +409,7 @@ v3d_exec_cleanup(struct kref *ref)
-       dma_fence_put(exec->render.done_fence);
-       dma_fence_put(exec->bin_done_fence);
-+      dma_fence_put(exec->render_done_fence);
-       for (i = 0; i < exec->bo_count; i++)
-               drm_gem_object_put_unlocked(&exec->bo[i]->base);
-@@ -572,6 +573,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       if (ret)
-               goto fail_unreserve;
-+      exec->render_done_fence =
-+              dma_fence_get(&exec->render.base.s_fence->finished);
-+
-       kref_get(&exec->refcount); /* put by scheduler job completion */
-       drm_sched_entity_push_job(&exec->render.base,
-                                 &v3d_priv->sched_entity[V3D_RENDER]);
-@@ -585,7 +589,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       sync_out = drm_syncobj_find(file_priv, args->out_sync);
-       if (sync_out) {
-               drm_syncobj_replace_fence(sync_out,
--                                        &exec->render.base.s_fence->finished);
-+                                        exec->render_done_fence);
-               drm_syncobj_put(sync_out);
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0488-drm-v3d-Update-a-comment-about-what-uses-v3d_job_dep.patch b/target/linux/brcm2708/patches-4.19/950-0488-drm-v3d-Update-a-comment-about-what-uses-v3d_job_dep.patch
new file mode 100644 (file)
index 0000000..e506809
--- /dev/null
@@ -0,0 +1,27 @@
+From 6351d93a0f1a18c45c4407c472195d957da5d3d0 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 8 Nov 2018 08:16:52 -0800
+Subject: [PATCH] drm/v3d: Update a comment about what uses
+ v3d_job_dependency().
+
+I merged bin and render's paths in a late refactoring.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-3-eric@anholt.net
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
+(cherry picked from commit e90e45f6bd45cc494a6f4cd1853c5e7cd4be7f68)
+---
+ drivers/gpu/drm/v3d/v3d_sched.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -39,7 +39,7 @@ v3d_job_free(struct drm_sched_job *sched
+ }
+ /**
+- * Returns the fences that the bin job depends on, one by one.
++ * Returns the fences that the bin or render job depends on, one by one.
+  * v3d_job_run() won't be called until all of them have been signaled.
+  */
+ static struct dma_fence *
diff --git a/target/linux/brcm2708/patches-4.19/950-0489-drm-v3d-Add-a-little-debugfs-entry-for-measuring-the.patch b/target/linux/brcm2708/patches-4.19/950-0489-drm-v3d-Add-a-little-debugfs-entry-for-measuring-the.patch
deleted file mode 100644 (file)
index 847bb20..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-From 18f93916e42ea25fc77cab20d1e038620e33d741 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 28 Sep 2018 16:21:24 -0700
-Subject: [PATCH] drm/v3d: Add a little debugfs entry for measuring the
- core clock.
-
-This adds just enough performance counter support to measure the
-clock.  We don't have linux kernel drivers for the clock driving the
-HW, and this was useful for determining that the V3D HW is running on
-a slow clock, not that the driver was slow.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20180928232126.4332-2-eric@anholt.net
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-(cherry picked from commit 6915c9a525e575732429c22b28eb11871a29374b)
----
- drivers/gpu/drm/v3d/v3d_debugfs.c | 35 +++++++++++++++++++++++++++++++
- drivers/gpu/drm/v3d/v3d_regs.h    | 30 ++++++++++++++++++++++++++
- 2 files changed, 65 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -179,9 +179,44 @@ static int v3d_debugfs_bo_stats(struct s
-       return 0;
- }
-+static int v3d_measure_clock(struct seq_file *m, void *unused)
-+{
-+      struct drm_info_node *node = (struct drm_info_node *)m->private;
-+      struct drm_device *dev = node->minor->dev;
-+      struct v3d_dev *v3d = to_v3d_dev(dev);
-+      uint32_t cycles;
-+      int core = 0;
-+      int measure_ms = 1000;
-+
-+      if (v3d->ver >= 40) {
-+              V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
-+                             V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT,
-+                                           V3D_PCTR_S0));
-+              V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1);
-+              V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1);
-+      } else {
-+              V3D_CORE_WRITE(core, V3D_V3_PCTR_0_PCTRS0,
-+                             V3D_PCTR_CYCLE_COUNT);
-+              V3D_CORE_WRITE(core, V3D_V3_PCTR_0_CLR, 1);
-+              V3D_CORE_WRITE(core, V3D_V3_PCTR_0_EN,
-+                             V3D_V3_PCTR_0_EN_ENABLE |
-+                             1);
-+      }
-+      msleep(measure_ms);
-+      cycles = V3D_CORE_READ(core, V3D_PCTR_0_PCTR0);
-+
-+      seq_printf(m, "cycles: %d (%d.%d Mhz)\n",
-+                 cycles,
-+                 cycles / (measure_ms * 1000),
-+                 (cycles / (measure_ms * 100)) % 10);
-+
-+      return 0;
-+}
-+
- static const struct drm_info_list v3d_debugfs_list[] = {
-       {"v3d_ident", v3d_v3d_debugfs_ident, 0},
-       {"v3d_regs", v3d_v3d_debugfs_regs, 0},
-+      {"measure_clock", v3d_measure_clock, 0},
-       {"bo_stats", v3d_debugfs_bo_stats, 0},
- };
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -267,6 +267,36 @@
- # define V3D_PTB_BXCF_RWORDERDISA                      BIT(1)
- # define V3D_PTB_BXCF_CLIPDISA                         BIT(0)
-+#define V3D_V3_PCTR_0_EN                               0x00674
-+#define V3D_V3_PCTR_0_EN_ENABLE                        BIT(31)
-+#define V3D_V4_PCTR_0_EN                               0x00650
-+/* When a bit is set, resets the counter to 0. */
-+#define V3D_V3_PCTR_0_CLR                              0x00670
-+#define V3D_V4_PCTR_0_CLR                              0x00654
-+#define V3D_PCTR_0_OVERFLOW                            0x00658
-+
-+#define V3D_V3_PCTR_0_PCTRS0                           0x00684
-+#define V3D_V3_PCTR_0_PCTRS15                          0x00660
-+#define V3D_V3_PCTR_0_PCTRSX(x)                        (V3D_V3_PCTR_0_PCTRS0 + \
-+                                                      4 * (x))
-+/* Each src reg muxes four counters each. */
-+#define V3D_V4_PCTR_0_SRC_0_3                          0x00660
-+#define V3D_V4_PCTR_0_SRC_28_31                        0x0067c
-+# define V3D_PCTR_S0_MASK                              V3D_MASK(6, 0)
-+# define V3D_PCTR_S0_SHIFT                             0
-+# define V3D_PCTR_S1_MASK                              V3D_MASK(14, 8)
-+# define V3D_PCTR_S1_SHIFT                             8
-+# define V3D_PCTR_S2_MASK                              V3D_MASK(22, 16)
-+# define V3D_PCTR_S2_SHIFT                             16
-+# define V3D_PCTR_S3_MASK                              V3D_MASK(30, 24)
-+# define V3D_PCTR_S3_SHIFT                             24
-+# define V3D_PCTR_CYCLE_COUNT                          32
-+
-+/* Output values of the counters. */
-+#define V3D_PCTR_0_PCTR0                               0x00680
-+#define V3D_PCTR_0_PCTR31                              0x006fc
-+#define V3D_PCTR_0_PCTRX(x)                            (V3D_PCTR_0_PCTR0 + \
-+                                                      4 * (x))
- #define V3D_GMP_STATUS                                 0x00800
- # define V3D_GMP_STATUS_GMPRST                         BIT(31)
- # define V3D_GMP_STATUS_WR_COUNT_MASK                  V3D_MASK(30, 24)
diff --git a/target/linux/brcm2708/patches-4.19/950-0489-drm-v3d-Clean-up-the-reservation-object-setup.patch b/target/linux/brcm2708/patches-4.19/950-0489-drm-v3d-Clean-up-the-reservation-object-setup.patch
new file mode 100644 (file)
index 0000000..94156e7
--- /dev/null
@@ -0,0 +1,102 @@
+From 5ca5bd799b4f4a065b969461fa7852415bfb8c6f Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 8 Nov 2018 08:16:53 -0800
+Subject: [PATCH] drm/v3d: Clean up the reservation object setup.
+
+The extra to_v3d_bo() calls came from copying this from the vc4
+driver, which stored the cma gem object in the structs.
+
+v2: Fix an unused var warning
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-4-eric@anholt.net
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com> (v1)
+(cherry picked from commit 8f1cd826641d677d0f7494253ecfc3335f0bcd4e)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 33 +++++++++++----------------------
+ 1 file changed, 11 insertions(+), 22 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -210,14 +210,11 @@ static void
+ v3d_attach_object_fences(struct v3d_exec_info *exec)
+ {
+       struct dma_fence *out_fence = exec->render_done_fence;
+-      struct v3d_bo *bo;
+       int i;
+       for (i = 0; i < exec->bo_count; i++) {
+-              bo = to_v3d_bo(&exec->bo[i]->base);
+-
+               /* XXX: Use shared fences for read-only objects. */
+-              reservation_object_add_excl_fence(bo->resv, out_fence);
++              reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
+       }
+ }
+@@ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_de
+ {
+       int i;
+-      for (i = 0; i < exec->bo_count; i++) {
+-              struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base);
+-
+-              ww_mutex_unlock(&bo->resv->lock);
+-      }
++      for (i = 0; i < exec->bo_count; i++)
++              ww_mutex_unlock(&exec->bo[i]->resv->lock);
+       ww_acquire_fini(acquire_ctx);
+ }
+@@ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_devi
+ {
+       int contended_lock = -1;
+       int i, ret;
+-      struct v3d_bo *bo;
+       ww_acquire_init(acquire_ctx, &reservation_ww_class);
+ retry:
+       if (contended_lock != -1) {
+-              bo = to_v3d_bo(&exec->bo[contended_lock]->base);
++              struct v3d_bo *bo = exec->bo[contended_lock];
++
+               ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
+                                                      acquire_ctx);
+               if (ret) {
+@@ -270,19 +264,16 @@ retry:
+               if (i == contended_lock)
+                       continue;
+-              bo = to_v3d_bo(&exec->bo[i]->base);
+-
+-              ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
++              ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
++                                                acquire_ctx);
+               if (ret) {
+                       int j;
+-                      for (j = 0; j < i; j++) {
+-                              bo = to_v3d_bo(&exec->bo[j]->base);
+-                              ww_mutex_unlock(&bo->resv->lock);
+-                      }
++                      for (j = 0; j < i; j++)
++                              ww_mutex_unlock(&exec->bo[j]->resv->lock);
+                       if (contended_lock != -1 && contended_lock >= i) {
+-                              bo = to_v3d_bo(&exec->bo[contended_lock]->base);
++                              struct v3d_bo *bo = exec->bo[contended_lock];
+                               ww_mutex_unlock(&bo->resv->lock);
+                       }
+@@ -303,9 +294,7 @@ retry:
+        * before we commit the CL to the hardware.
+        */
+       for (i = 0; i < exec->bo_count; i++) {
+-              bo = to_v3d_bo(&exec->bo[i]->base);
+-
+-              ret = reservation_object_reserve_shared(bo->resv);
++              ret = reservation_object_reserve_shared(exec->bo[i]->resv);
+               if (ret) {
+                       v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
+                       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0490-drm-v3d-Add-support-for-submitting-jobs-to-the-TFU.patch b/target/linux/brcm2708/patches-4.19/950-0490-drm-v3d-Add-support-for-submitting-jobs-to-the-TFU.patch
new file mode 100644 (file)
index 0000000..99b1a69
--- /dev/null
@@ -0,0 +1,802 @@
+From ba1e90b6c3b3bf0e88ab01c824c4f8fde582e878 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 28 Nov 2018 15:09:25 -0800
+Subject: [PATCH] drm/v3d: Add support for submitting jobs to the TFU.
+
+The TFU can copy from raster, UIF, and SAND input images to UIF output
+images, with optional mipmap generation.  This will certainly be
+useful for media EGL image input, but is also useful immediately for
+mipmap generation without bogging the V3D core down.
+
+For now we only run the queue 1 job deep, and don't have any hang
+recovery (though I don't think we should need it, with TFU).  Queuing
+multiple jobs in the HW will require synchronizing the YUV coefficient
+regs updates since they don't get FIFOed with the job.
+
+v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
+    why TFU is AUTH, clarify the syncing docs, drop the unused TFU
+    interrupt regs (you're expected to use the hub's), don't take
+    &bo->base for NULL bos.
+v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
+    on drm_sched_job_cleanup() changes.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
+Link: https://patchwork.freedesktop.org/patch/264607/
+(cherry picked from commit 1584f16ca96ef124aad79efa3303cff5f3530e2c)
+---
+ drivers/gpu/drm/v3d/v3d_drv.c   |  15 ++-
+ drivers/gpu/drm/v3d/v3d_drv.h   |  32 +++++-
+ drivers/gpu/drm/v3d/v3d_gem.c   | 178 ++++++++++++++++++++++++++++----
+ drivers/gpu/drm/v3d/v3d_irq.c   |  12 ++-
+ drivers/gpu/drm/v3d/v3d_regs.h  |  49 +++++++++
+ drivers/gpu/drm/v3d/v3d_sched.c | 148 ++++++++++++++++++++++----
+ drivers/gpu/drm/v3d/v3d_trace.h |  20 ++++
+ include/uapi/drm/v3d_drm.h      |  25 +++++
+ 8 files changed, 426 insertions(+), 53 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -112,10 +112,15 @@ static int v3d_get_param_ioctl(struct dr
+               return 0;
+       }
+-      /* Any params that aren't just register reads would go here. */
+-      DRM_DEBUG("Unknown parameter %d\n", args->param);
+-      return -EINVAL;
++      switch (args->param) {
++      case DRM_V3D_PARAM_SUPPORTS_TFU:
++              args->value = 1;
++              return 0;
++      default:
++              DRM_DEBUG("Unknown parameter %d\n", args->param);
++              return -EINVAL;
++      }
+ }
+ static int
+@@ -170,7 +175,8 @@ static const struct file_operations v3d_
+ /* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP
+  * protection between clients.  Note that render nodes would be be
+  * able to submit CLs that could access BOs from clients authenticated
+- * with the master node.
++ * with the master node.  The TFU doesn't use the GMP, so it would
++ * need to stay DRM_AUTH until we do buffer size/offset validation.
+  */
+ static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
+       DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CL, v3d_submit_cl_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+@@ -179,6 +185,7 @@ static const struct drm_ioctl_desc v3d_d
+       DRM_IOCTL_DEF_DRV(V3D_MMAP_BO, v3d_mmap_bo_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
++      DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+ };
+ static const struct vm_operations_struct v3d_vm_ops = {
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -7,19 +7,18 @@
+ #include <drm/drm_encoder.h>
+ #include <drm/drm_gem.h>
+ #include <drm/gpu_scheduler.h>
++#include "uapi/drm/v3d_drm.h"
+ #define GMP_GRANULARITY (128 * 1024)
+-/* Enum for each of the V3D queues.  We maintain various queue
+- * tracking as an array because at some point we'll want to support
+- * the TFU (texture formatting unit) as another queue.
+- */
++/* Enum for each of the V3D queues. */
+ enum v3d_queue {
+       V3D_BIN,
+       V3D_RENDER,
++      V3D_TFU,
+ };
+-#define V3D_MAX_QUEUES (V3D_RENDER + 1)
++#define V3D_MAX_QUEUES (V3D_TFU + 1)
+ struct v3d_queue_state {
+       struct drm_gpu_scheduler sched;
+@@ -68,6 +67,7 @@ struct v3d_dev {
+       struct v3d_exec_info *bin_job;
+       struct v3d_exec_info *render_job;
++      struct v3d_tfu_job *tfu_job;
+       struct v3d_queue_state queue[V3D_MAX_QUEUES];
+@@ -218,6 +218,25 @@ struct v3d_exec_info {
+       u32 qma, qms, qts;
+ };
++struct v3d_tfu_job {
++      struct drm_sched_job base;
++
++      struct drm_v3d_submit_tfu args;
++
++      /* An optional fence userspace can pass in for the job to depend on. */
++      struct dma_fence *in_fence;
++
++      /* v3d fence to be signaled by IRQ handler when the job is complete. */
++      struct dma_fence *done_fence;
++
++      struct v3d_dev *v3d;
++
++      struct kref refcount;
++
++      /* This is the array of BOs that were looked up at the start of exec. */
++      struct v3d_bo *bo[4];
++};
++
+ /**
+  * _wait_for - magic (register) wait macro
+  *
+@@ -281,9 +300,12 @@ int v3d_gem_init(struct drm_device *dev)
+ void v3d_gem_destroy(struct drm_device *dev);
+ int v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
++int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
++                       struct drm_file *file_priv);
+ int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+ void v3d_exec_put(struct v3d_exec_info *exec);
++void v3d_tfu_job_put(struct v3d_tfu_job *exec);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
+ void v3d_flush_caches(struct v3d_dev *v3d);
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -207,26 +207,27 @@ v3d_flush_caches(struct v3d_dev *v3d)
+ }
+ static void
+-v3d_attach_object_fences(struct v3d_exec_info *exec)
++v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
++                       struct dma_fence *fence)
+ {
+-      struct dma_fence *out_fence = exec->render_done_fence;
+       int i;
+-      for (i = 0; i < exec->bo_count; i++) {
++      for (i = 0; i < bo_count; i++) {
+               /* XXX: Use shared fences for read-only objects. */
+-              reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
++              reservation_object_add_excl_fence(bos[i]->resv, fence);
+       }
+ }
+ static void
+ v3d_unlock_bo_reservations(struct drm_device *dev,
+-                         struct v3d_exec_info *exec,
++                         struct v3d_bo **bos,
++                         int bo_count,
+                          struct ww_acquire_ctx *acquire_ctx)
+ {
+       int i;
+-      for (i = 0; i < exec->bo_count; i++)
+-              ww_mutex_unlock(&exec->bo[i]->resv->lock);
++      for (i = 0; i < bo_count; i++)
++              ww_mutex_unlock(&bos[i]->resv->lock);
+       ww_acquire_fini(acquire_ctx);
+ }
+@@ -240,7 +241,8 @@ v3d_unlock_bo_reservations(struct drm_de
+  */
+ static int
+ v3d_lock_bo_reservations(struct drm_device *dev,
+-                       struct v3d_exec_info *exec,
++                       struct v3d_bo **bos,
++                       int bo_count,
+                        struct ww_acquire_ctx *acquire_ctx)
+ {
+       int contended_lock = -1;
+@@ -250,7 +252,7 @@ v3d_lock_bo_reservations(struct drm_devi
+ retry:
+       if (contended_lock != -1) {
+-              struct v3d_bo *bo = exec->bo[contended_lock];
++              struct v3d_bo *bo = bos[contended_lock];
+               ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
+                                                      acquire_ctx);
+@@ -260,20 +262,20 @@ retry:
+               }
+       }
+-      for (i = 0; i < exec->bo_count; i++) {
++      for (i = 0; i < bo_count; i++) {
+               if (i == contended_lock)
+                       continue;
+-              ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
++              ret = ww_mutex_lock_interruptible(&bos[i]->resv->lock,
+                                                 acquire_ctx);
+               if (ret) {
+                       int j;
+                       for (j = 0; j < i; j++)
+-                              ww_mutex_unlock(&exec->bo[j]->resv->lock);
++                              ww_mutex_unlock(&bos[j]->resv->lock);
+                       if (contended_lock != -1 && contended_lock >= i) {
+-                              struct v3d_bo *bo = exec->bo[contended_lock];
++                              struct v3d_bo *bo = bos[contended_lock];
+                               ww_mutex_unlock(&bo->resv->lock);
+                       }
+@@ -293,10 +295,11 @@ retry:
+       /* Reserve space for our shared (read-only) fence references,
+        * before we commit the CL to the hardware.
+        */
+-      for (i = 0; i < exec->bo_count; i++) {
+-              ret = reservation_object_reserve_shared(exec->bo[i]->resv);
++      for (i = 0; i < bo_count; i++) {
++              ret = reservation_object_reserve_shared(bos[i]->resv);
+               if (ret) {
+-                      v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
++                      v3d_unlock_bo_reservations(dev, bos, bo_count,
++                                                 acquire_ctx);
+                       return ret;
+               }
+       }
+@@ -419,6 +422,33 @@ void v3d_exec_put(struct v3d_exec_info *
+       kref_put(&exec->refcount, v3d_exec_cleanup);
+ }
++static void
++v3d_tfu_job_cleanup(struct kref *ref)
++{
++      struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
++                                             refcount);
++      struct v3d_dev *v3d = job->v3d;
++      unsigned int i;
++
++      dma_fence_put(job->in_fence);
++      dma_fence_put(job->done_fence);
++
++      for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
++              if (job->bo[i])
++                      drm_gem_object_put_unlocked(&job->bo[i]->base);
++      }
++
++      pm_runtime_mark_last_busy(v3d->dev);
++      pm_runtime_put_autosuspend(v3d->dev);
++
++      kfree(job);
++}
++
++void v3d_tfu_job_put(struct v3d_tfu_job *job)
++{
++      kref_put(&job->refcount, v3d_tfu_job_cleanup);
++}
++
+ int
+ v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+@@ -536,7 +566,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       if (ret)
+               goto fail;
+-      ret = v3d_lock_bo_reservations(dev, exec, &acquire_ctx);
++      ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
++                                     &acquire_ctx);
+       if (ret)
+               goto fail;
+@@ -570,9 +601,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
+                                 &v3d_priv->sched_entity[V3D_RENDER]);
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_attach_object_fences(exec);
++      v3d_attach_object_fences(exec->bo, exec->bo_count,
++                               exec->render_done_fence);
+-      v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
++      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
+       /* Update the return sync object for the */
+       sync_out = drm_syncobj_find(file_priv, args->out_sync);
+@@ -588,12 +620,118 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ fail_unreserve:
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
++      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
+ fail:
+       v3d_exec_put(exec);
+       return ret;
+ }
++
++/**
++ * v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D.
++ * @dev: DRM device
++ * @data: ioctl argument
++ * @file_priv: DRM file for this fd
++ *
++ * Userspace provides the register setup for the TFU, which we don't
++ * need to validate since the TFU is behind the MMU.
++ */
++int
++v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
++                   struct drm_file *file_priv)
++{
++      struct v3d_dev *v3d = to_v3d_dev(dev);
++      struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
++      struct drm_v3d_submit_tfu *args = data;
++      struct v3d_tfu_job *job;
++      struct ww_acquire_ctx acquire_ctx;
++      struct drm_syncobj *sync_out;
++      struct dma_fence *sched_done_fence;
++      int ret = 0;
++      int bo_count;
++
++      job = kcalloc(1, sizeof(*job), GFP_KERNEL);
++      if (!job)
++              return -ENOMEM;
++
++      ret = pm_runtime_get_sync(v3d->dev);
++      if (ret < 0) {
++              kfree(job);
++              return ret;
++      }
++
++      kref_init(&job->refcount);
++
++      ret = drm_syncobj_find_fence(file_priv, args->in_sync,
++                                   0, &job->in_fence);
++      if (ret == -EINVAL)
++              goto fail;
++
++      job->args = *args;
++      job->v3d = v3d;
++
++      spin_lock(&file_priv->table_lock);
++      for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
++              struct drm_gem_object *bo;
++
++              if (!args->bo_handles[bo_count])
++                      break;
++
++              bo = idr_find(&file_priv->object_idr,
++                            args->bo_handles[bo_count]);
++              if (!bo) {
++                      DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
++                                bo_count, args->bo_handles[bo_count]);
++                      ret = -ENOENT;
++                      spin_unlock(&file_priv->table_lock);
++                      goto fail;
++              }
++              drm_gem_object_get(bo);
++              job->bo[bo_count] = to_v3d_bo(bo);
++      }
++      spin_unlock(&file_priv->table_lock);
++
++      ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++      if (ret)
++              goto fail;
++
++      mutex_lock(&v3d->sched_lock);
++      ret = drm_sched_job_init(&job->base,
++                               &v3d_priv->sched_entity[V3D_TFU],
++                               v3d_priv);
++      if (ret)
++              goto fail_unreserve;
++
++      sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
++
++      kref_get(&job->refcount); /* put by scheduler job completion */
++      drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
++      mutex_unlock(&v3d->sched_lock);
++
++      v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
++
++      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++
++      /* Update the return sync object */
++      sync_out = drm_syncobj_find(file_priv, args->out_sync);
++      if (sync_out) {
++              drm_syncobj_replace_fence(sync_out, sched_done_fence);
++              drm_syncobj_put(sync_out);
++      }
++      dma_fence_put(sched_done_fence);
++
++      v3d_tfu_job_put(job);
++
++      return 0;
++
++fail_unreserve:
++      mutex_unlock(&v3d->sched_lock);
++      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++fail:
++      v3d_tfu_job_put(job);
++
++      return ret;
++}
+ int
+ v3d_gem_init(struct drm_device *dev)
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -4,8 +4,8 @@
+ /**
+  * DOC: Interrupt management for the V3D engine
+  *
+- * When we take a binning or rendering flush done interrupt, we need
+- * to signal the fence for that job so that the scheduler can queue up
++ * When we take a bin, render, or TFU done interrupt, we need to
++ * signal the fence for that job so that the scheduler can queue up
+  * the next one and unblock any waiters.
+  *
+  * When we take the binner out of memory interrupt, we need to
+@@ -23,7 +23,8 @@
+ #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV |     \
+                           V3D_HUB_INT_MMU_PTI |       \
+-                          V3D_HUB_INT_MMU_CAP))
++                          V3D_HUB_INT_MMU_CAP |       \
++                          V3D_HUB_INT_TFUC))
+ static void
+ v3d_overflow_mem_work(struct work_struct *work)
+@@ -117,6 +118,11 @@ v3d_hub_irq(int irq, void *arg)
+       /* Acknowledge the interrupts we're handling here. */
+       V3D_WRITE(V3D_HUB_INT_CLR, intsts);
++      if (intsts & V3D_HUB_INT_TFUC) {
++              dma_fence_signal(v3d->tfu_job->done_fence);
++              status = IRQ_HANDLED;
++      }
++
+       if (intsts & (V3D_HUB_INT_MMU_WRV |
+                     V3D_HUB_INT_MMU_PTI |
+                     V3D_HUB_INT_MMU_CAP)) {
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -86,6 +86,55 @@
+ # define V3D_TOP_GR_BRIDGE_SW_INIT_1                   0x0000c
+ # define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0)
++#define V3D_TFU_CS                                     0x00400
++/* Stops current job, empties input fifo. */
++# define V3D_TFU_CS_TFURST                             BIT(31)
++# define V3D_TFU_CS_CVTCT_MASK                         V3D_MASK(23, 16)
++# define V3D_TFU_CS_CVTCT_SHIFT                        16
++# define V3D_TFU_CS_NFREE_MASK                         V3D_MASK(13, 8)
++# define V3D_TFU_CS_NFREE_SHIFT                        8
++# define V3D_TFU_CS_BUSY                               BIT(0)
++
++#define V3D_TFU_SU                                     0x00404
++/* Interrupt when FINTTHR input slots are free (0 = disabled) */
++# define V3D_TFU_SU_FINTTHR_MASK                       V3D_MASK(13, 8)
++# define V3D_TFU_SU_FINTTHR_SHIFT                      8
++/* Skips resetting the CRC at the start of CRC generation. */
++# define V3D_TFU_SU_CRCCHAIN                           BIT(4)
++/* skips writes, computes CRC of the image.  miplevels must be 0. */
++# define V3D_TFU_SU_CRC                                BIT(3)
++# define V3D_TFU_SU_THROTTLE_MASK                      V3D_MASK(1, 0)
++# define V3D_TFU_SU_THROTTLE_SHIFT                     0
++
++#define V3D_TFU_ICFG                                   0x00408
++/* Interrupt when the conversion is complete. */
++# define V3D_TFU_ICFG_IOC                              BIT(0)
++
++/* Input Image Address */
++#define V3D_TFU_IIA                                    0x0040c
++/* Input Chroma Address */
++#define V3D_TFU_ICA                                    0x00410
++/* Input Image Stride */
++#define V3D_TFU_IIS                                    0x00414
++/* Input Image U-Plane Address */
++#define V3D_TFU_IUA                                    0x00418
++/* Output Image Address */
++#define V3D_TFU_IOA                                    0x0041c
++/* Image Output Size */
++#define V3D_TFU_IOS                                    0x00420
++/* TFU YUV Coefficient 0 */
++#define V3D_TFU_COEF0                                  0x00424
++/* Use these regs instead of the defaults. */
++# define V3D_TFU_COEF0_USECOEF                         BIT(31)
++/* TFU YUV Coefficient 1 */
++#define V3D_TFU_COEF1                                  0x00428
++/* TFU YUV Coefficient 2 */
++#define V3D_TFU_COEF2                                  0x0042c
++/* TFU YUV Coefficient 3 */
++#define V3D_TFU_COEF3                                  0x00430
++
++#define V3D_TFU_CRC                                    0x00434
++
+ /* Per-MMU registers. */
+ #define V3D_MMUC_CONTROL                               0x01000
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -30,6 +30,12 @@ to_v3d_job(struct drm_sched_job *sched_j
+       return container_of(sched_job, struct v3d_job, base);
+ }
++static struct v3d_tfu_job *
++to_tfu_job(struct drm_sched_job *sched_job)
++{
++      return container_of(sched_job, struct v3d_tfu_job, base);
++}
++
+ static void
+ v3d_job_free(struct drm_sched_job *sched_job)
+ {
+@@ -38,6 +44,14 @@ v3d_job_free(struct drm_sched_job *sched
+       v3d_exec_put(job->exec);
+ }
++static void
++v3d_tfu_job_free(struct drm_sched_job *sched_job)
++{
++      struct v3d_tfu_job *job = to_tfu_job(sched_job);
++
++      v3d_tfu_job_put(job);
++}
++
+ /**
+  * Returns the fences that the bin or render job depends on, one by one.
+  * v3d_job_run() won't be called until all of them have been signaled.
+@@ -76,6 +90,27 @@ v3d_job_dependency(struct drm_sched_job
+       return fence;
+ }
++/**
++ * Returns the fences that the TFU job depends on, one by one.
++ * v3d_tfu_job_run() won't be called until all of them have been
++ * signaled.
++ */
++static struct dma_fence *
++v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
++                     struct drm_sched_entity *s_entity)
++{
++      struct v3d_tfu_job *job = to_tfu_job(sched_job);
++      struct dma_fence *fence;
++
++      fence = job->in_fence;
++      if (fence) {
++              job->in_fence = NULL;
++              return fence;
++      }
++
++      return NULL;
++}
++
+ static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
+ {
+       struct v3d_job *job = to_v3d_job(sched_job);
+@@ -147,31 +182,47 @@ static struct dma_fence *v3d_job_run(str
+       return fence;
+ }
+-static void
+-v3d_job_timedout(struct drm_sched_job *sched_job)
++static struct dma_fence *
++v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ {
+-      struct v3d_job *job = to_v3d_job(sched_job);
+-      struct v3d_exec_info *exec = job->exec;
+-      struct v3d_dev *v3d = exec->v3d;
+-      enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+-      enum v3d_queue q;
+-      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
+-      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
++      struct v3d_tfu_job *job = to_tfu_job(sched_job);
++      struct v3d_dev *v3d = job->v3d;
++      struct drm_device *dev = &v3d->drm;
++      struct dma_fence *fence;
+-      /* If the current address or return address have changed, then
+-       * the GPU has probably made progress and we should delay the
+-       * reset.  This could fail if the GPU got in an infinite loop
+-       * in the CL, but that is pretty unlikely outside of an i-g-t
+-       * testcase.
+-       */
+-      if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
+-              job->timedout_ctca = ctca;
+-              job->timedout_ctra = ctra;
++      fence = v3d_fence_create(v3d, V3D_TFU);
++      if (IS_ERR(fence))
++              return NULL;
+-              schedule_delayed_work(&job->base.work_tdr,
+-                                    job->base.sched->timeout);
+-              return;
++      v3d->tfu_job = job;
++      if (job->done_fence)
++              dma_fence_put(job->done_fence);
++      job->done_fence = dma_fence_get(fence);
++
++      trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
++
++      V3D_WRITE(V3D_TFU_IIA, job->args.iia);
++      V3D_WRITE(V3D_TFU_IIS, job->args.iis);
++      V3D_WRITE(V3D_TFU_ICA, job->args.ica);
++      V3D_WRITE(V3D_TFU_IUA, job->args.iua);
++      V3D_WRITE(V3D_TFU_IOA, job->args.ioa);
++      V3D_WRITE(V3D_TFU_IOS, job->args.ios);
++      V3D_WRITE(V3D_TFU_COEF0, job->args.coef[0]);
++      if (job->args.coef[0] & V3D_TFU_COEF0_USECOEF) {
++              V3D_WRITE(V3D_TFU_COEF1, job->args.coef[1]);
++              V3D_WRITE(V3D_TFU_COEF2, job->args.coef[2]);
++              V3D_WRITE(V3D_TFU_COEF3, job->args.coef[3]);
+       }
++      /* ICFG kicks off the job. */
++      V3D_WRITE(V3D_TFU_ICFG, job->args.icfg | V3D_TFU_ICFG_IOC);
++
++      return fence;
++}
++
++static void
++v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
++{
++      enum v3d_queue q;
+       mutex_lock(&v3d->reset_lock);
+@@ -196,6 +247,41 @@ v3d_job_timedout(struct drm_sched_job *s
+       mutex_unlock(&v3d->reset_lock);
+ }
++static void
++v3d_job_timedout(struct drm_sched_job *sched_job)
++{
++      struct v3d_job *job = to_v3d_job(sched_job);
++      struct v3d_exec_info *exec = job->exec;
++      struct v3d_dev *v3d = exec->v3d;
++      enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
++      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
++      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
++
++      /* If the current address or return address have changed, then
++       * the GPU has probably made progress and we should delay the
++       * reset.  This could fail if the GPU got in an infinite loop
++       * in the CL, but that is pretty unlikely outside of an i-g-t
++       * testcase.
++       */
++      if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
++              job->timedout_ctca = ctca;
++              job->timedout_ctra = ctra;
++              schedule_delayed_work(&job->base.work_tdr,
++                                    job->base.sched->timeout);
++              return;
++      }
++
++      v3d_gpu_reset_for_timeout(v3d, sched_job);
++}
++
++static void
++v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
++{
++      struct v3d_tfu_job *job = to_tfu_job(sched_job);
++
++      v3d_gpu_reset_for_timeout(job->v3d, sched_job);
++}
++
+ static const struct drm_sched_backend_ops v3d_sched_ops = {
+       .dependency = v3d_job_dependency,
+       .run_job = v3d_job_run,
+@@ -203,6 +289,13 @@ static const struct drm_sched_backend_op
+       .free_job = v3d_job_free
+ };
++static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
++      .dependency = v3d_tfu_job_dependency,
++      .run_job = v3d_tfu_job_run,
++      .timedout_job = v3d_tfu_job_timedout,
++      .free_job = v3d_tfu_job_free
++};
++
+ int
+ v3d_sched_init(struct v3d_dev *v3d)
+ {
+@@ -232,6 +325,19 @@ v3d_sched_init(struct v3d_dev *v3d)
+               drm_sched_fini(&v3d->queue[V3D_BIN].sched);
+               return ret;
+       }
++
++      ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
++                           &v3d_tfu_sched_ops,
++                           hw_jobs_limit, job_hang_limit,
++                           msecs_to_jiffies(hang_limit_ms),
++                           "v3d_tfu");
++      if (ret) {
++              dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
++                      ret);
++              drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
++              drm_sched_fini(&v3d->queue[V3D_BIN].sched);
++              return ret;
++      }
+       return 0;
+ }
+--- a/drivers/gpu/drm/v3d/v3d_trace.h
++++ b/drivers/gpu/drm/v3d/v3d_trace.h
+@@ -42,6 +42,26 @@ TRACE_EVENT(v3d_submit_cl,
+                     __entry->ctnqea)
+ );
++TRACE_EVENT(v3d_submit_tfu,
++          TP_PROTO(struct drm_device *dev,
++                   uint64_t seqno),
++          TP_ARGS(dev, seqno),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u64, seqno)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->seqno = seqno;
++                         ),
++
++          TP_printk("dev=%u, seqno=%llu",
++                    __entry->dev,
++                    __entry->seqno)
++);
++
+ TRACE_EVENT(v3d_reset_begin,
+           TP_PROTO(struct drm_device *dev),
+           TP_ARGS(dev),
+--- a/include/uapi/drm/v3d_drm.h
++++ b/include/uapi/drm/v3d_drm.h
+@@ -36,6 +36,7 @@ extern "C" {
+ #define DRM_V3D_MMAP_BO                           0x03
+ #define DRM_V3D_GET_PARAM                         0x04
+ #define DRM_V3D_GET_BO_OFFSET                     0x05
++#define DRM_V3D_SUBMIT_TFU                        0x06
+ #define DRM_IOCTL_V3D_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
+ #define DRM_IOCTL_V3D_WAIT_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
+@@ -43,6 +44,7 @@ extern "C" {
+ #define DRM_IOCTL_V3D_MMAP_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
+ #define DRM_IOCTL_V3D_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
+ #define DRM_IOCTL_V3D_GET_BO_OFFSET       DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
++#define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
+ /**
+  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
+@@ -169,6 +171,7 @@ enum drm_v3d_param {
+       DRM_V3D_PARAM_V3D_CORE0_IDENT0,
+       DRM_V3D_PARAM_V3D_CORE0_IDENT1,
+       DRM_V3D_PARAM_V3D_CORE0_IDENT2,
++      DRM_V3D_PARAM_SUPPORTS_TFU,
+ };
+ struct drm_v3d_get_param {
+@@ -187,6 +190,28 @@ struct drm_v3d_get_bo_offset {
+       __u32 offset;
+ };
++struct drm_v3d_submit_tfu {
++      __u32 icfg;
++      __u32 iia;
++      __u32 iis;
++      __u32 ica;
++      __u32 iua;
++      __u32 ioa;
++      __u32 ios;
++      __u32 coef[4];
++      /* First handle is the output BO, following are other inputs.
++       * 0 for unused.
++       */
++      __u32 bo_handles[4];
++      /* sync object to block on before running the TFU job.  Each TFU
++       * job will execute in the order submitted to its FD.  Synchronization
++       * against rendering jobs requires using sync objects.
++       */
++      __u32 in_sync;
++      /* Sync object to signal when the TFU job is done. */
++      __u32 out_sync;
++};
++
+ #if defined(__cplusplus)
+ }
+ #endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0490-drm-v3d-Update-a-comment-about-what-uses-v3d_job_dep.patch b/target/linux/brcm2708/patches-4.19/950-0490-drm-v3d-Update-a-comment-about-what-uses-v3d_job_dep.patch
deleted file mode 100644 (file)
index e506809..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 6351d93a0f1a18c45c4407c472195d957da5d3d0 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 8 Nov 2018 08:16:52 -0800
-Subject: [PATCH] drm/v3d: Update a comment about what uses
- v3d_job_dependency().
-
-I merged bin and render's paths in a late refactoring.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-3-eric@anholt.net
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-(cherry picked from commit e90e45f6bd45cc494a6f4cd1853c5e7cd4be7f68)
----
- drivers/gpu/drm/v3d/v3d_sched.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -39,7 +39,7 @@ v3d_job_free(struct drm_sched_job *sched
- }
- /**
-- * Returns the fences that the bin job depends on, one by one.
-+ * Returns the fences that the bin or render job depends on, one by one.
-  * v3d_job_run() won't be called until all of them have been signaled.
-  */
- static struct dma_fence *
diff --git a/target/linux/brcm2708/patches-4.19/950-0491-drm-v3d-Clean-up-the-reservation-object-setup.patch b/target/linux/brcm2708/patches-4.19/950-0491-drm-v3d-Clean-up-the-reservation-object-setup.patch
deleted file mode 100644 (file)
index 94156e7..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From 5ca5bd799b4f4a065b969461fa7852415bfb8c6f Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 8 Nov 2018 08:16:53 -0800
-Subject: [PATCH] drm/v3d: Clean up the reservation object setup.
-
-The extra to_v3d_bo() calls came from copying this from the vc4
-driver, which stored the cma gem object in the structs.
-
-v2: Fix an unused var warning
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-4-eric@anholt.net
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com> (v1)
-(cherry picked from commit 8f1cd826641d677d0f7494253ecfc3335f0bcd4e)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 33 +++++++++++----------------------
- 1 file changed, 11 insertions(+), 22 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -210,14 +210,11 @@ static void
- v3d_attach_object_fences(struct v3d_exec_info *exec)
- {
-       struct dma_fence *out_fence = exec->render_done_fence;
--      struct v3d_bo *bo;
-       int i;
-       for (i = 0; i < exec->bo_count; i++) {
--              bo = to_v3d_bo(&exec->bo[i]->base);
--
-               /* XXX: Use shared fences for read-only objects. */
--              reservation_object_add_excl_fence(bo->resv, out_fence);
-+              reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
-       }
- }
-@@ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_de
- {
-       int i;
--      for (i = 0; i < exec->bo_count; i++) {
--              struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base);
--
--              ww_mutex_unlock(&bo->resv->lock);
--      }
-+      for (i = 0; i < exec->bo_count; i++)
-+              ww_mutex_unlock(&exec->bo[i]->resv->lock);
-       ww_acquire_fini(acquire_ctx);
- }
-@@ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_devi
- {
-       int contended_lock = -1;
-       int i, ret;
--      struct v3d_bo *bo;
-       ww_acquire_init(acquire_ctx, &reservation_ww_class);
- retry:
-       if (contended_lock != -1) {
--              bo = to_v3d_bo(&exec->bo[contended_lock]->base);
-+              struct v3d_bo *bo = exec->bo[contended_lock];
-+
-               ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
-                                                      acquire_ctx);
-               if (ret) {
-@@ -270,19 +264,16 @@ retry:
-               if (i == contended_lock)
-                       continue;
--              bo = to_v3d_bo(&exec->bo[i]->base);
--
--              ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
-+              ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
-+                                                acquire_ctx);
-               if (ret) {
-                       int j;
--                      for (j = 0; j < i; j++) {
--                              bo = to_v3d_bo(&exec->bo[j]->base);
--                              ww_mutex_unlock(&bo->resv->lock);
--                      }
-+                      for (j = 0; j < i; j++)
-+                              ww_mutex_unlock(&exec->bo[j]->resv->lock);
-                       if (contended_lock != -1 && contended_lock >= i) {
--                              bo = to_v3d_bo(&exec->bo[contended_lock]->base);
-+                              struct v3d_bo *bo = exec->bo[contended_lock];
-                               ww_mutex_unlock(&bo->resv->lock);
-                       }
-@@ -303,9 +294,7 @@ retry:
-        * before we commit the CL to the hardware.
-        */
-       for (i = 0; i < exec->bo_count; i++) {
--              bo = to_v3d_bo(&exec->bo[i]->base);
--
--              ret = reservation_object_reserve_shared(bo->resv);
-+              ret = reservation_object_reserve_shared(exec->bo[i]->resv);
-               if (ret) {
-                       v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
-                       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0491-drm-v3d-Drop-the-dev-argument-to-lock-unlock-of-BO-r.patch b/target/linux/brcm2708/patches-4.19/950-0491-drm-v3d-Drop-the-dev-argument-to-lock-unlock-of-BO-r.patch
new file mode 100644 (file)
index 0000000..e39c191
--- /dev/null
@@ -0,0 +1,102 @@
+From c95a4208ef87c56349d35480e68304562c7612bd Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 28 Nov 2018 15:09:26 -0800
+Subject: [PATCH] drm/v3d: Drop the "dev" argument to lock/unlock of BO
+ reservations.
+
+They were unused, as Dave Emett noticed in TFU review.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Cc: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181128230927.10951-2-eric@anholt.net
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+(cherry picked from commit e14a07fc4b961a75f6c275d6bd670ba54fbdae14)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -219,8 +219,7 @@ v3d_attach_object_fences(struct v3d_bo *
+ }
+ static void
+-v3d_unlock_bo_reservations(struct drm_device *dev,
+-                         struct v3d_bo **bos,
++v3d_unlock_bo_reservations(struct v3d_bo **bos,
+                          int bo_count,
+                          struct ww_acquire_ctx *acquire_ctx)
+ {
+@@ -240,8 +239,7 @@ v3d_unlock_bo_reservations(struct drm_de
+  * to v3d, so we don't attach dma-buf fences to them.
+  */
+ static int
+-v3d_lock_bo_reservations(struct drm_device *dev,
+-                       struct v3d_bo **bos,
++v3d_lock_bo_reservations(struct v3d_bo **bos,
+                        int bo_count,
+                        struct ww_acquire_ctx *acquire_ctx)
+ {
+@@ -298,7 +296,7 @@ retry:
+       for (i = 0; i < bo_count; i++) {
+               ret = reservation_object_reserve_shared(bos[i]->resv);
+               if (ret) {
+-                      v3d_unlock_bo_reservations(dev, bos, bo_count,
++                      v3d_unlock_bo_reservations(bos, bo_count,
+                                                  acquire_ctx);
+                       return ret;
+               }
+@@ -566,7 +564,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       if (ret)
+               goto fail;
+-      ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
++      ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
+                                      &acquire_ctx);
+       if (ret)
+               goto fail;
+@@ -604,7 +602,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       v3d_attach_object_fences(exec->bo, exec->bo_count,
+                                exec->render_done_fence);
+-      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
++      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
+       /* Update the return sync object for the */
+       sync_out = drm_syncobj_find(file_priv, args->out_sync);
+@@ -620,7 +618,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ fail_unreserve:
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
++      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
+ fail:
+       v3d_exec_put(exec);
+@@ -691,7 +689,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       }
+       spin_unlock(&file_priv->table_lock);
+-      ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++      ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+       if (ret)
+               goto fail;
+@@ -710,7 +708,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
+-      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+       /* Update the return sync object */
+       sync_out = drm_syncobj_find(file_priv, args->out_sync);
+@@ -726,7 +724,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+ fail_unreserve:
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+ fail:
+       v3d_tfu_job_put(job);
diff --git a/target/linux/brcm2708/patches-4.19/950-0492-drm-v3d-Add-missing-fence-timeline-name-for-TFU.patch b/target/linux/brcm2708/patches-4.19/950-0492-drm-v3d-Add-missing-fence-timeline-name-for-TFU.patch
new file mode 100644 (file)
index 0000000..d56e045
--- /dev/null
@@ -0,0 +1,37 @@
+From 49281ec9b6f3c7bda94c798133dd35d50eb69649 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 30 Nov 2018 16:57:59 -0800
+Subject: [PATCH] drm/v3d: Add missing fence timeline name for TFU.
+
+We shouldn't be returning v3d-render for our new queue.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 83d5139982db ("drm/v3d: Add support for submitting jobs to the TFU.")
+Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-6-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit db176f6ba1da39ad0016c77b9775a6bb3d0ce88a)
+---
+ drivers/gpu/drm/v3d/v3d_fence.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_fence.c
++++ b/drivers/gpu/drm/v3d/v3d_fence.c
+@@ -29,10 +29,16 @@ static const char *v3d_fence_get_timelin
+ {
+       struct v3d_fence *f = to_v3d_fence(fence);
+-      if (f->queue == V3D_BIN)
++      switch (f->queue) {
++      case V3D_BIN:
+               return "v3d-bin";
+-      else
++      case V3D_RENDER:
+               return "v3d-render";
++      case V3D_TFU:
++              return "v3d-tfu";
++      default:
++              return NULL;
++      }
+ }
+ const struct dma_fence_ops v3d_fence_ops = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0492-drm-v3d-Add-support-for-submitting-jobs-to-the-TFU.patch b/target/linux/brcm2708/patches-4.19/950-0492-drm-v3d-Add-support-for-submitting-jobs-to-the-TFU.patch
deleted file mode 100644 (file)
index 99b1a69..0000000
+++ /dev/null
@@ -1,802 +0,0 @@
-From ba1e90b6c3b3bf0e88ab01c824c4f8fde582e878 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 28 Nov 2018 15:09:25 -0800
-Subject: [PATCH] drm/v3d: Add support for submitting jobs to the TFU.
-
-The TFU can copy from raster, UIF, and SAND input images to UIF output
-images, with optional mipmap generation.  This will certainly be
-useful for media EGL image input, but is also useful immediately for
-mipmap generation without bogging the V3D core down.
-
-For now we only run the queue 1 job deep, and don't have any hang
-recovery (though I don't think we should need it, with TFU).  Queuing
-multiple jobs in the HW will require synchronizing the YUV coefficient
-regs updates since they don't get FIFOed with the job.
-
-v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
-    why TFU is AUTH, clarify the syncing docs, drop the unused TFU
-    interrupt regs (you're expected to use the hub's), don't take
-    &bo->base for NULL bos.
-v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
-    on drm_sched_job_cleanup() changes.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
-Link: https://patchwork.freedesktop.org/patch/264607/
-(cherry picked from commit 1584f16ca96ef124aad79efa3303cff5f3530e2c)
----
- drivers/gpu/drm/v3d/v3d_drv.c   |  15 ++-
- drivers/gpu/drm/v3d/v3d_drv.h   |  32 +++++-
- drivers/gpu/drm/v3d/v3d_gem.c   | 178 ++++++++++++++++++++++++++++----
- drivers/gpu/drm/v3d/v3d_irq.c   |  12 ++-
- drivers/gpu/drm/v3d/v3d_regs.h  |  49 +++++++++
- drivers/gpu/drm/v3d/v3d_sched.c | 148 ++++++++++++++++++++++----
- drivers/gpu/drm/v3d/v3d_trace.h |  20 ++++
- include/uapi/drm/v3d_drm.h      |  25 +++++
- 8 files changed, 426 insertions(+), 53 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -112,10 +112,15 @@ static int v3d_get_param_ioctl(struct dr
-               return 0;
-       }
--      /* Any params that aren't just register reads would go here. */
--      DRM_DEBUG("Unknown parameter %d\n", args->param);
--      return -EINVAL;
-+      switch (args->param) {
-+      case DRM_V3D_PARAM_SUPPORTS_TFU:
-+              args->value = 1;
-+              return 0;
-+      default:
-+              DRM_DEBUG("Unknown parameter %d\n", args->param);
-+              return -EINVAL;
-+      }
- }
- static int
-@@ -170,7 +175,8 @@ static const struct file_operations v3d_
- /* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP
-  * protection between clients.  Note that render nodes would be be
-  * able to submit CLs that could access BOs from clients authenticated
-- * with the master node.
-+ * with the master node.  The TFU doesn't use the GMP, so it would
-+ * need to stay DRM_AUTH until we do buffer size/offset validation.
-  */
- static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CL, v3d_submit_cl_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
-@@ -179,6 +185,7 @@ static const struct drm_ioctl_desc v3d_d
-       DRM_IOCTL_DEF_DRV(V3D_MMAP_BO, v3d_mmap_bo_ioctl, DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
-+      DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
- };
- static const struct vm_operations_struct v3d_vm_ops = {
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -7,19 +7,18 @@
- #include <drm/drm_encoder.h>
- #include <drm/drm_gem.h>
- #include <drm/gpu_scheduler.h>
-+#include "uapi/drm/v3d_drm.h"
- #define GMP_GRANULARITY (128 * 1024)
--/* Enum for each of the V3D queues.  We maintain various queue
-- * tracking as an array because at some point we'll want to support
-- * the TFU (texture formatting unit) as another queue.
-- */
-+/* Enum for each of the V3D queues. */
- enum v3d_queue {
-       V3D_BIN,
-       V3D_RENDER,
-+      V3D_TFU,
- };
--#define V3D_MAX_QUEUES (V3D_RENDER + 1)
-+#define V3D_MAX_QUEUES (V3D_TFU + 1)
- struct v3d_queue_state {
-       struct drm_gpu_scheduler sched;
-@@ -68,6 +67,7 @@ struct v3d_dev {
-       struct v3d_exec_info *bin_job;
-       struct v3d_exec_info *render_job;
-+      struct v3d_tfu_job *tfu_job;
-       struct v3d_queue_state queue[V3D_MAX_QUEUES];
-@@ -218,6 +218,25 @@ struct v3d_exec_info {
-       u32 qma, qms, qts;
- };
-+struct v3d_tfu_job {
-+      struct drm_sched_job base;
-+
-+      struct drm_v3d_submit_tfu args;
-+
-+      /* An optional fence userspace can pass in for the job to depend on. */
-+      struct dma_fence *in_fence;
-+
-+      /* v3d fence to be signaled by IRQ handler when the job is complete. */
-+      struct dma_fence *done_fence;
-+
-+      struct v3d_dev *v3d;
-+
-+      struct kref refcount;
-+
-+      /* This is the array of BOs that were looked up at the start of exec. */
-+      struct v3d_bo *bo[4];
-+};
-+
- /**
-  * _wait_for - magic (register) wait macro
-  *
-@@ -281,9 +300,12 @@ int v3d_gem_init(struct drm_device *dev)
- void v3d_gem_destroy(struct drm_device *dev);
- int v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-+int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
-+                       struct drm_file *file_priv);
- int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
- void v3d_exec_put(struct v3d_exec_info *exec);
-+void v3d_tfu_job_put(struct v3d_tfu_job *exec);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
- void v3d_flush_caches(struct v3d_dev *v3d);
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -207,26 +207,27 @@ v3d_flush_caches(struct v3d_dev *v3d)
- }
- static void
--v3d_attach_object_fences(struct v3d_exec_info *exec)
-+v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
-+                       struct dma_fence *fence)
- {
--      struct dma_fence *out_fence = exec->render_done_fence;
-       int i;
--      for (i = 0; i < exec->bo_count; i++) {
-+      for (i = 0; i < bo_count; i++) {
-               /* XXX: Use shared fences for read-only objects. */
--              reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
-+              reservation_object_add_excl_fence(bos[i]->resv, fence);
-       }
- }
- static void
- v3d_unlock_bo_reservations(struct drm_device *dev,
--                         struct v3d_exec_info *exec,
-+                         struct v3d_bo **bos,
-+                         int bo_count,
-                          struct ww_acquire_ctx *acquire_ctx)
- {
-       int i;
--      for (i = 0; i < exec->bo_count; i++)
--              ww_mutex_unlock(&exec->bo[i]->resv->lock);
-+      for (i = 0; i < bo_count; i++)
-+              ww_mutex_unlock(&bos[i]->resv->lock);
-       ww_acquire_fini(acquire_ctx);
- }
-@@ -240,7 +241,8 @@ v3d_unlock_bo_reservations(struct drm_de
-  */
- static int
- v3d_lock_bo_reservations(struct drm_device *dev,
--                       struct v3d_exec_info *exec,
-+                       struct v3d_bo **bos,
-+                       int bo_count,
-                        struct ww_acquire_ctx *acquire_ctx)
- {
-       int contended_lock = -1;
-@@ -250,7 +252,7 @@ v3d_lock_bo_reservations(struct drm_devi
- retry:
-       if (contended_lock != -1) {
--              struct v3d_bo *bo = exec->bo[contended_lock];
-+              struct v3d_bo *bo = bos[contended_lock];
-               ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
-                                                      acquire_ctx);
-@@ -260,20 +262,20 @@ retry:
-               }
-       }
--      for (i = 0; i < exec->bo_count; i++) {
-+      for (i = 0; i < bo_count; i++) {
-               if (i == contended_lock)
-                       continue;
--              ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
-+              ret = ww_mutex_lock_interruptible(&bos[i]->resv->lock,
-                                                 acquire_ctx);
-               if (ret) {
-                       int j;
-                       for (j = 0; j < i; j++)
--                              ww_mutex_unlock(&exec->bo[j]->resv->lock);
-+                              ww_mutex_unlock(&bos[j]->resv->lock);
-                       if (contended_lock != -1 && contended_lock >= i) {
--                              struct v3d_bo *bo = exec->bo[contended_lock];
-+                              struct v3d_bo *bo = bos[contended_lock];
-                               ww_mutex_unlock(&bo->resv->lock);
-                       }
-@@ -293,10 +295,11 @@ retry:
-       /* Reserve space for our shared (read-only) fence references,
-        * before we commit the CL to the hardware.
-        */
--      for (i = 0; i < exec->bo_count; i++) {
--              ret = reservation_object_reserve_shared(exec->bo[i]->resv);
-+      for (i = 0; i < bo_count; i++) {
-+              ret = reservation_object_reserve_shared(bos[i]->resv);
-               if (ret) {
--                      v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
-+                      v3d_unlock_bo_reservations(dev, bos, bo_count,
-+                                                 acquire_ctx);
-                       return ret;
-               }
-       }
-@@ -419,6 +422,33 @@ void v3d_exec_put(struct v3d_exec_info *
-       kref_put(&exec->refcount, v3d_exec_cleanup);
- }
-+static void
-+v3d_tfu_job_cleanup(struct kref *ref)
-+{
-+      struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
-+                                             refcount);
-+      struct v3d_dev *v3d = job->v3d;
-+      unsigned int i;
-+
-+      dma_fence_put(job->in_fence);
-+      dma_fence_put(job->done_fence);
-+
-+      for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
-+              if (job->bo[i])
-+                      drm_gem_object_put_unlocked(&job->bo[i]->base);
-+      }
-+
-+      pm_runtime_mark_last_busy(v3d->dev);
-+      pm_runtime_put_autosuspend(v3d->dev);
-+
-+      kfree(job);
-+}
-+
-+void v3d_tfu_job_put(struct v3d_tfu_job *job)
-+{
-+      kref_put(&job->refcount, v3d_tfu_job_cleanup);
-+}
-+
- int
- v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-@@ -536,7 +566,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       if (ret)
-               goto fail;
--      ret = v3d_lock_bo_reservations(dev, exec, &acquire_ctx);
-+      ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
-+                                     &acquire_ctx);
-       if (ret)
-               goto fail;
-@@ -570,9 +601,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
-                                 &v3d_priv->sched_entity[V3D_RENDER]);
-       mutex_unlock(&v3d->sched_lock);
--      v3d_attach_object_fences(exec);
-+      v3d_attach_object_fences(exec->bo, exec->bo_count,
-+                               exec->render_done_fence);
--      v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
-+      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
-       /* Update the return sync object for the */
-       sync_out = drm_syncobj_find(file_priv, args->out_sync);
-@@ -588,12 +620,118 @@ v3d_submit_cl_ioctl(struct drm_device *d
- fail_unreserve:
-       mutex_unlock(&v3d->sched_lock);
--      v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
-+      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
- fail:
-       v3d_exec_put(exec);
-       return ret;
- }
-+
-+/**
-+ * v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D.
-+ * @dev: DRM device
-+ * @data: ioctl argument
-+ * @file_priv: DRM file for this fd
-+ *
-+ * Userspace provides the register setup for the TFU, which we don't
-+ * need to validate since the TFU is behind the MMU.
-+ */
-+int
-+v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
-+                   struct drm_file *file_priv)
-+{
-+      struct v3d_dev *v3d = to_v3d_dev(dev);
-+      struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
-+      struct drm_v3d_submit_tfu *args = data;
-+      struct v3d_tfu_job *job;
-+      struct ww_acquire_ctx acquire_ctx;
-+      struct drm_syncobj *sync_out;
-+      struct dma_fence *sched_done_fence;
-+      int ret = 0;
-+      int bo_count;
-+
-+      job = kcalloc(1, sizeof(*job), GFP_KERNEL);
-+      if (!job)
-+              return -ENOMEM;
-+
-+      ret = pm_runtime_get_sync(v3d->dev);
-+      if (ret < 0) {
-+              kfree(job);
-+              return ret;
-+      }
-+
-+      kref_init(&job->refcount);
-+
-+      ret = drm_syncobj_find_fence(file_priv, args->in_sync,
-+                                   0, &job->in_fence);
-+      if (ret == -EINVAL)
-+              goto fail;
-+
-+      job->args = *args;
-+      job->v3d = v3d;
-+
-+      spin_lock(&file_priv->table_lock);
-+      for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
-+              struct drm_gem_object *bo;
-+
-+              if (!args->bo_handles[bo_count])
-+                      break;
-+
-+              bo = idr_find(&file_priv->object_idr,
-+                            args->bo_handles[bo_count]);
-+              if (!bo) {
-+                      DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
-+                                bo_count, args->bo_handles[bo_count]);
-+                      ret = -ENOENT;
-+                      spin_unlock(&file_priv->table_lock);
-+                      goto fail;
-+              }
-+              drm_gem_object_get(bo);
-+              job->bo[bo_count] = to_v3d_bo(bo);
-+      }
-+      spin_unlock(&file_priv->table_lock);
-+
-+      ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+      if (ret)
-+              goto fail;
-+
-+      mutex_lock(&v3d->sched_lock);
-+      ret = drm_sched_job_init(&job->base,
-+                               &v3d_priv->sched_entity[V3D_TFU],
-+                               v3d_priv);
-+      if (ret)
-+              goto fail_unreserve;
-+
-+      sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
-+
-+      kref_get(&job->refcount); /* put by scheduler job completion */
-+      drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
-+      mutex_unlock(&v3d->sched_lock);
-+
-+      v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
-+
-+      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+
-+      /* Update the return sync object */
-+      sync_out = drm_syncobj_find(file_priv, args->out_sync);
-+      if (sync_out) {
-+              drm_syncobj_replace_fence(sync_out, sched_done_fence);
-+              drm_syncobj_put(sync_out);
-+      }
-+      dma_fence_put(sched_done_fence);
-+
-+      v3d_tfu_job_put(job);
-+
-+      return 0;
-+
-+fail_unreserve:
-+      mutex_unlock(&v3d->sched_lock);
-+      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+fail:
-+      v3d_tfu_job_put(job);
-+
-+      return ret;
-+}
- int
- v3d_gem_init(struct drm_device *dev)
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -4,8 +4,8 @@
- /**
-  * DOC: Interrupt management for the V3D engine
-  *
-- * When we take a binning or rendering flush done interrupt, we need
-- * to signal the fence for that job so that the scheduler can queue up
-+ * When we take a bin, render, or TFU done interrupt, we need to
-+ * signal the fence for that job so that the scheduler can queue up
-  * the next one and unblock any waiters.
-  *
-  * When we take the binner out of memory interrupt, we need to
-@@ -23,7 +23,8 @@
- #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV |     \
-                           V3D_HUB_INT_MMU_PTI |       \
--                          V3D_HUB_INT_MMU_CAP))
-+                          V3D_HUB_INT_MMU_CAP |       \
-+                          V3D_HUB_INT_TFUC))
- static void
- v3d_overflow_mem_work(struct work_struct *work)
-@@ -117,6 +118,11 @@ v3d_hub_irq(int irq, void *arg)
-       /* Acknowledge the interrupts we're handling here. */
-       V3D_WRITE(V3D_HUB_INT_CLR, intsts);
-+      if (intsts & V3D_HUB_INT_TFUC) {
-+              dma_fence_signal(v3d->tfu_job->done_fence);
-+              status = IRQ_HANDLED;
-+      }
-+
-       if (intsts & (V3D_HUB_INT_MMU_WRV |
-                     V3D_HUB_INT_MMU_PTI |
-                     V3D_HUB_INT_MMU_CAP)) {
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -86,6 +86,55 @@
- # define V3D_TOP_GR_BRIDGE_SW_INIT_1                   0x0000c
- # define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0)
-+#define V3D_TFU_CS                                     0x00400
-+/* Stops current job, empties input fifo. */
-+# define V3D_TFU_CS_TFURST                             BIT(31)
-+# define V3D_TFU_CS_CVTCT_MASK                         V3D_MASK(23, 16)
-+# define V3D_TFU_CS_CVTCT_SHIFT                        16
-+# define V3D_TFU_CS_NFREE_MASK                         V3D_MASK(13, 8)
-+# define V3D_TFU_CS_NFREE_SHIFT                        8
-+# define V3D_TFU_CS_BUSY                               BIT(0)
-+
-+#define V3D_TFU_SU                                     0x00404
-+/* Interrupt when FINTTHR input slots are free (0 = disabled) */
-+# define V3D_TFU_SU_FINTTHR_MASK                       V3D_MASK(13, 8)
-+# define V3D_TFU_SU_FINTTHR_SHIFT                      8
-+/* Skips resetting the CRC at the start of CRC generation. */
-+# define V3D_TFU_SU_CRCCHAIN                           BIT(4)
-+/* skips writes, computes CRC of the image.  miplevels must be 0. */
-+# define V3D_TFU_SU_CRC                                BIT(3)
-+# define V3D_TFU_SU_THROTTLE_MASK                      V3D_MASK(1, 0)
-+# define V3D_TFU_SU_THROTTLE_SHIFT                     0
-+
-+#define V3D_TFU_ICFG                                   0x00408
-+/* Interrupt when the conversion is complete. */
-+# define V3D_TFU_ICFG_IOC                              BIT(0)
-+
-+/* Input Image Address */
-+#define V3D_TFU_IIA                                    0x0040c
-+/* Input Chroma Address */
-+#define V3D_TFU_ICA                                    0x00410
-+/* Input Image Stride */
-+#define V3D_TFU_IIS                                    0x00414
-+/* Input Image U-Plane Address */
-+#define V3D_TFU_IUA                                    0x00418
-+/* Output Image Address */
-+#define V3D_TFU_IOA                                    0x0041c
-+/* Image Output Size */
-+#define V3D_TFU_IOS                                    0x00420
-+/* TFU YUV Coefficient 0 */
-+#define V3D_TFU_COEF0                                  0x00424
-+/* Use these regs instead of the defaults. */
-+# define V3D_TFU_COEF0_USECOEF                         BIT(31)
-+/* TFU YUV Coefficient 1 */
-+#define V3D_TFU_COEF1                                  0x00428
-+/* TFU YUV Coefficient 2 */
-+#define V3D_TFU_COEF2                                  0x0042c
-+/* TFU YUV Coefficient 3 */
-+#define V3D_TFU_COEF3                                  0x00430
-+
-+#define V3D_TFU_CRC                                    0x00434
-+
- /* Per-MMU registers. */
- #define V3D_MMUC_CONTROL                               0x01000
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -30,6 +30,12 @@ to_v3d_job(struct drm_sched_job *sched_j
-       return container_of(sched_job, struct v3d_job, base);
- }
-+static struct v3d_tfu_job *
-+to_tfu_job(struct drm_sched_job *sched_job)
-+{
-+      return container_of(sched_job, struct v3d_tfu_job, base);
-+}
-+
- static void
- v3d_job_free(struct drm_sched_job *sched_job)
- {
-@@ -38,6 +44,14 @@ v3d_job_free(struct drm_sched_job *sched
-       v3d_exec_put(job->exec);
- }
-+static void
-+v3d_tfu_job_free(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+
-+      v3d_tfu_job_put(job);
-+}
-+
- /**
-  * Returns the fences that the bin or render job depends on, one by one.
-  * v3d_job_run() won't be called until all of them have been signaled.
-@@ -76,6 +90,27 @@ v3d_job_dependency(struct drm_sched_job
-       return fence;
- }
-+/**
-+ * Returns the fences that the TFU job depends on, one by one.
-+ * v3d_tfu_job_run() won't be called until all of them have been
-+ * signaled.
-+ */
-+static struct dma_fence *
-+v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
-+                     struct drm_sched_entity *s_entity)
-+{
-+      struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+      struct dma_fence *fence;
-+
-+      fence = job->in_fence;
-+      if (fence) {
-+              job->in_fence = NULL;
-+              return fence;
-+      }
-+
-+      return NULL;
-+}
-+
- static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
- {
-       struct v3d_job *job = to_v3d_job(sched_job);
-@@ -147,31 +182,47 @@ static struct dma_fence *v3d_job_run(str
-       return fence;
- }
--static void
--v3d_job_timedout(struct drm_sched_job *sched_job)
-+static struct dma_fence *
-+v3d_tfu_job_run(struct drm_sched_job *sched_job)
- {
--      struct v3d_job *job = to_v3d_job(sched_job);
--      struct v3d_exec_info *exec = job->exec;
--      struct v3d_dev *v3d = exec->v3d;
--      enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
--      enum v3d_queue q;
--      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
--      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
-+      struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+      struct v3d_dev *v3d = job->v3d;
-+      struct drm_device *dev = &v3d->drm;
-+      struct dma_fence *fence;
--      /* If the current address or return address have changed, then
--       * the GPU has probably made progress and we should delay the
--       * reset.  This could fail if the GPU got in an infinite loop
--       * in the CL, but that is pretty unlikely outside of an i-g-t
--       * testcase.
--       */
--      if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
--              job->timedout_ctca = ctca;
--              job->timedout_ctra = ctra;
-+      fence = v3d_fence_create(v3d, V3D_TFU);
-+      if (IS_ERR(fence))
-+              return NULL;
--              schedule_delayed_work(&job->base.work_tdr,
--                                    job->base.sched->timeout);
--              return;
-+      v3d->tfu_job = job;
-+      if (job->done_fence)
-+              dma_fence_put(job->done_fence);
-+      job->done_fence = dma_fence_get(fence);
-+
-+      trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
-+
-+      V3D_WRITE(V3D_TFU_IIA, job->args.iia);
-+      V3D_WRITE(V3D_TFU_IIS, job->args.iis);
-+      V3D_WRITE(V3D_TFU_ICA, job->args.ica);
-+      V3D_WRITE(V3D_TFU_IUA, job->args.iua);
-+      V3D_WRITE(V3D_TFU_IOA, job->args.ioa);
-+      V3D_WRITE(V3D_TFU_IOS, job->args.ios);
-+      V3D_WRITE(V3D_TFU_COEF0, job->args.coef[0]);
-+      if (job->args.coef[0] & V3D_TFU_COEF0_USECOEF) {
-+              V3D_WRITE(V3D_TFU_COEF1, job->args.coef[1]);
-+              V3D_WRITE(V3D_TFU_COEF2, job->args.coef[2]);
-+              V3D_WRITE(V3D_TFU_COEF3, job->args.coef[3]);
-       }
-+      /* ICFG kicks off the job. */
-+      V3D_WRITE(V3D_TFU_ICFG, job->args.icfg | V3D_TFU_ICFG_IOC);
-+
-+      return fence;
-+}
-+
-+static void
-+v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
-+{
-+      enum v3d_queue q;
-       mutex_lock(&v3d->reset_lock);
-@@ -196,6 +247,41 @@ v3d_job_timedout(struct drm_sched_job *s
-       mutex_unlock(&v3d->reset_lock);
- }
-+static void
-+v3d_job_timedout(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_job *job = to_v3d_job(sched_job);
-+      struct v3d_exec_info *exec = job->exec;
-+      struct v3d_dev *v3d = exec->v3d;
-+      enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
-+      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
-+      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
-+
-+      /* If the current address or return address have changed, then
-+       * the GPU has probably made progress and we should delay the
-+       * reset.  This could fail if the GPU got in an infinite loop
-+       * in the CL, but that is pretty unlikely outside of an i-g-t
-+       * testcase.
-+       */
-+      if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
-+              job->timedout_ctca = ctca;
-+              job->timedout_ctra = ctra;
-+              schedule_delayed_work(&job->base.work_tdr,
-+                                    job->base.sched->timeout);
-+              return;
-+      }
-+
-+      v3d_gpu_reset_for_timeout(v3d, sched_job);
-+}
-+
-+static void
-+v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+
-+      v3d_gpu_reset_for_timeout(job->v3d, sched_job);
-+}
-+
- static const struct drm_sched_backend_ops v3d_sched_ops = {
-       .dependency = v3d_job_dependency,
-       .run_job = v3d_job_run,
-@@ -203,6 +289,13 @@ static const struct drm_sched_backend_op
-       .free_job = v3d_job_free
- };
-+static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
-+      .dependency = v3d_tfu_job_dependency,
-+      .run_job = v3d_tfu_job_run,
-+      .timedout_job = v3d_tfu_job_timedout,
-+      .free_job = v3d_tfu_job_free
-+};
-+
- int
- v3d_sched_init(struct v3d_dev *v3d)
- {
-@@ -232,6 +325,19 @@ v3d_sched_init(struct v3d_dev *v3d)
-               drm_sched_fini(&v3d->queue[V3D_BIN].sched);
-               return ret;
-       }
-+
-+      ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
-+                           &v3d_tfu_sched_ops,
-+                           hw_jobs_limit, job_hang_limit,
-+                           msecs_to_jiffies(hang_limit_ms),
-+                           "v3d_tfu");
-+      if (ret) {
-+              dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
-+                      ret);
-+              drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
-+              drm_sched_fini(&v3d->queue[V3D_BIN].sched);
-+              return ret;
-+      }
-       return 0;
- }
---- a/drivers/gpu/drm/v3d/v3d_trace.h
-+++ b/drivers/gpu/drm/v3d/v3d_trace.h
-@@ -42,6 +42,26 @@ TRACE_EVENT(v3d_submit_cl,
-                     __entry->ctnqea)
- );
-+TRACE_EVENT(v3d_submit_tfu,
-+          TP_PROTO(struct drm_device *dev,
-+                   uint64_t seqno),
-+          TP_ARGS(dev, seqno),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u64, seqno)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->seqno = seqno;
-+                         ),
-+
-+          TP_printk("dev=%u, seqno=%llu",
-+                    __entry->dev,
-+                    __entry->seqno)
-+);
-+
- TRACE_EVENT(v3d_reset_begin,
-           TP_PROTO(struct drm_device *dev),
-           TP_ARGS(dev),
---- a/include/uapi/drm/v3d_drm.h
-+++ b/include/uapi/drm/v3d_drm.h
-@@ -36,6 +36,7 @@ extern "C" {
- #define DRM_V3D_MMAP_BO                           0x03
- #define DRM_V3D_GET_PARAM                         0x04
- #define DRM_V3D_GET_BO_OFFSET                     0x05
-+#define DRM_V3D_SUBMIT_TFU                        0x06
- #define DRM_IOCTL_V3D_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
- #define DRM_IOCTL_V3D_WAIT_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
-@@ -43,6 +44,7 @@ extern "C" {
- #define DRM_IOCTL_V3D_MMAP_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
- #define DRM_IOCTL_V3D_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
- #define DRM_IOCTL_V3D_GET_BO_OFFSET       DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
-+#define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
- /**
-  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
-@@ -169,6 +171,7 @@ enum drm_v3d_param {
-       DRM_V3D_PARAM_V3D_CORE0_IDENT0,
-       DRM_V3D_PARAM_V3D_CORE0_IDENT1,
-       DRM_V3D_PARAM_V3D_CORE0_IDENT2,
-+      DRM_V3D_PARAM_SUPPORTS_TFU,
- };
- struct drm_v3d_get_param {
-@@ -187,6 +190,28 @@ struct drm_v3d_get_bo_offset {
-       __u32 offset;
- };
-+struct drm_v3d_submit_tfu {
-+      __u32 icfg;
-+      __u32 iia;
-+      __u32 iis;
-+      __u32 ica;
-+      __u32 iua;
-+      __u32 ioa;
-+      __u32 ios;
-+      __u32 coef[4];
-+      /* First handle is the output BO, following are other inputs.
-+       * 0 for unused.
-+       */
-+      __u32 bo_handles[4];
-+      /* sync object to block on before running the TFU job.  Each TFU
-+       * job will execute in the order submitted to its FD.  Synchronization
-+       * against rendering jobs requires using sync objects.
-+       */
-+      __u32 in_sync;
-+      /* Sync object to signal when the TFU job is done. */
-+      __u32 out_sync;
-+};
-+
- #if defined(__cplusplus)
- }
- #endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0493-drm-v3d-Add-more-tracepoints-for-V3D-GPU-rendering.patch b/target/linux/brcm2708/patches-4.19/950-0493-drm-v3d-Add-more-tracepoints-for-V3D-GPU-rendering.patch
new file mode 100644 (file)
index 0000000..0b54645
--- /dev/null
@@ -0,0 +1,205 @@
+From 128adbc39c9826ca137ca3627cff17644e786fdb Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 30 Nov 2018 16:57:58 -0800
+Subject: [PATCH] drm/v3d: Add more tracepoints for V3D GPU rendering.
+
+The core scheduler tells us when the job is pushed to the scheduler's
+queue, and I had the job_run functions saying when they actually queue
+the job to the hardware.  By adding tracepoints for the very top of
+the ioctls and the IRQs signaling job completion, "perf record -a -e
+v3d:.\* -e gpu_scheduler:.\* <job>; perf script" gets you a pretty
+decent timeline.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-5-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit 55a9b74846ed5e6219c7d81a8e1bf96f25d8ad5e)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c   |   4 ++
+ drivers/gpu/drm/v3d/v3d_irq.c   |  19 +++++-
+ drivers/gpu/drm/v3d/v3d_trace.h | 101 ++++++++++++++++++++++++++++++++
+ 3 files changed, 121 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -521,6 +521,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       struct drm_syncobj *sync_out;
+       int ret = 0;
++      trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
++
+       if (args->pad != 0) {
+               DRM_INFO("pad must be zero: %d\n", args->pad);
+               return -EINVAL;
+@@ -648,6 +650,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       int ret = 0;
+       int bo_count;
++      trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
++
+       job = kcalloc(1, sizeof(*job), GFP_KERNEL);
+       if (!job)
+               return -ENOMEM;
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -15,6 +15,7 @@
+ #include "v3d_drv.h"
+ #include "v3d_regs.h"
++#include "v3d_trace.h"
+ #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM |        \
+                            V3D_INT_FLDONE |   \
+@@ -88,12 +89,20 @@ v3d_irq(int irq, void *arg)
+       }
+       if (intsts & V3D_INT_FLDONE) {
+-              dma_fence_signal(v3d->bin_job->bin.done_fence);
++              struct v3d_fence *fence =
++                      to_v3d_fence(v3d->bin_job->bin.done_fence);
++
++              trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
++              dma_fence_signal(&fence->base);
+               status = IRQ_HANDLED;
+       }
+       if (intsts & V3D_INT_FRDONE) {
+-              dma_fence_signal(v3d->render_job->render.done_fence);
++              struct v3d_fence *fence =
++                      to_v3d_fence(v3d->render_job->render.done_fence);
++
++              trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
++              dma_fence_signal(&fence->base);
+               status = IRQ_HANDLED;
+       }
+@@ -119,7 +128,11 @@ v3d_hub_irq(int irq, void *arg)
+       V3D_WRITE(V3D_HUB_INT_CLR, intsts);
+       if (intsts & V3D_HUB_INT_TFUC) {
+-              dma_fence_signal(v3d->tfu_job->done_fence);
++              struct v3d_fence *fence =
++                      to_v3d_fence(v3d->tfu_job->done_fence);
++
++              trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
++              dma_fence_signal(&fence->base);
+               status = IRQ_HANDLED;
+       }
+--- a/drivers/gpu/drm/v3d/v3d_trace.h
++++ b/drivers/gpu/drm/v3d/v3d_trace.h
+@@ -12,6 +12,28 @@
+ #define TRACE_SYSTEM v3d
+ #define TRACE_INCLUDE_FILE v3d_trace
++TRACE_EVENT(v3d_submit_cl_ioctl,
++          TP_PROTO(struct drm_device *dev, u32 ct1qba, u32 ct1qea),
++          TP_ARGS(dev, ct1qba, ct1qea),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u32, ct1qba)
++                           __field(u32, ct1qea)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->ct1qba = ct1qba;
++                         __entry->ct1qea = ct1qea;
++                         ),
++
++          TP_printk("dev=%u, RCL 0x%08x..0x%08x",
++                    __entry->dev,
++                    __entry->ct1qba,
++                    __entry->ct1qea)
++);
++
+ TRACE_EVENT(v3d_submit_cl,
+           TP_PROTO(struct drm_device *dev, bool is_render,
+                    uint64_t seqno,
+@@ -42,6 +64,85 @@ TRACE_EVENT(v3d_submit_cl,
+                     __entry->ctnqea)
+ );
++TRACE_EVENT(v3d_bcl_irq,
++          TP_PROTO(struct drm_device *dev,
++                   uint64_t seqno),
++          TP_ARGS(dev, seqno),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u64, seqno)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->seqno = seqno;
++                         ),
++
++          TP_printk("dev=%u, seqno=%llu",
++                    __entry->dev,
++                    __entry->seqno)
++);
++
++TRACE_EVENT(v3d_rcl_irq,
++          TP_PROTO(struct drm_device *dev,
++                   uint64_t seqno),
++          TP_ARGS(dev, seqno),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u64, seqno)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->seqno = seqno;
++                         ),
++
++          TP_printk("dev=%u, seqno=%llu",
++                    __entry->dev,
++                    __entry->seqno)
++);
++
++TRACE_EVENT(v3d_tfu_irq,
++          TP_PROTO(struct drm_device *dev,
++                   uint64_t seqno),
++          TP_ARGS(dev, seqno),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u64, seqno)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->seqno = seqno;
++                         ),
++
++          TP_printk("dev=%u, seqno=%llu",
++                    __entry->dev,
++                    __entry->seqno)
++);
++
++TRACE_EVENT(v3d_submit_tfu_ioctl,
++          TP_PROTO(struct drm_device *dev, u32 iia),
++          TP_ARGS(dev, iia),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u32, iia)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->iia = iia;
++                         ),
++
++          TP_printk("dev=%u, IIA 0x%08x",
++                    __entry->dev,
++                    __entry->iia)
++);
++
+ TRACE_EVENT(v3d_submit_tfu,
+           TP_PROTO(struct drm_device *dev,
+                    uint64_t seqno),
diff --git a/target/linux/brcm2708/patches-4.19/950-0493-drm-v3d-Drop-the-dev-argument-to-lock-unlock-of-BO-r.patch b/target/linux/brcm2708/patches-4.19/950-0493-drm-v3d-Drop-the-dev-argument-to-lock-unlock-of-BO-r.patch
deleted file mode 100644 (file)
index e39c191..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From c95a4208ef87c56349d35480e68304562c7612bd Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 28 Nov 2018 15:09:26 -0800
-Subject: [PATCH] drm/v3d: Drop the "dev" argument to lock/unlock of BO
- reservations.
-
-They were unused, as Dave Emett noticed in TFU review.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Cc: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181128230927.10951-2-eric@anholt.net
-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-(cherry picked from commit e14a07fc4b961a75f6c275d6bd670ba54fbdae14)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 20 +++++++++-----------
- 1 file changed, 9 insertions(+), 11 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -219,8 +219,7 @@ v3d_attach_object_fences(struct v3d_bo *
- }
- static void
--v3d_unlock_bo_reservations(struct drm_device *dev,
--                         struct v3d_bo **bos,
-+v3d_unlock_bo_reservations(struct v3d_bo **bos,
-                          int bo_count,
-                          struct ww_acquire_ctx *acquire_ctx)
- {
-@@ -240,8 +239,7 @@ v3d_unlock_bo_reservations(struct drm_de
-  * to v3d, so we don't attach dma-buf fences to them.
-  */
- static int
--v3d_lock_bo_reservations(struct drm_device *dev,
--                       struct v3d_bo **bos,
-+v3d_lock_bo_reservations(struct v3d_bo **bos,
-                        int bo_count,
-                        struct ww_acquire_ctx *acquire_ctx)
- {
-@@ -298,7 +296,7 @@ retry:
-       for (i = 0; i < bo_count; i++) {
-               ret = reservation_object_reserve_shared(bos[i]->resv);
-               if (ret) {
--                      v3d_unlock_bo_reservations(dev, bos, bo_count,
-+                      v3d_unlock_bo_reservations(bos, bo_count,
-                                                  acquire_ctx);
-                       return ret;
-               }
-@@ -566,7 +564,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       if (ret)
-               goto fail;
--      ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
-+      ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
-                                      &acquire_ctx);
-       if (ret)
-               goto fail;
-@@ -604,7 +602,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       v3d_attach_object_fences(exec->bo, exec->bo_count,
-                                exec->render_done_fence);
--      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
-+      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
-       /* Update the return sync object for the */
-       sync_out = drm_syncobj_find(file_priv, args->out_sync);
-@@ -620,7 +618,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
- fail_unreserve:
-       mutex_unlock(&v3d->sched_lock);
--      v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
-+      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
- fail:
-       v3d_exec_put(exec);
-@@ -691,7 +689,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       }
-       spin_unlock(&file_priv->table_lock);
--      ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+      ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
-       if (ret)
-               goto fail;
-@@ -710,7 +708,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
--      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
-       /* Update the return sync object */
-       sync_out = drm_syncobj_find(file_priv, args->out_sync);
-@@ -726,7 +724,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
- fail_unreserve:
-       mutex_unlock(&v3d->sched_lock);
--      v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
- fail:
-       v3d_tfu_job_put(job);
diff --git a/target/linux/brcm2708/patches-4.19/950-0494-drm-v3d-Add-missing-fence-timeline-name-for-TFU.patch b/target/linux/brcm2708/patches-4.19/950-0494-drm-v3d-Add-missing-fence-timeline-name-for-TFU.patch
deleted file mode 100644 (file)
index d56e045..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 49281ec9b6f3c7bda94c798133dd35d50eb69649 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 30 Nov 2018 16:57:59 -0800
-Subject: [PATCH] drm/v3d: Add missing fence timeline name for TFU.
-
-We shouldn't be returning v3d-render for our new queue.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 83d5139982db ("drm/v3d: Add support for submitting jobs to the TFU.")
-Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-6-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit db176f6ba1da39ad0016c77b9775a6bb3d0ce88a)
----
- drivers/gpu/drm/v3d/v3d_fence.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_fence.c
-+++ b/drivers/gpu/drm/v3d/v3d_fence.c
-@@ -29,10 +29,16 @@ static const char *v3d_fence_get_timelin
- {
-       struct v3d_fence *f = to_v3d_fence(fence);
--      if (f->queue == V3D_BIN)
-+      switch (f->queue) {
-+      case V3D_BIN:
-               return "v3d-bin";
--      else
-+      case V3D_RENDER:
-               return "v3d-render";
-+      case V3D_TFU:
-+              return "v3d-tfu";
-+      default:
-+              return NULL;
-+      }
- }
- const struct dma_fence_ops v3d_fence_ops = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0494-drm-v3d-Drop-unused-v3d_flush_caches.patch b/target/linux/brcm2708/patches-4.19/950-0494-drm-v3d-Drop-unused-v3d_flush_caches.patch
new file mode 100644 (file)
index 0000000..aba98eb
--- /dev/null
@@ -0,0 +1,64 @@
+From 065c8947cb7c40bfb3e76dcbb9d901b5e8fe0ea4 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:34 -0800
+Subject: [PATCH] drm/v3d: Drop unused v3d_flush_caches().
+
+Now that I've specified how the end-of-pipeline flushing should work,
+we're never going to use this function.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-2-eric@anholt.net
+(cherry picked from commit 2aa34fd5c7754824cf5488b61ac644f30d3c5c85)
+---
+ drivers/gpu/drm/v3d/v3d_drv.h |  1 -
+ drivers/gpu/drm/v3d/v3d_gem.c | 21 ---------------------
+ 2 files changed, 22 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -308,7 +308,6 @@ void v3d_exec_put(struct v3d_exec_info *
+ void v3d_tfu_job_put(struct v3d_tfu_job *exec);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
+-void v3d_flush_caches(struct v3d_dev *v3d);
+ /* v3d_irq.c */
+ int v3d_irq_init(struct v3d_dev *v3d);
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -175,20 +175,6 @@ v3d_invalidate_slices(struct v3d_dev *v3
+                      V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC));
+ }
+-/* Invalidates texture L2 cachelines */
+-static void
+-v3d_invalidate_l2t(struct v3d_dev *v3d, int core)
+-{
+-      V3D_CORE_WRITE(core,
+-                     V3D_CTL_L2TCACTL,
+-                     V3D_L2TCACTL_L2TFLS |
+-                     V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAR, V3D_L2TCACTL_FLM));
+-      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
+-                     V3D_L2TCACTL_L2TFLS), 100)) {
+-              DRM_ERROR("Timeout waiting for L2T invalidate\n");
+-      }
+-}
+-
+ void
+ v3d_invalidate_caches(struct v3d_dev *v3d)
+ {
+@@ -199,13 +185,6 @@ v3d_invalidate_caches(struct v3d_dev *v3
+       v3d_flush_l2t(v3d, 0);
+ }
+-void
+-v3d_flush_caches(struct v3d_dev *v3d)
+-{
+-      v3d_invalidate_l1td(v3d, 0);
+-      v3d_invalidate_l2t(v3d, 0);
+-}
+-
+ static void
+ v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
+                        struct dma_fence *fence)
diff --git a/target/linux/brcm2708/patches-4.19/950-0495-drm-v3d-Add-more-tracepoints-for-V3D-GPU-rendering.patch b/target/linux/brcm2708/patches-4.19/950-0495-drm-v3d-Add-more-tracepoints-for-V3D-GPU-rendering.patch
deleted file mode 100644 (file)
index 0b54645..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-From 128adbc39c9826ca137ca3627cff17644e786fdb Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 30 Nov 2018 16:57:58 -0800
-Subject: [PATCH] drm/v3d: Add more tracepoints for V3D GPU rendering.
-
-The core scheduler tells us when the job is pushed to the scheduler's
-queue, and I had the job_run functions saying when they actually queue
-the job to the hardware.  By adding tracepoints for the very top of
-the ioctls and the IRQs signaling job completion, "perf record -a -e
-v3d:.\* -e gpu_scheduler:.\* <job>; perf script" gets you a pretty
-decent timeline.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-5-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit 55a9b74846ed5e6219c7d81a8e1bf96f25d8ad5e)
----
- drivers/gpu/drm/v3d/v3d_gem.c   |   4 ++
- drivers/gpu/drm/v3d/v3d_irq.c   |  19 +++++-
- drivers/gpu/drm/v3d/v3d_trace.h | 101 ++++++++++++++++++++++++++++++++
- 3 files changed, 121 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -521,6 +521,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       struct drm_syncobj *sync_out;
-       int ret = 0;
-+      trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
-+
-       if (args->pad != 0) {
-               DRM_INFO("pad must be zero: %d\n", args->pad);
-               return -EINVAL;
-@@ -648,6 +650,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       int ret = 0;
-       int bo_count;
-+      trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
-+
-       job = kcalloc(1, sizeof(*job), GFP_KERNEL);
-       if (!job)
-               return -ENOMEM;
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -15,6 +15,7 @@
- #include "v3d_drv.h"
- #include "v3d_regs.h"
-+#include "v3d_trace.h"
- #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM |        \
-                            V3D_INT_FLDONE |   \
-@@ -88,12 +89,20 @@ v3d_irq(int irq, void *arg)
-       }
-       if (intsts & V3D_INT_FLDONE) {
--              dma_fence_signal(v3d->bin_job->bin.done_fence);
-+              struct v3d_fence *fence =
-+                      to_v3d_fence(v3d->bin_job->bin.done_fence);
-+
-+              trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
-+              dma_fence_signal(&fence->base);
-               status = IRQ_HANDLED;
-       }
-       if (intsts & V3D_INT_FRDONE) {
--              dma_fence_signal(v3d->render_job->render.done_fence);
-+              struct v3d_fence *fence =
-+                      to_v3d_fence(v3d->render_job->render.done_fence);
-+
-+              trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
-+              dma_fence_signal(&fence->base);
-               status = IRQ_HANDLED;
-       }
-@@ -119,7 +128,11 @@ v3d_hub_irq(int irq, void *arg)
-       V3D_WRITE(V3D_HUB_INT_CLR, intsts);
-       if (intsts & V3D_HUB_INT_TFUC) {
--              dma_fence_signal(v3d->tfu_job->done_fence);
-+              struct v3d_fence *fence =
-+                      to_v3d_fence(v3d->tfu_job->done_fence);
-+
-+              trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
-+              dma_fence_signal(&fence->base);
-               status = IRQ_HANDLED;
-       }
---- a/drivers/gpu/drm/v3d/v3d_trace.h
-+++ b/drivers/gpu/drm/v3d/v3d_trace.h
-@@ -12,6 +12,28 @@
- #define TRACE_SYSTEM v3d
- #define TRACE_INCLUDE_FILE v3d_trace
-+TRACE_EVENT(v3d_submit_cl_ioctl,
-+          TP_PROTO(struct drm_device *dev, u32 ct1qba, u32 ct1qea),
-+          TP_ARGS(dev, ct1qba, ct1qea),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u32, ct1qba)
-+                           __field(u32, ct1qea)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->ct1qba = ct1qba;
-+                         __entry->ct1qea = ct1qea;
-+                         ),
-+
-+          TP_printk("dev=%u, RCL 0x%08x..0x%08x",
-+                    __entry->dev,
-+                    __entry->ct1qba,
-+                    __entry->ct1qea)
-+);
-+
- TRACE_EVENT(v3d_submit_cl,
-           TP_PROTO(struct drm_device *dev, bool is_render,
-                    uint64_t seqno,
-@@ -42,6 +64,85 @@ TRACE_EVENT(v3d_submit_cl,
-                     __entry->ctnqea)
- );
-+TRACE_EVENT(v3d_bcl_irq,
-+          TP_PROTO(struct drm_device *dev,
-+                   uint64_t seqno),
-+          TP_ARGS(dev, seqno),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u64, seqno)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->seqno = seqno;
-+                         ),
-+
-+          TP_printk("dev=%u, seqno=%llu",
-+                    __entry->dev,
-+                    __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_rcl_irq,
-+          TP_PROTO(struct drm_device *dev,
-+                   uint64_t seqno),
-+          TP_ARGS(dev, seqno),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u64, seqno)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->seqno = seqno;
-+                         ),
-+
-+          TP_printk("dev=%u, seqno=%llu",
-+                    __entry->dev,
-+                    __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_tfu_irq,
-+          TP_PROTO(struct drm_device *dev,
-+                   uint64_t seqno),
-+          TP_ARGS(dev, seqno),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u64, seqno)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->seqno = seqno;
-+                         ),
-+
-+          TP_printk("dev=%u, seqno=%llu",
-+                    __entry->dev,
-+                    __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_submit_tfu_ioctl,
-+          TP_PROTO(struct drm_device *dev, u32 iia),
-+          TP_ARGS(dev, iia),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u32, iia)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->iia = iia;
-+                         ),
-+
-+          TP_printk("dev=%u, IIA 0x%08x",
-+                    __entry->dev,
-+                    __entry->iia)
-+);
-+
- TRACE_EVENT(v3d_submit_tfu,
-           TP_PROTO(struct drm_device *dev,
-                    uint64_t seqno),
diff --git a/target/linux/brcm2708/patches-4.19/950-0495-drm-v3d-Don-t-bother-flushing-L1TD-at-job-start.patch b/target/linux/brcm2708/patches-4.19/950-0495-drm-v3d-Don-t-bother-flushing-L1TD-at-job-start.patch
new file mode 100644 (file)
index 0000000..164e29f
--- /dev/null
@@ -0,0 +1,43 @@
+From 4a6410a53059d6505680b70fc438b7cfbf8939ca Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:35 -0800
+Subject: [PATCH] drm/v3d: Don't bother flushing L1TD at job start.
+
+This is the write combiner for TMU writes.  You're supposed to flush
+that at job end if you had dirtied any cachelines.  Flushing it at job
+start then doesn't make any sense.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-3-eric@anholt.net
+(cherry picked from commit 2e6dc3bd80478212e84addf1cafd6ec60674b884)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -139,22 +139,10 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
+                      V3D_L2CACTL_L2CENA);
+ }
+-static void
+-v3d_invalidate_l1td(struct v3d_dev *v3d, int core)
+-{
+-      V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
+-      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
+-                     V3D_L2TCACTL_L2TFLS), 100)) {
+-              DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
+-      }
+-}
+-
+ /* Invalidates texture L2 cachelines */
+ static void
+ v3d_flush_l2t(struct v3d_dev *v3d, int core)
+ {
+-      v3d_invalidate_l1td(v3d, core);
+-
+       V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
+                      V3D_L2TCACTL_L2TFLS |
+                      V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
diff --git a/target/linux/brcm2708/patches-4.19/950-0496-drm-v3d-Drop-the-wait-for-L2T-flush-to-complete.patch b/target/linux/brcm2708/patches-4.19/950-0496-drm-v3d-Drop-the-wait-for-L2T-flush-to-complete.patch
new file mode 100644 (file)
index 0000000..5a72f9c
--- /dev/null
@@ -0,0 +1,41 @@
+From 9d8fa62500ae52348d36766e70b49c7508addaf3 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:36 -0800
+Subject: [PATCH] drm/v3d: Drop the wait for L2T flush to complete.
+
+According to Dave, once you've started an L2T flush, all L2T accesses
+will be blocked until the flush completes.  This fixes a consistent
+3-4ms stall between the ioctl and running the job, and 3DMMES Taiji
+goes from 27fps to 110fps.
+
+v2: Leave a note about why we don't need to wait for completion.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-4-eric@anholt.net
+(cherry picked from commit 51c1b6f9eb3dbdec91b0e3c89f623e634c996bbb)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -143,13 +143,13 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
+ static void
+ v3d_flush_l2t(struct v3d_dev *v3d, int core)
+ {
++      /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
++       * need to wait for completion before dispatching the job --
++       * L2T accesses will be stalled until the flush has completed.
++       */
+       V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
+                      V3D_L2TCACTL_L2TFLS |
+                      V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
+-      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
+-                     V3D_L2TCACTL_L2TFLS), 100)) {
+-              DRM_ERROR("Timeout waiting for L2T flush\n");
+-      }
+ }
+ /* Invalidates the slice caches.  These are read-only caches. */
diff --git a/target/linux/brcm2708/patches-4.19/950-0496-drm-v3d-Drop-unused-v3d_flush_caches.patch b/target/linux/brcm2708/patches-4.19/950-0496-drm-v3d-Drop-unused-v3d_flush_caches.patch
deleted file mode 100644 (file)
index aba98eb..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From 065c8947cb7c40bfb3e76dcbb9d901b5e8fe0ea4 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:34 -0800
-Subject: [PATCH] drm/v3d: Drop unused v3d_flush_caches().
-
-Now that I've specified how the end-of-pipeline flushing should work,
-we're never going to use this function.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-2-eric@anholt.net
-(cherry picked from commit 2aa34fd5c7754824cf5488b61ac644f30d3c5c85)
----
- drivers/gpu/drm/v3d/v3d_drv.h |  1 -
- drivers/gpu/drm/v3d/v3d_gem.c | 21 ---------------------
- 2 files changed, 22 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -308,7 +308,6 @@ void v3d_exec_put(struct v3d_exec_info *
- void v3d_tfu_job_put(struct v3d_tfu_job *exec);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
--void v3d_flush_caches(struct v3d_dev *v3d);
- /* v3d_irq.c */
- int v3d_irq_init(struct v3d_dev *v3d);
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -175,20 +175,6 @@ v3d_invalidate_slices(struct v3d_dev *v3
-                      V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC));
- }
--/* Invalidates texture L2 cachelines */
--static void
--v3d_invalidate_l2t(struct v3d_dev *v3d, int core)
--{
--      V3D_CORE_WRITE(core,
--                     V3D_CTL_L2TCACTL,
--                     V3D_L2TCACTL_L2TFLS |
--                     V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAR, V3D_L2TCACTL_FLM));
--      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
--                     V3D_L2TCACTL_L2TFLS), 100)) {
--              DRM_ERROR("Timeout waiting for L2T invalidate\n");
--      }
--}
--
- void
- v3d_invalidate_caches(struct v3d_dev *v3d)
- {
-@@ -199,13 +185,6 @@ v3d_invalidate_caches(struct v3d_dev *v3
-       v3d_flush_l2t(v3d, 0);
- }
--void
--v3d_flush_caches(struct v3d_dev *v3d)
--{
--      v3d_invalidate_l1td(v3d, 0);
--      v3d_invalidate_l2t(v3d, 0);
--}
--
- static void
- v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
-                        struct dma_fence *fence)
diff --git a/target/linux/brcm2708/patches-4.19/950-0497-drm-v3d-Don-t-bother-flushing-L1TD-at-job-start.patch b/target/linux/brcm2708/patches-4.19/950-0497-drm-v3d-Don-t-bother-flushing-L1TD-at-job-start.patch
deleted file mode 100644 (file)
index 164e29f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-From 4a6410a53059d6505680b70fc438b7cfbf8939ca Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:35 -0800
-Subject: [PATCH] drm/v3d: Don't bother flushing L1TD at job start.
-
-This is the write combiner for TMU writes.  You're supposed to flush
-that at job end if you had dirtied any cachelines.  Flushing it at job
-start then doesn't make any sense.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-3-eric@anholt.net
-(cherry picked from commit 2e6dc3bd80478212e84addf1cafd6ec60674b884)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 12 ------------
- 1 file changed, 12 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -139,22 +139,10 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
-                      V3D_L2CACTL_L2CENA);
- }
--static void
--v3d_invalidate_l1td(struct v3d_dev *v3d, int core)
--{
--      V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
--      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
--                     V3D_L2TCACTL_L2TFLS), 100)) {
--              DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
--      }
--}
--
- /* Invalidates texture L2 cachelines */
- static void
- v3d_flush_l2t(struct v3d_dev *v3d, int core)
- {
--      v3d_invalidate_l1td(v3d, core);
--
-       V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
-                      V3D_L2TCACTL_L2TFLS |
-                      V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
diff --git a/target/linux/brcm2708/patches-4.19/950-0497-drm-v3d-Stop-trying-to-flush-L2C-on-V3D-3.3.patch b/target/linux/brcm2708/patches-4.19/950-0497-drm-v3d-Stop-trying-to-flush-L2C-on-V3D-3.3.patch
new file mode 100644 (file)
index 0000000..b109477
--- /dev/null
@@ -0,0 +1,45 @@
+From abee30ca29ec11b62842934de04b5a0033bff21b Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:37 -0800
+Subject: [PATCH] drm/v3d: Stop trying to flush L2C on V3D 3.3+
+
+This cache was replaced with the slice accessing the L2T in the newer
+generations.  Noted by Dave during review.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-5-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit 7b9d2fe4350a9c12f66ad8cc78c1098226f6c3c2)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -130,10 +130,15 @@ v3d_flush_l3(struct v3d_dev *v3d)
+       }
+ }
+-/* Invalidates the (read-only) L2 cache. */
++/* Invalidates the (read-only) L2C cache.  This was the L2 cache for
++ * uniforms and instructions on V3D 3.2.
++ */
+ static void
+-v3d_invalidate_l2(struct v3d_dev *v3d, int core)
++v3d_invalidate_l2c(struct v3d_dev *v3d, int core)
+ {
++      if (v3d->ver > 32)
++              return;
++
+       V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
+                      V3D_L2CACTL_L2CCLR |
+                      V3D_L2CACTL_L2CENA);
+@@ -168,7 +173,7 @@ v3d_invalidate_caches(struct v3d_dev *v3
+ {
+       v3d_flush_l3(v3d);
+-      v3d_invalidate_l2(v3d, 0);
++      v3d_invalidate_l2c(v3d, 0);
+       v3d_invalidate_slices(v3d, 0);
+       v3d_flush_l2t(v3d, 0);
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0498-drm-v3d-Drop-the-wait-for-L2T-flush-to-complete.patch b/target/linux/brcm2708/patches-4.19/950-0498-drm-v3d-Drop-the-wait-for-L2T-flush-to-complete.patch
deleted file mode 100644 (file)
index 5a72f9c..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From 9d8fa62500ae52348d36766e70b49c7508addaf3 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:36 -0800
-Subject: [PATCH] drm/v3d: Drop the wait for L2T flush to complete.
-
-According to Dave, once you've started an L2T flush, all L2T accesses
-will be blocked until the flush completes.  This fixes a consistent
-3-4ms stall between the ioctl and running the job, and 3DMMES Taiji
-goes from 27fps to 110fps.
-
-v2: Leave a note about why we don't need to wait for completion.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-4-eric@anholt.net
-(cherry picked from commit 51c1b6f9eb3dbdec91b0e3c89f623e634c996bbb)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -143,13 +143,13 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
- static void
- v3d_flush_l2t(struct v3d_dev *v3d, int core)
- {
-+      /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
-+       * need to wait for completion before dispatching the job --
-+       * L2T accesses will be stalled until the flush has completed.
-+       */
-       V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
-                      V3D_L2TCACTL_L2TFLS |
-                      V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
--      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
--                     V3D_L2TCACTL_L2TFLS), 100)) {
--              DRM_ERROR("Timeout waiting for L2T flush\n");
--      }
- }
- /* Invalidates the slice caches.  These are read-only caches. */
diff --git a/target/linux/brcm2708/patches-4.19/950-0498-drm-v3d-Invalidate-the-caches-from-the-outside-in.patch b/target/linux/brcm2708/patches-4.19/950-0498-drm-v3d-Invalidate-the-caches-from-the-outside-in.patch
new file mode 100644 (file)
index 0000000..7682ab6
--- /dev/null
@@ -0,0 +1,36 @@
+From 514653cd51ff6bc14268dc0f98ebb37daa8f0e88 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:38 -0800
+Subject: [PATCH] drm/v3d: Invalidate the caches from the outside in.
+
+This would be a fairly obscure race, but let's make sure we don't ever
+lose it.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-6-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit aa5beec32e8b78bfcf621e3c3daebfb1644b6365)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -171,11 +171,15 @@ v3d_invalidate_slices(struct v3d_dev *v3
+ void
+ v3d_invalidate_caches(struct v3d_dev *v3d)
+ {
++      /* Invalidate the caches from the outside in.  That way if
++       * another CL's concurrent use of nearby memory were to pull
++       * an invalidated cacheline back in, we wouldn't leave stale
++       * data in the inner cache.
++       */
+       v3d_flush_l3(v3d);
+-
+       v3d_invalidate_l2c(v3d, 0);
+-      v3d_invalidate_slices(v3d, 0);
+       v3d_flush_l2t(v3d, 0);
++      v3d_invalidate_slices(v3d, 0);
+ }
+ static void
diff --git a/target/linux/brcm2708/patches-4.19/950-0499-drm-v3d-Fix-BO-stats-accounting-for-dma-buf-imported.patch b/target/linux/brcm2708/patches-4.19/950-0499-drm-v3d-Fix-BO-stats-accounting-for-dma-buf-imported.patch
new file mode 100644 (file)
index 0000000..fc2b566
--- /dev/null
@@ -0,0 +1,40 @@
+From f91d0382b735a3d7711f6b160d80627cd4be54af Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 7 Feb 2019 15:26:13 -0800
+Subject: [PATCH] drm/v3d: Fix BO stats accounting for dma-buf-imported
+ buffers.
+
+We always decrement at GEM free, so make sure we increment at GEM
+creation for dma-bufs.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190207232613.24981-1-eric@anholt.net
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+(cherry picked from commit cc3f60cfd4f2752f1bad7eaa3839855c15347abc)
+---
+ drivers/gpu/drm/v3d/v3d_bo.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_bo.c
++++ b/drivers/gpu/drm/v3d/v3d_bo.c
+@@ -282,6 +282,7 @@ v3d_prime_import_sg_table(struct drm_dev
+                         struct dma_buf_attachment *attach,
+                         struct sg_table *sgt)
+ {
++      struct v3d_dev *v3d = to_v3d_dev(dev);
+       struct drm_gem_object *obj;
+       struct v3d_bo *bo;
+@@ -296,6 +297,11 @@ v3d_prime_import_sg_table(struct drm_dev
+       obj->import_attach = attach;
+       v3d_bo_get_pages(bo);
++      mutex_lock(&v3d->bo_lock);
++      v3d->bo_stats.num_allocated++;
++      v3d->bo_stats.pages_allocated += obj->size >> PAGE_SHIFT;
++      mutex_unlock(&v3d->bo_lock);
++
+       v3d_mmu_insert_ptes(bo);
+       return obj;
diff --git a/target/linux/brcm2708/patches-4.19/950-0499-drm-v3d-Stop-trying-to-flush-L2C-on-V3D-3.3.patch b/target/linux/brcm2708/patches-4.19/950-0499-drm-v3d-Stop-trying-to-flush-L2C-on-V3D-3.3.patch
deleted file mode 100644 (file)
index b109477..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From abee30ca29ec11b62842934de04b5a0033bff21b Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:37 -0800
-Subject: [PATCH] drm/v3d: Stop trying to flush L2C on V3D 3.3+
-
-This cache was replaced with the slice accessing the L2T in the newer
-generations.  Noted by Dave during review.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-5-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit 7b9d2fe4350a9c12f66ad8cc78c1098226f6c3c2)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -130,10 +130,15 @@ v3d_flush_l3(struct v3d_dev *v3d)
-       }
- }
--/* Invalidates the (read-only) L2 cache. */
-+/* Invalidates the (read-only) L2C cache.  This was the L2 cache for
-+ * uniforms and instructions on V3D 3.2.
-+ */
- static void
--v3d_invalidate_l2(struct v3d_dev *v3d, int core)
-+v3d_invalidate_l2c(struct v3d_dev *v3d, int core)
- {
-+      if (v3d->ver > 32)
-+              return;
-+
-       V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
-                      V3D_L2CACTL_L2CCLR |
-                      V3D_L2CACTL_L2CENA);
-@@ -168,7 +173,7 @@ v3d_invalidate_caches(struct v3d_dev *v3
- {
-       v3d_flush_l3(v3d);
--      v3d_invalidate_l2(v3d, 0);
-+      v3d_invalidate_l2c(v3d, 0);
-       v3d_invalidate_slices(v3d, 0);
-       v3d_flush_l2t(v3d, 0);
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0500-drm-v3d-Invalidate-the-caches-from-the-outside-in.patch b/target/linux/brcm2708/patches-4.19/950-0500-drm-v3d-Invalidate-the-caches-from-the-outside-in.patch
deleted file mode 100644 (file)
index 7682ab6..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From 514653cd51ff6bc14268dc0f98ebb37daa8f0e88 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:38 -0800
-Subject: [PATCH] drm/v3d: Invalidate the caches from the outside in.
-
-This would be a fairly obscure race, but let's make sure we don't ever
-lose it.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-6-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit aa5beec32e8b78bfcf621e3c3daebfb1644b6365)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -171,11 +171,15 @@ v3d_invalidate_slices(struct v3d_dev *v3
- void
- v3d_invalidate_caches(struct v3d_dev *v3d)
- {
-+      /* Invalidate the caches from the outside in.  That way if
-+       * another CL's concurrent use of nearby memory were to pull
-+       * an invalidated cacheline back in, we wouldn't leave stale
-+       * data in the inner cache.
-+       */
-       v3d_flush_l3(v3d);
--
-       v3d_invalidate_l2c(v3d, 0);
--      v3d_invalidate_slices(v3d, 0);
-       v3d_flush_l2t(v3d, 0);
-+      v3d_invalidate_slices(v3d, 0);
- }
- static void
diff --git a/target/linux/brcm2708/patches-4.19/950-0500-drm-v3d-Update-top-level-kerneldoc-for-the-addition-.patch b/target/linux/brcm2708/patches-4.19/950-0500-drm-v3d-Update-top-level-kerneldoc-for-the-addition-.patch
new file mode 100644 (file)
index 0000000..df8cc1a
--- /dev/null
@@ -0,0 +1,30 @@
+From 752f66d4482db75db81e5255f5071de1e47ac121 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 7 Feb 2019 12:09:58 -0800
+Subject: [PATCH] drm/v3d: Update top-level kerneldoc for the addition
+ of TFU.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190207201001.5730-1-eric@anholt.net
+Reviewed-by: Thomas Spurden <thomas.spurden@broadcom.com>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+(cherry picked from commit fd347df16d4ed2eef565344b8f16a1134bddf185)
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -7,9 +7,9 @@
+  * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
+  * For V3D 2.x support, see the VC4 driver.
+  *
+- * Currently only single-core rendering using the binner and renderer
+- * is supported.  The TFU (texture formatting unit) and V3D 4.x's CSD
+- * (compute shader dispatch) are not yet supported.
++ * Currently only single-core rendering using the binner and renderer,
++ * along with TFU (texture formatting unit) rendering is supported.
++ * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
+  */
+ #include <linux/clk.h>
diff --git a/target/linux/brcm2708/patches-4.19/950-0501-drm-v3d-Fix-BO-stats-accounting-for-dma-buf-imported.patch b/target/linux/brcm2708/patches-4.19/950-0501-drm-v3d-Fix-BO-stats-accounting-for-dma-buf-imported.patch
deleted file mode 100644 (file)
index fc2b566..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From f91d0382b735a3d7711f6b160d80627cd4be54af Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 7 Feb 2019 15:26:13 -0800
-Subject: [PATCH] drm/v3d: Fix BO stats accounting for dma-buf-imported
- buffers.
-
-We always decrement at GEM free, so make sure we increment at GEM
-creation for dma-bufs.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20190207232613.24981-1-eric@anholt.net
-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-(cherry picked from commit cc3f60cfd4f2752f1bad7eaa3839855c15347abc)
----
- drivers/gpu/drm/v3d/v3d_bo.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_bo.c
-+++ b/drivers/gpu/drm/v3d/v3d_bo.c
-@@ -282,6 +282,7 @@ v3d_prime_import_sg_table(struct drm_dev
-                         struct dma_buf_attachment *attach,
-                         struct sg_table *sgt)
- {
-+      struct v3d_dev *v3d = to_v3d_dev(dev);
-       struct drm_gem_object *obj;
-       struct v3d_bo *bo;
-@@ -296,6 +297,11 @@ v3d_prime_import_sg_table(struct drm_dev
-       obj->import_attach = attach;
-       v3d_bo_get_pages(bo);
-+      mutex_lock(&v3d->bo_lock);
-+      v3d->bo_stats.num_allocated++;
-+      v3d->bo_stats.pages_allocated += obj->size >> PAGE_SHIFT;
-+      mutex_unlock(&v3d->bo_lock);
-+
-       v3d_mmu_insert_ptes(bo);
-       return obj;
diff --git a/target/linux/brcm2708/patches-4.19/950-0501-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch b/target/linux/brcm2708/patches-4.19/950-0501-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch
new file mode 100644 (file)
index 0000000..aaeeb94
--- /dev/null
@@ -0,0 +1,22 @@
+From ec551e663ddd1be9140cc23f1eff33b8d270ed60 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 4 Mar 2019 11:59:34 -0800
+Subject: [PATCH] drm/vc4: Fix oops at boot with firmwarekms on 4.19.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -107,6 +107,9 @@ vc4_ctm_commit(struct vc4_dev *vc4, stru
+       struct vc4_ctm_state *ctm_state = to_vc4_ctm_state(vc4->ctm_manager.state);
+       struct drm_color_ctm *ctm = ctm_state->ctm;
++      if (vc4->firmware_kms)
++              return;
++
+       if (ctm_state->fifo) {
+               HVS_WRITE(SCALER_OLEDCOEF2,
+                         VC4_SET_FIELD(vc4_ctm_s31_32_to_s0_9(ctm->matrix[0]),
diff --git a/target/linux/brcm2708/patches-4.19/950-0502-drm-v3d-Add-support-for-V3D-v4.2.patch b/target/linux/brcm2708/patches-4.19/950-0502-drm-v3d-Add-support-for-V3D-v4.2.patch
new file mode 100644 (file)
index 0000000..35fc072
--- /dev/null
@@ -0,0 +1,207 @@
+From b0e7b8814e74be0559e07f737ef18cc3709d4ac4 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 4 Oct 2018 17:22:43 -0700
+Subject: [PATCH] drm/v3d: Add support for V3D v4.2.
+
+No compatible string for it yet, just the version-dependent changes.
+They've now tied the hub and the core interrupt lines into a single
+interrupt line coming out of the block.  It also turns out I made a
+mistake in modeling the V3D v3.3 and v4.1 bridge as a part of V3D
+itself -- the bridge is going away in favor of an external reset
+controller in a larger HW module.
+
+v2: Use consistent checks for whether we're on 4.2, and fix a leak in
+    an error path.
+v3: Use more general means of determining if the current 4.2 changes
+    are in place, as apparently other platforms may switch back (noted
+    by Dave).  Update the binding doc.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ .../devicetree/bindings/gpu/brcm,bcm-v3d.txt  | 11 ++++--
+ drivers/gpu/drm/v3d/v3d_drv.c                 | 21 +++++++++---
+ drivers/gpu/drm/v3d/v3d_drv.h                 |  2 ++
+ drivers/gpu/drm/v3d/v3d_gem.c                 | 12 ++++++-
+ drivers/gpu/drm/v3d/v3d_irq.c                 | 34 ++++++++++++++-----
+ 5 files changed, 63 insertions(+), 17 deletions(-)
+
+--- a/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
++++ b/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
+@@ -6,15 +6,20 @@ For V3D 2.x, see brcm,bcm-vc4.txt.
+ Required properties:
+ - compatible: Should be "brcm,7268-v3d" or "brcm,7278-v3d"
+ - reg:                Physical base addresses and lengths of the register areas
+-- reg-names:  Names for the register areas.  The "hub", "bridge", and "core0"
++- reg-names:  Names for the register areas.  The "hub" and "core0"
+                 register areas are always required.  The "gca" register area
+-                is required if the GCA cache controller is present.
++                is required if the GCA cache controller is present.  The
++                "bridge" register area is required if an external reset
++                controller is not present.
+ - interrupts: The interrupt numbers.  The first interrupt is for the hub,
+-                while the following interrupts are for the cores.
++                while the following interrupts are separate interrupt lines
++                for the cores (if they don't share the hub's interrupt).
+                 See bindings/interrupt-controller/interrupts.txt
+ Optional properties:
+ - clocks:     The core clock the unit runs on
++- resets:     The reset line for v3d, if not using a mapping of the bridge
++                See bindings/reset/reset.txt
+ v3d {
+       compatible = "brcm,7268-v3d";
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -19,6 +19,7 @@
+ #include <linux/of_platform.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/reset.h>
+ #include <drm/drm_fb_cma_helper.h>
+ #include <drm/drm_fb_helper.h>
+@@ -265,10 +266,6 @@ static int v3d_platform_drm_probe(struct
+       v3d->pdev = pdev;
+       drm = &v3d->drm;
+-      ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
+-      if (ret)
+-              goto dev_free;
+-
+       ret = map_regs(v3d, &v3d->hub_regs, "hub");
+       if (ret)
+               goto dev_free;
+@@ -283,6 +280,22 @@ static int v3d_platform_drm_probe(struct
+       v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES);
+       WARN_ON(v3d->cores > 1); /* multicore not yet implemented */
++      v3d->reset = devm_reset_control_get_exclusive(dev, NULL);
++      if (IS_ERR(v3d->reset)) {
++              ret = PTR_ERR(v3d->reset);
++
++              if (ret == -EPROBE_DEFER)
++                      goto dev_free;
++
++              v3d->reset = NULL;
++              ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
++              if (ret) {
++                      dev_err(dev,
++                              "Failed to get reset control or bridge regs\n");
++                      goto dev_free;
++              }
++      }
++
+       if (v3d->ver < 41) {
+               ret = map_regs(v3d, &v3d->gca_regs, "gca");
+               if (ret)
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -34,6 +34,7 @@ struct v3d_dev {
+        * and revision.
+        */
+       int ver;
++      bool single_irq_line;
+       struct device *dev;
+       struct platform_device *pdev;
+@@ -42,6 +43,7 @@ struct v3d_dev {
+       void __iomem *bridge_regs;
+       void __iomem *gca_regs;
+       struct clk *clk;
++      struct reset_control *reset;
+       /* Virtual and DMA addresses of the single shared page table. */
+       volatile u32 *pt;
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -6,6 +6,7 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/reset.h>
+ #include <linux/device.h>
+ #include <linux/io.h>
+ #include <linux/sched/signal.h>
+@@ -69,7 +70,7 @@ v3d_idle_gca(struct v3d_dev *v3d)
+ }
+ static void
+-v3d_reset_v3d(struct v3d_dev *v3d)
++v3d_reset_by_bridge(struct v3d_dev *v3d)
+ {
+       int version = V3D_BRIDGE_READ(V3D_TOP_GR_BRIDGE_REVISION);
+@@ -89,6 +90,15 @@ v3d_reset_v3d(struct v3d_dev *v3d)
+                                V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT);
+               V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1, 0);
+       }
++}
++
++static void
++v3d_reset_v3d(struct v3d_dev *v3d)
++{
++      if (v3d->reset)
++              reset_control_reset(v3d->reset);
++      else
++              v3d_reset_by_bridge(v3d);
+       v3d_init_hw_state(v3d);
+ }
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -27,6 +27,9 @@
+                           V3D_HUB_INT_MMU_CAP |       \
+                           V3D_HUB_INT_TFUC))
++static irqreturn_t
++v3d_hub_irq(int irq, void *arg);
++
+ static void
+ v3d_overflow_mem_work(struct work_struct *work)
+ {
+@@ -112,6 +115,12 @@ v3d_irq(int irq, void *arg)
+       if (intsts & V3D_INT_GMPV)
+               dev_err(v3d->dev, "GMP violation\n");
++      /* V3D 4.2 wires the hub and core IRQs together, so if we &
++       * didn't see the common one then check hub for MMU IRQs.
++       */
++      if (v3d->single_irq_line && status == IRQ_NONE)
++              return v3d_hub_irq(irq, arg);
++
+       return status;
+ }
+@@ -170,15 +179,22 @@ v3d_irq_init(struct v3d_dev *v3d)
+               V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
+       V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
+-      ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
+-                             v3d_hub_irq, IRQF_SHARED,
+-                             "v3d_hub", v3d);
+-      if (ret)
+-              goto fail;
+-
+-      ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
+-                             v3d_irq, IRQF_SHARED,
+-                             "v3d_core0", v3d);
++      if (platform_get_irq(v3d->pdev, 1) < 0) {
++              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
++                                     v3d_irq, IRQF_SHARED,
++                                     "v3d", v3d);
++              v3d->single_irq_line = true;
++      } else {
++              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
++                                     v3d_hub_irq, IRQF_SHARED,
++                                     "v3d_hub", v3d);
++              if (ret)
++                      goto fail;
++
++              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
++                                     v3d_irq, IRQF_SHARED,
++                                     "v3d_core0", v3d);
++      }
+       if (ret)
+               goto fail;
diff --git a/target/linux/brcm2708/patches-4.19/950-0502-drm-v3d-Update-top-level-kerneldoc-for-the-addition-.patch b/target/linux/brcm2708/patches-4.19/950-0502-drm-v3d-Update-top-level-kerneldoc-for-the-addition-.patch
deleted file mode 100644 (file)
index df8cc1a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 752f66d4482db75db81e5255f5071de1e47ac121 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 7 Feb 2019 12:09:58 -0800
-Subject: [PATCH] drm/v3d: Update top-level kerneldoc for the addition
- of TFU.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20190207201001.5730-1-eric@anholt.net
-Reviewed-by: Thomas Spurden <thomas.spurden@broadcom.com>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-(cherry picked from commit fd347df16d4ed2eef565344b8f16a1134bddf185)
----
- drivers/gpu/drm/v3d/v3d_drv.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -7,9 +7,9 @@
-  * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
-  * For V3D 2.x support, see the VC4 driver.
-  *
-- * Currently only single-core rendering using the binner and renderer
-- * is supported.  The TFU (texture formatting unit) and V3D 4.x's CSD
-- * (compute shader dispatch) are not yet supported.
-+ * Currently only single-core rendering using the binner and renderer,
-+ * along with TFU (texture formatting unit) rendering is supported.
-+ * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
-  */
- #include <linux/clk.h>
diff --git a/target/linux/brcm2708/patches-4.19/950-0503-drm-v3d-Don-t-try-to-set-OVRTMUOUT-on-V3D-4.x.patch b/target/linux/brcm2708/patches-4.19/950-0503-drm-v3d-Don-t-try-to-set-OVRTMUOUT-on-V3D-4.x.patch
new file mode 100644 (file)
index 0000000..a6d0d26
--- /dev/null
@@ -0,0 +1,42 @@
+From 8011a92f6eabd682e62e268bcd80b45ce3f06af4 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 16 Oct 2018 10:13:41 -0700
+Subject: [PATCH] drm/v3d: Don't try to set OVRTMUOUT on V3D 4.x.
+
+The old field is gone and the register now has a different field,
+QRMAXCNT for how many TMU requests get serviced before thread switch.
+We were accidentally reducing it from its default of 0x3 (4 requests)
+to 0x0 (1).
+
+v2: Skip setting the reg at all on 4.x, instead of trying to update
+    only the old field.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_gem.c  | 3 ++-
+ drivers/gpu/drm/v3d/v3d_regs.h | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -25,7 +25,8 @@ v3d_init_core(struct v3d_dev *v3d, int c
+        * type.  If you want the default behavior, you can still put
+        * "2" in the indirect texture state's output_type field.
+        */
+-      V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
++      if (v3d->ver < 40)
++              V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
+       /* Whenever we flush the L2T cache, we always want to flush
+        * the whole thing.
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -216,6 +216,8 @@
+ # define V3D_IDENT2_BCG_INT                            BIT(28)
+ #define V3D_CTL_MISCCFG                                0x00018
++# define V3D_CTL_MISCCFG_QRMAXCNT_MASK                 V3D_MASK(3, 1)
++# define V3D_CTL_MISCCFG_QRMAXCNT_SHIFT                1
+ # define V3D_MISCCFG_OVRTMUOUT                         BIT(0)
+ #define V3D_CTL_L2CACTL                                0x00020
diff --git a/target/linux/brcm2708/patches-4.19/950-0503-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch b/target/linux/brcm2708/patches-4.19/950-0503-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch
deleted file mode 100644 (file)
index aaeeb94..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-From ec551e663ddd1be9140cc23f1eff33b8d270ed60 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 4 Mar 2019 11:59:34 -0800
-Subject: [PATCH] drm/vc4: Fix oops at boot with firmwarekms on 4.19.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -107,6 +107,9 @@ vc4_ctm_commit(struct vc4_dev *vc4, stru
-       struct vc4_ctm_state *ctm_state = to_vc4_ctm_state(vc4->ctm_manager.state);
-       struct drm_color_ctm *ctm = ctm_state->ctm;
-+      if (vc4->firmware_kms)
-+              return;
-+
-       if (ctm_state->fifo) {
-               HVS_WRITE(SCALER_OLEDCOEF2,
-                         VC4_SET_FIELD(vc4_ctm_s31_32_to_s0_9(ctm->matrix[0]),
diff --git a/target/linux/brcm2708/patches-4.19/950-0504-drm-v3d-Add-support-for-V3D-v4.2.patch b/target/linux/brcm2708/patches-4.19/950-0504-drm-v3d-Add-support-for-V3D-v4.2.patch
deleted file mode 100644 (file)
index 35fc072..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-From b0e7b8814e74be0559e07f737ef18cc3709d4ac4 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 4 Oct 2018 17:22:43 -0700
-Subject: [PATCH] drm/v3d: Add support for V3D v4.2.
-
-No compatible string for it yet, just the version-dependent changes.
-They've now tied the hub and the core interrupt lines into a single
-interrupt line coming out of the block.  It also turns out I made a
-mistake in modeling the V3D v3.3 and v4.1 bridge as a part of V3D
-itself -- the bridge is going away in favor of an external reset
-controller in a larger HW module.
-
-v2: Use consistent checks for whether we're on 4.2, and fix a leak in
-    an error path.
-v3: Use more general means of determining if the current 4.2 changes
-    are in place, as apparently other platforms may switch back (noted
-    by Dave).  Update the binding doc.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- .../devicetree/bindings/gpu/brcm,bcm-v3d.txt  | 11 ++++--
- drivers/gpu/drm/v3d/v3d_drv.c                 | 21 +++++++++---
- drivers/gpu/drm/v3d/v3d_drv.h                 |  2 ++
- drivers/gpu/drm/v3d/v3d_gem.c                 | 12 ++++++-
- drivers/gpu/drm/v3d/v3d_irq.c                 | 34 ++++++++++++++-----
- 5 files changed, 63 insertions(+), 17 deletions(-)
-
---- a/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
-+++ b/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
-@@ -6,15 +6,20 @@ For V3D 2.x, see brcm,bcm-vc4.txt.
- Required properties:
- - compatible: Should be "brcm,7268-v3d" or "brcm,7278-v3d"
- - reg:                Physical base addresses and lengths of the register areas
--- reg-names:  Names for the register areas.  The "hub", "bridge", and "core0"
-+- reg-names:  Names for the register areas.  The "hub" and "core0"
-                 register areas are always required.  The "gca" register area
--                is required if the GCA cache controller is present.
-+                is required if the GCA cache controller is present.  The
-+                "bridge" register area is required if an external reset
-+                controller is not present.
- - interrupts: The interrupt numbers.  The first interrupt is for the hub,
--                while the following interrupts are for the cores.
-+                while the following interrupts are separate interrupt lines
-+                for the cores (if they don't share the hub's interrupt).
-                 See bindings/interrupt-controller/interrupts.txt
- Optional properties:
- - clocks:     The core clock the unit runs on
-+- resets:     The reset line for v3d, if not using a mapping of the bridge
-+                See bindings/reset/reset.txt
- v3d {
-       compatible = "brcm,7268-v3d";
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -19,6 +19,7 @@
- #include <linux/of_platform.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
-+#include <linux/reset.h>
- #include <drm/drm_fb_cma_helper.h>
- #include <drm/drm_fb_helper.h>
-@@ -265,10 +266,6 @@ static int v3d_platform_drm_probe(struct
-       v3d->pdev = pdev;
-       drm = &v3d->drm;
--      ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
--      if (ret)
--              goto dev_free;
--
-       ret = map_regs(v3d, &v3d->hub_regs, "hub");
-       if (ret)
-               goto dev_free;
-@@ -283,6 +280,22 @@ static int v3d_platform_drm_probe(struct
-       v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES);
-       WARN_ON(v3d->cores > 1); /* multicore not yet implemented */
-+      v3d->reset = devm_reset_control_get_exclusive(dev, NULL);
-+      if (IS_ERR(v3d->reset)) {
-+              ret = PTR_ERR(v3d->reset);
-+
-+              if (ret == -EPROBE_DEFER)
-+                      goto dev_free;
-+
-+              v3d->reset = NULL;
-+              ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
-+              if (ret) {
-+                      dev_err(dev,
-+                              "Failed to get reset control or bridge regs\n");
-+                      goto dev_free;
-+              }
-+      }
-+
-       if (v3d->ver < 41) {
-               ret = map_regs(v3d, &v3d->gca_regs, "gca");
-               if (ret)
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -34,6 +34,7 @@ struct v3d_dev {
-        * and revision.
-        */
-       int ver;
-+      bool single_irq_line;
-       struct device *dev;
-       struct platform_device *pdev;
-@@ -42,6 +43,7 @@ struct v3d_dev {
-       void __iomem *bridge_regs;
-       void __iomem *gca_regs;
-       struct clk *clk;
-+      struct reset_control *reset;
-       /* Virtual and DMA addresses of the single shared page table. */
-       volatile u32 *pt;
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -6,6 +6,7 @@
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
-+#include <linux/reset.h>
- #include <linux/device.h>
- #include <linux/io.h>
- #include <linux/sched/signal.h>
-@@ -69,7 +70,7 @@ v3d_idle_gca(struct v3d_dev *v3d)
- }
- static void
--v3d_reset_v3d(struct v3d_dev *v3d)
-+v3d_reset_by_bridge(struct v3d_dev *v3d)
- {
-       int version = V3D_BRIDGE_READ(V3D_TOP_GR_BRIDGE_REVISION);
-@@ -89,6 +90,15 @@ v3d_reset_v3d(struct v3d_dev *v3d)
-                                V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT);
-               V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1, 0);
-       }
-+}
-+
-+static void
-+v3d_reset_v3d(struct v3d_dev *v3d)
-+{
-+      if (v3d->reset)
-+              reset_control_reset(v3d->reset);
-+      else
-+              v3d_reset_by_bridge(v3d);
-       v3d_init_hw_state(v3d);
- }
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -27,6 +27,9 @@
-                           V3D_HUB_INT_MMU_CAP |       \
-                           V3D_HUB_INT_TFUC))
-+static irqreturn_t
-+v3d_hub_irq(int irq, void *arg);
-+
- static void
- v3d_overflow_mem_work(struct work_struct *work)
- {
-@@ -112,6 +115,12 @@ v3d_irq(int irq, void *arg)
-       if (intsts & V3D_INT_GMPV)
-               dev_err(v3d->dev, "GMP violation\n");
-+      /* V3D 4.2 wires the hub and core IRQs together, so if we &
-+       * didn't see the common one then check hub for MMU IRQs.
-+       */
-+      if (v3d->single_irq_line && status == IRQ_NONE)
-+              return v3d_hub_irq(irq, arg);
-+
-       return status;
- }
-@@ -170,15 +179,22 @@ v3d_irq_init(struct v3d_dev *v3d)
-               V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
-       V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
--      ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
--                             v3d_hub_irq, IRQF_SHARED,
--                             "v3d_hub", v3d);
--      if (ret)
--              goto fail;
--
--      ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
--                             v3d_irq, IRQF_SHARED,
--                             "v3d_core0", v3d);
-+      if (platform_get_irq(v3d->pdev, 1) < 0) {
-+              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-+                                     v3d_irq, IRQF_SHARED,
-+                                     "v3d", v3d);
-+              v3d->single_irq_line = true;
-+      } else {
-+              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-+                                     v3d_hub_irq, IRQF_SHARED,
-+                                     "v3d_hub", v3d);
-+              if (ret)
-+                      goto fail;
-+
-+              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
-+                                     v3d_irq, IRQF_SHARED,
-+                                     "v3d_core0", v3d);
-+      }
-       if (ret)
-               goto fail;
diff --git a/target/linux/brcm2708/patches-4.19/950-0504-drm-v3d-Make-sure-the-GPU-is-on-when-measuring-clock.patch b/target/linux/brcm2708/patches-4.19/950-0504-drm-v3d-Make-sure-the-GPU-is-on-when-measuring-clock.patch
new file mode 100644 (file)
index 0000000..30cb228
--- /dev/null
@@ -0,0 +1,38 @@
+From 19846d53c32be7c9d8d46b369910374c5ea9b9d5 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 17:26:04 -0800
+Subject: [PATCH] drm/v3d: Make sure the GPU is on when measuring
+ clocks.
+
+You'll get garbage measurements if the registers always read back
+0xdeadbeef
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -187,6 +187,11 @@ static int v3d_measure_clock(struct seq_
+       uint32_t cycles;
+       int core = 0;
+       int measure_ms = 1000;
++      int ret;
++
++      ret = pm_runtime_get_sync(v3d->dev);
++      if (ret < 0)
++              return ret;
+       if (v3d->ver >= 40) {
+               V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
+@@ -210,6 +215,9 @@ static int v3d_measure_clock(struct seq_
+                  cycles / (measure_ms * 1000),
+                  (cycles / (measure_ms * 100)) % 10);
++      pm_runtime_mark_last_busy(v3d->dev);
++      pm_runtime_put_autosuspend(v3d->dev);
++
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0505-drm-v3d-Add-support-for-2711.patch b/target/linux/brcm2708/patches-4.19/950-0505-drm-v3d-Add-support-for-2711.patch
new file mode 100644 (file)
index 0000000..1d723db
--- /dev/null
@@ -0,0 +1,20 @@
+From ffd9543f2d74e9215996ce6500fc34dcf7976462 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 4 Oct 2018 17:22:43 -0700
+Subject: [PATCH] drm/v3d: Add support for 2711.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -235,6 +235,7 @@ static struct drm_driver v3d_drm_driver
+ static const struct of_device_id v3d_of_match[] = {
+       { .compatible = "brcm,7268-v3d" },
+       { .compatible = "brcm,7278-v3d" },
++      { .compatible = "brcm,2711-v3d" },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, v3d_of_match);
diff --git a/target/linux/brcm2708/patches-4.19/950-0505-drm-v3d-Don-t-try-to-set-OVRTMUOUT-on-V3D-4.x.patch b/target/linux/brcm2708/patches-4.19/950-0505-drm-v3d-Don-t-try-to-set-OVRTMUOUT-on-V3D-4.x.patch
deleted file mode 100644 (file)
index a6d0d26..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 8011a92f6eabd682e62e268bcd80b45ce3f06af4 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 16 Oct 2018 10:13:41 -0700
-Subject: [PATCH] drm/v3d: Don't try to set OVRTMUOUT on V3D 4.x.
-
-The old field is gone and the register now has a different field,
-QRMAXCNT for how many TMU requests get serviced before thread switch.
-We were accidentally reducing it from its default of 0x3 (4 requests)
-to 0x0 (1).
-
-v2: Skip setting the reg at all on 4.x, instead of trying to update
-    only the old field.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_gem.c  | 3 ++-
- drivers/gpu/drm/v3d/v3d_regs.h | 2 ++
- 2 files changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -25,7 +25,8 @@ v3d_init_core(struct v3d_dev *v3d, int c
-        * type.  If you want the default behavior, you can still put
-        * "2" in the indirect texture state's output_type field.
-        */
--      V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
-+      if (v3d->ver < 40)
-+              V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
-       /* Whenever we flush the L2T cache, we always want to flush
-        * the whole thing.
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -216,6 +216,8 @@
- # define V3D_IDENT2_BCG_INT                            BIT(28)
- #define V3D_CTL_MISCCFG                                0x00018
-+# define V3D_CTL_MISCCFG_QRMAXCNT_MASK                 V3D_MASK(3, 1)
-+# define V3D_CTL_MISCCFG_QRMAXCNT_SHIFT                1
- # define V3D_MISCCFG_OVRTMUOUT                         BIT(0)
- #define V3D_CTL_L2CACTL                                0x00020
diff --git a/target/linux/brcm2708/patches-4.19/950-0506-drm-v3d-Make-sure-the-GPU-is-on-when-measuring-clock.patch b/target/linux/brcm2708/patches-4.19/950-0506-drm-v3d-Make-sure-the-GPU-is-on-when-measuring-clock.patch
deleted file mode 100644 (file)
index 30cb228..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 19846d53c32be7c9d8d46b369910374c5ea9b9d5 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 17:26:04 -0800
-Subject: [PATCH] drm/v3d: Make sure the GPU is on when measuring
- clocks.
-
-You'll get garbage measurements if the registers always read back
-0xdeadbeef
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_debugfs.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -187,6 +187,11 @@ static int v3d_measure_clock(struct seq_
-       uint32_t cycles;
-       int core = 0;
-       int measure_ms = 1000;
-+      int ret;
-+
-+      ret = pm_runtime_get_sync(v3d->dev);
-+      if (ret < 0)
-+              return ret;
-       if (v3d->ver >= 40) {
-               V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
-@@ -210,6 +215,9 @@ static int v3d_measure_clock(struct seq_
-                  cycles / (measure_ms * 1000),
-                  (cycles / (measure_ms * 100)) % 10);
-+      pm_runtime_mark_last_busy(v3d->dev);
-+      pm_runtime_put_autosuspend(v3d->dev);
-+
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0506-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch b/target/linux/brcm2708/patches-4.19/950-0506-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch
new file mode 100644 (file)
index 0000000..57f8e50
--- /dev/null
@@ -0,0 +1,52 @@
+From f389abea861f9bd3165f98a8d3a1f3407e9fc01a Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 12:35:43 -0800
+Subject: [PATCH] drm/v3d: Skip MMU flush if the device is currently
+ off.
+
+If it's off, we know it will be reset on poweron, so the MMU won't
+have any TLB cached from before this point.  Avoids failed waits for
+MMU flush to reply.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+(cherry picked from commit 3ee4e2e0a9e9587eacbb69b067bbc72ab2cdc47b)
+---
+ drivers/gpu/drm/v3d/v3d_mmu.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_mmu.c
++++ b/drivers/gpu/drm/v3d/v3d_mmu.c
+@@ -18,6 +18,8 @@
+  * each client.  This is not yet implemented.
+  */
++#include <linux/pm_runtime.h>
++
+ #include "v3d_drv.h"
+ #include "v3d_regs.h"
+@@ -34,6 +36,14 @@ static int v3d_mmu_flush_all(struct v3d_
+ {
+       int ret;
++      /* Keep power on the device on until we're done with this
++       * call, but skip the flush if the device is off and will be
++       * reset when powered back on.
++       */
++      ret = pm_runtime_get_if_in_use(v3d->dev);
++      if (ret == 0)
++              return 0;
++
+       /* Make sure that another flush isn't already running when we
+        * start this one.
+        */
+@@ -61,6 +71,9 @@ static int v3d_mmu_flush_all(struct v3d_
+       if (ret)
+               dev_err(v3d->dev, "MMUC flush wait idle failed\n");
++      pm_runtime_mark_last_busy(v3d->dev);
++      pm_runtime_put_autosuspend(v3d->dev);
++
+       return ret;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0507-drm-v3d-Add-support-for-2711.patch b/target/linux/brcm2708/patches-4.19/950-0507-drm-v3d-Add-support-for-2711.patch
deleted file mode 100644 (file)
index 1d723db..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From ffd9543f2d74e9215996ce6500fc34dcf7976462 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 4 Oct 2018 17:22:43 -0700
-Subject: [PATCH] drm/v3d: Add support for 2711.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -235,6 +235,7 @@ static struct drm_driver v3d_drm_driver
- static const struct of_device_id v3d_of_match[] = {
-       { .compatible = "brcm,7268-v3d" },
-       { .compatible = "brcm,7278-v3d" },
-+      { .compatible = "brcm,2711-v3d" },
-       {},
- };
- MODULE_DEVICE_TABLE(of, v3d_of_match);
diff --git a/target/linux/brcm2708/patches-4.19/950-0507-drm-v3d-Hook-up-the-runtime-PM-ops.patch b/target/linux/brcm2708/patches-4.19/950-0507-drm-v3d-Hook-up-the-runtime-PM-ops.patch
new file mode 100644 (file)
index 0000000..3286cd0
--- /dev/null
@@ -0,0 +1,34 @@
+From 30dd82d785715b2ed52a5079595ffcd2ec1f728d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 14:47:57 -0800
+Subject: [PATCH] drm/v3d: Hook up the runtime PM ops.
+
+In translating the runtime PM code from vc4, I missed the ".pm"
+assignment to actually connect them up.  Fixes missing MMU setup if
+runtime PM resets V3D.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+(cherry picked from commit ca197699af29baa8236c74c53d4904ca8957ee06)
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -66,7 +66,7 @@ static int v3d_runtime_resume(struct dev
+ }
+ #endif
+-static const struct dev_pm_ops v3d_v3d_pm_ops = {
++static const struct dev_pm_ops v3d_pm_ops = {
+       SET_RUNTIME_PM_OPS(v3d_runtime_suspend, v3d_runtime_resume, NULL)
+ };
+@@ -371,6 +371,7 @@ static struct platform_driver v3d_platfo
+       .driver         = {
+               .name   = "v3d",
+               .of_match_table = v3d_of_match,
++              .pm = &v3d_pm_ops,
+       },
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0508-drm-v3d-HACK-gut-runtime-pm-for-now.patch b/target/linux/brcm2708/patches-4.19/950-0508-drm-v3d-HACK-gut-runtime-pm-for-now.patch
new file mode 100644 (file)
index 0000000..654ef43
--- /dev/null
@@ -0,0 +1,172 @@
+From 2d4f38abdc2a919d8002fbec7bc0be7c1312786a Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 15:13:17 -0800
+Subject: [PATCH] drm/v3d: HACK: gut runtime pm for now.
+
+Something is still unstable -- on starting a new glxgears from an idle
+X11, I get an MMU violation in high addresses.  The CTS also failed
+quite quickly.  With this, CTS progresses for an hour before OOMing
+(allocating some big buffers when my board only has 600MB available to
+Linux)
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c | 16 +---------------
+ drivers/gpu/drm/v3d/v3d_drv.c     |  7 -------
+ drivers/gpu/drm/v3d/v3d_gem.c     | 20 --------------------
+ 3 files changed, 1 insertion(+), 42 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -4,7 +4,6 @@
+ #include <linux/circ_buf.h>
+ #include <linux/ctype.h>
+ #include <linux/debugfs.h>
+-#include <linux/pm_runtime.h>
+ #include <linux/seq_file.h>
+ #include <drm/drmP.h>
+@@ -100,11 +99,8 @@ static int v3d_v3d_debugfs_ident(struct
+       struct drm_device *dev = node->minor->dev;
+       struct v3d_dev *v3d = to_v3d_dev(dev);
+       u32 ident0, ident1, ident2, ident3, cores;
+-      int ret, core;
++      int core;
+-      ret = pm_runtime_get_sync(v3d->dev);
+-      if (ret < 0)
+-              return ret;
+       ident0 = V3D_READ(V3D_HUB_IDENT0);
+       ident1 = V3D_READ(V3D_HUB_IDENT1);
+@@ -157,9 +153,6 @@ static int v3d_v3d_debugfs_ident(struct
+                          (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0);
+       }
+-      pm_runtime_mark_last_busy(v3d->dev);
+-      pm_runtime_put_autosuspend(v3d->dev);
+-
+       return 0;
+ }
+@@ -187,11 +180,6 @@ static int v3d_measure_clock(struct seq_
+       uint32_t cycles;
+       int core = 0;
+       int measure_ms = 1000;
+-      int ret;
+-
+-      ret = pm_runtime_get_sync(v3d->dev);
+-      if (ret < 0)
+-              return ret;
+       if (v3d->ver >= 40) {
+               V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
+@@ -215,8 +203,6 @@ static int v3d_measure_clock(struct seq_
+                  cycles / (measure_ms * 1000),
+                  (cycles / (measure_ms * 100)) % 10);
+-      pm_runtime_mark_last_busy(v3d->dev);
+-      pm_runtime_put_autosuspend(v3d->dev);
+       return 0;
+ }
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -75,7 +75,6 @@ static int v3d_get_param_ioctl(struct dr
+ {
+       struct v3d_dev *v3d = to_v3d_dev(dev);
+       struct drm_v3d_get_param *args = data;
+-      int ret;
+       static const u32 reg_map[] = {
+               [DRM_V3D_PARAM_V3D_UIFCFG] = V3D_HUB_UIFCFG,
+               [DRM_V3D_PARAM_V3D_HUB_IDENT1] = V3D_HUB_IDENT1,
+@@ -101,15 +100,12 @@ static int v3d_get_param_ioctl(struct dr
+               if (args->value != 0)
+                       return -EINVAL;
+-              ret = pm_runtime_get_sync(v3d->dev);
+               if (args->param >= DRM_V3D_PARAM_V3D_CORE0_IDENT0 &&
+                   args->param <= DRM_V3D_PARAM_V3D_CORE0_IDENT2) {
+                       args->value = V3D_CORE_READ(0, offset);
+               } else {
+                       args->value = V3D_READ(offset);
+               }
+-              pm_runtime_mark_last_busy(v3d->dev);
+-              pm_runtime_put_autosuspend(v3d->dev);
+               return 0;
+       }
+@@ -311,9 +307,6 @@ static int v3d_platform_drm_probe(struct
+               goto dev_free;
+       }
+-      pm_runtime_use_autosuspend(dev);
+-      pm_runtime_set_autosuspend_delay(dev, 50);
+-      pm_runtime_enable(dev);
+       ret = drm_dev_init(&v3d->drm, &v3d_drm_driver, dev);
+       if (ret)
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -375,7 +375,6 @@ v3d_exec_cleanup(struct kref *ref)
+ {
+       struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
+                                                 refcount);
+-      struct v3d_dev *v3d = exec->v3d;
+       unsigned int i;
+       struct v3d_bo *bo, *save;
+@@ -396,9 +395,6 @@ v3d_exec_cleanup(struct kref *ref)
+               drm_gem_object_put_unlocked(&bo->base);
+       }
+-      pm_runtime_mark_last_busy(v3d->dev);
+-      pm_runtime_put_autosuspend(v3d->dev);
+-
+       kfree(exec);
+ }
+@@ -412,7 +408,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
+ {
+       struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
+                                              refcount);
+-      struct v3d_dev *v3d = job->v3d;
+       unsigned int i;
+       dma_fence_put(job->in_fence);
+@@ -423,9 +418,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
+                       drm_gem_object_put_unlocked(&job->bo[i]->base);
+       }
+-      pm_runtime_mark_last_busy(v3d->dev);
+-      pm_runtime_put_autosuspend(v3d->dev);
+-
+       kfree(job);
+ }
+@@ -519,12 +511,6 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       if (!exec)
+               return -ENOMEM;
+-      ret = pm_runtime_get_sync(v3d->dev);
+-      if (ret < 0) {
+-              kfree(exec);
+-              return ret;
+-      }
+-
+       kref_init(&exec->refcount);
+       ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
+@@ -643,12 +629,6 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       if (!job)
+               return -ENOMEM;
+-      ret = pm_runtime_get_sync(v3d->dev);
+-      if (ret < 0) {
+-              kfree(job);
+-              return ret;
+-      }
+-
+       kref_init(&job->refcount);
+       ret = drm_syncobj_find_fence(file_priv, args->in_sync,
diff --git a/target/linux/brcm2708/patches-4.19/950-0508-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch b/target/linux/brcm2708/patches-4.19/950-0508-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch
deleted file mode 100644 (file)
index 57f8e50..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From f389abea861f9bd3165f98a8d3a1f3407e9fc01a Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 12:35:43 -0800
-Subject: [PATCH] drm/v3d: Skip MMU flush if the device is currently
- off.
-
-If it's off, we know it will be reset on poweron, so the MMU won't
-have any TLB cached from before this point.  Avoids failed waits for
-MMU flush to reply.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 3ee4e2e0a9e9587eacbb69b067bbc72ab2cdc47b)
----
- drivers/gpu/drm/v3d/v3d_mmu.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_mmu.c
-+++ b/drivers/gpu/drm/v3d/v3d_mmu.c
-@@ -18,6 +18,8 @@
-  * each client.  This is not yet implemented.
-  */
-+#include <linux/pm_runtime.h>
-+
- #include "v3d_drv.h"
- #include "v3d_regs.h"
-@@ -34,6 +36,14 @@ static int v3d_mmu_flush_all(struct v3d_
- {
-       int ret;
-+      /* Keep power on the device on until we're done with this
-+       * call, but skip the flush if the device is off and will be
-+       * reset when powered back on.
-+       */
-+      ret = pm_runtime_get_if_in_use(v3d->dev);
-+      if (ret == 0)
-+              return 0;
-+
-       /* Make sure that another flush isn't already running when we
-        * start this one.
-        */
-@@ -61,6 +71,9 @@ static int v3d_mmu_flush_all(struct v3d_
-       if (ret)
-               dev_err(v3d->dev, "MMUC flush wait idle failed\n");
-+      pm_runtime_mark_last_busy(v3d->dev);
-+      pm_runtime_put_autosuspend(v3d->dev);
-+
-       return ret;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0509-drm-v3d-Hook-up-the-runtime-PM-ops.patch b/target/linux/brcm2708/patches-4.19/950-0509-drm-v3d-Hook-up-the-runtime-PM-ops.patch
deleted file mode 100644 (file)
index 3286cd0..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 30dd82d785715b2ed52a5079595ffcd2ec1f728d Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 14:47:57 -0800
-Subject: [PATCH] drm/v3d: Hook up the runtime PM ops.
-
-In translating the runtime PM code from vc4, I missed the ".pm"
-assignment to actually connect them up.  Fixes missing MMU setup if
-runtime PM resets V3D.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit ca197699af29baa8236c74c53d4904ca8957ee06)
----
- drivers/gpu/drm/v3d/v3d_drv.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -66,7 +66,7 @@ static int v3d_runtime_resume(struct dev
- }
- #endif
--static const struct dev_pm_ops v3d_v3d_pm_ops = {
-+static const struct dev_pm_ops v3d_pm_ops = {
-       SET_RUNTIME_PM_OPS(v3d_runtime_suspend, v3d_runtime_resume, NULL)
- };
-@@ -371,6 +371,7 @@ static struct platform_driver v3d_platfo
-       .driver         = {
-               .name   = "v3d",
-               .of_match_table = v3d_of_match,
-+              .pm = &v3d_pm_ops,
-       },
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0509-drm-v3d-Update-to-upstream-IRQ-code.patch b/target/linux/brcm2708/patches-4.19/950-0509-drm-v3d-Update-to-upstream-IRQ-code.patch
new file mode 100644 (file)
index 0000000..3c15cc1
--- /dev/null
@@ -0,0 +1,59 @@
+From 50088003d803f04e536eb09ac2635df35b5c8ae4 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 12 Mar 2019 09:08:10 -0700
+Subject: [PATCH] drm/v3d: Update to upstream IRQ code.
+
+---
+ drivers/gpu/drm/v3d/v3d_irq.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -168,7 +168,7 @@ v3d_hub_irq(int irq, void *arg)
+ int
+ v3d_irq_init(struct v3d_dev *v3d)
+ {
+-      int ret, core;
++      int irq1, ret, core;
+       INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work);
+@@ -179,24 +179,29 @@ v3d_irq_init(struct v3d_dev *v3d)
+               V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
+       V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
+-      if (platform_get_irq(v3d->pdev, 1) < 0) {
+-              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
++      irq1 = platform_get_irq(v3d->pdev, 1);
++      if (irq1 == -EPROBE_DEFER)
++              return irq1;
++      if (irq1 > 0) {
++              ret = devm_request_irq(v3d->dev, irq1,
+                                      v3d_irq, IRQF_SHARED,
+-                                     "v3d", v3d);
+-              v3d->single_irq_line = true;
+-      } else {
++                                     "v3d_core0", v3d);
++              if (ret)
++                      goto fail;
+               ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
+                                      v3d_hub_irq, IRQF_SHARED,
+                                      "v3d_hub", v3d);
+               if (ret)
+                       goto fail;
++      } else {
++              v3d->single_irq_line = true;
+-              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
++              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
+                                      v3d_irq, IRQF_SHARED,
+-                                     "v3d_core0", v3d);
++                                     "v3d", v3d);
++              if (ret)
++                      goto fail;
+       }
+-      if (ret)
+-              goto fail;
+       v3d_irq_enable(v3d);
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0510-drm-v3d-HACK-gut-runtime-pm-for-now.patch b/target/linux/brcm2708/patches-4.19/950-0510-drm-v3d-HACK-gut-runtime-pm-for-now.patch
deleted file mode 100644 (file)
index 654ef43..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-From 2d4f38abdc2a919d8002fbec7bc0be7c1312786a Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 15:13:17 -0800
-Subject: [PATCH] drm/v3d: HACK: gut runtime pm for now.
-
-Something is still unstable -- on starting a new glxgears from an idle
-X11, I get an MMU violation in high addresses.  The CTS also failed
-quite quickly.  With this, CTS progresses for an hour before OOMing
-(allocating some big buffers when my board only has 600MB available to
-Linux)
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_debugfs.c | 16 +---------------
- drivers/gpu/drm/v3d/v3d_drv.c     |  7 -------
- drivers/gpu/drm/v3d/v3d_gem.c     | 20 --------------------
- 3 files changed, 1 insertion(+), 42 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -4,7 +4,6 @@
- #include <linux/circ_buf.h>
- #include <linux/ctype.h>
- #include <linux/debugfs.h>
--#include <linux/pm_runtime.h>
- #include <linux/seq_file.h>
- #include <drm/drmP.h>
-@@ -100,11 +99,8 @@ static int v3d_v3d_debugfs_ident(struct
-       struct drm_device *dev = node->minor->dev;
-       struct v3d_dev *v3d = to_v3d_dev(dev);
-       u32 ident0, ident1, ident2, ident3, cores;
--      int ret, core;
-+      int core;
--      ret = pm_runtime_get_sync(v3d->dev);
--      if (ret < 0)
--              return ret;
-       ident0 = V3D_READ(V3D_HUB_IDENT0);
-       ident1 = V3D_READ(V3D_HUB_IDENT1);
-@@ -157,9 +153,6 @@ static int v3d_v3d_debugfs_ident(struct
-                          (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0);
-       }
--      pm_runtime_mark_last_busy(v3d->dev);
--      pm_runtime_put_autosuspend(v3d->dev);
--
-       return 0;
- }
-@@ -187,11 +180,6 @@ static int v3d_measure_clock(struct seq_
-       uint32_t cycles;
-       int core = 0;
-       int measure_ms = 1000;
--      int ret;
--
--      ret = pm_runtime_get_sync(v3d->dev);
--      if (ret < 0)
--              return ret;
-       if (v3d->ver >= 40) {
-               V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
-@@ -215,8 +203,6 @@ static int v3d_measure_clock(struct seq_
-                  cycles / (measure_ms * 1000),
-                  (cycles / (measure_ms * 100)) % 10);
--      pm_runtime_mark_last_busy(v3d->dev);
--      pm_runtime_put_autosuspend(v3d->dev);
-       return 0;
- }
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -75,7 +75,6 @@ static int v3d_get_param_ioctl(struct dr
- {
-       struct v3d_dev *v3d = to_v3d_dev(dev);
-       struct drm_v3d_get_param *args = data;
--      int ret;
-       static const u32 reg_map[] = {
-               [DRM_V3D_PARAM_V3D_UIFCFG] = V3D_HUB_UIFCFG,
-               [DRM_V3D_PARAM_V3D_HUB_IDENT1] = V3D_HUB_IDENT1,
-@@ -101,15 +100,12 @@ static int v3d_get_param_ioctl(struct dr
-               if (args->value != 0)
-                       return -EINVAL;
--              ret = pm_runtime_get_sync(v3d->dev);
-               if (args->param >= DRM_V3D_PARAM_V3D_CORE0_IDENT0 &&
-                   args->param <= DRM_V3D_PARAM_V3D_CORE0_IDENT2) {
-                       args->value = V3D_CORE_READ(0, offset);
-               } else {
-                       args->value = V3D_READ(offset);
-               }
--              pm_runtime_mark_last_busy(v3d->dev);
--              pm_runtime_put_autosuspend(v3d->dev);
-               return 0;
-       }
-@@ -311,9 +307,6 @@ static int v3d_platform_drm_probe(struct
-               goto dev_free;
-       }
--      pm_runtime_use_autosuspend(dev);
--      pm_runtime_set_autosuspend_delay(dev, 50);
--      pm_runtime_enable(dev);
-       ret = drm_dev_init(&v3d->drm, &v3d_drm_driver, dev);
-       if (ret)
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -375,7 +375,6 @@ v3d_exec_cleanup(struct kref *ref)
- {
-       struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
-                                                 refcount);
--      struct v3d_dev *v3d = exec->v3d;
-       unsigned int i;
-       struct v3d_bo *bo, *save;
-@@ -396,9 +395,6 @@ v3d_exec_cleanup(struct kref *ref)
-               drm_gem_object_put_unlocked(&bo->base);
-       }
--      pm_runtime_mark_last_busy(v3d->dev);
--      pm_runtime_put_autosuspend(v3d->dev);
--
-       kfree(exec);
- }
-@@ -412,7 +408,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
- {
-       struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
-                                              refcount);
--      struct v3d_dev *v3d = job->v3d;
-       unsigned int i;
-       dma_fence_put(job->in_fence);
-@@ -423,9 +418,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
-                       drm_gem_object_put_unlocked(&job->bo[i]->base);
-       }
--      pm_runtime_mark_last_busy(v3d->dev);
--      pm_runtime_put_autosuspend(v3d->dev);
--
-       kfree(job);
- }
-@@ -519,12 +511,6 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       if (!exec)
-               return -ENOMEM;
--      ret = pm_runtime_get_sync(v3d->dev);
--      if (ret < 0) {
--              kfree(exec);
--              return ret;
--      }
--
-       kref_init(&exec->refcount);
-       ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
-@@ -643,12 +629,6 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       if (!job)
-               return -ENOMEM;
--      ret = pm_runtime_get_sync(v3d->dev);
--      if (ret < 0) {
--              kfree(job);
--              return ret;
--      }
--
-       kref_init(&job->refcount);
-       ret = drm_syncobj_find_fence(file_priv, args->in_sync,
diff --git a/target/linux/brcm2708/patches-4.19/950-0510-drm-v3d-Rename-the-fence-signaled-from-IRQs-to-irq_f.patch b/target/linux/brcm2708/patches-4.19/950-0510-drm-v3d-Rename-the-fence-signaled-from-IRQs-to-irq_f.patch
new file mode 100644 (file)
index 0000000..55408a0
--- /dev/null
@@ -0,0 +1,117 @@
+From 0d00e0340c1aa9ce36bdff46f927916fe4903cee Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 27 Dec 2018 14:04:44 -0800
+Subject: [PATCH] drm/v3d: Rename the fence signaled from IRQs to
+ "irq_fence".
+
+We have another thing called the "done fence" that tracks when the
+scheduler considers the job done, and having the shared name was
+confusing.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h   |  4 ++--
+ drivers/gpu/drm/v3d/v3d_gem.c   |  6 +++---
+ drivers/gpu/drm/v3d/v3d_irq.c   |  6 +++---
+ drivers/gpu/drm/v3d/v3d_sched.c | 12 ++++++------
+ 4 files changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -182,7 +182,7 @@ struct v3d_job {
+       struct dma_fence *in_fence;
+       /* v3d fence to be signaled by IRQ handler when the job is complete. */
+-      struct dma_fence *done_fence;
++      struct dma_fence *irq_fence;
+       /* GPU virtual addresses of the start/end of the CL job. */
+       u32 start, end;
+@@ -229,7 +229,7 @@ struct v3d_tfu_job {
+       struct dma_fence *in_fence;
+       /* v3d fence to be signaled by IRQ handler when the job is complete. */
+-      struct dma_fence *done_fence;
++      struct dma_fence *irq_fence;
+       struct v3d_dev *v3d;
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -381,8 +381,8 @@ v3d_exec_cleanup(struct kref *ref)
+       dma_fence_put(exec->bin.in_fence);
+       dma_fence_put(exec->render.in_fence);
+-      dma_fence_put(exec->bin.done_fence);
+-      dma_fence_put(exec->render.done_fence);
++      dma_fence_put(exec->bin.irq_fence);
++      dma_fence_put(exec->render.irq_fence);
+       dma_fence_put(exec->bin_done_fence);
+       dma_fence_put(exec->render_done_fence);
+@@ -411,7 +411,7 @@ v3d_tfu_job_cleanup(struct kref *ref)
+       unsigned int i;
+       dma_fence_put(job->in_fence);
+-      dma_fence_put(job->done_fence);
++      dma_fence_put(job->irq_fence);
+       for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
+               if (job->bo[i])
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
+       if (intsts & V3D_INT_FLDONE) {
+               struct v3d_fence *fence =
+-                      to_v3d_fence(v3d->bin_job->bin.done_fence);
++                      to_v3d_fence(v3d->bin_job->bin.irq_fence);
+               trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+               dma_fence_signal(&fence->base);
+@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
+       if (intsts & V3D_INT_FRDONE) {
+               struct v3d_fence *fence =
+-                      to_v3d_fence(v3d->render_job->render.done_fence);
++                      to_v3d_fence(v3d->render_job->render.irq_fence);
+               trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+               dma_fence_signal(&fence->base);
+@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
+       if (intsts & V3D_HUB_INT_TFUC) {
+               struct v3d_fence *fence =
+-                      to_v3d_fence(v3d->tfu_job->done_fence);
++                      to_v3d_fence(v3d->tfu_job->irq_fence);
+               trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+               dma_fence_signal(&fence->base);
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -152,9 +152,9 @@ static struct dma_fence *v3d_job_run(str
+       if (IS_ERR(fence))
+               return NULL;
+-      if (job->done_fence)
+-              dma_fence_put(job->done_fence);
+-      job->done_fence = dma_fence_get(fence);
++      if (job->irq_fence)
++              dma_fence_put(job->irq_fence);
++      job->irq_fence = dma_fence_get(fence);
+       trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
+                           job->start, job->end);
+@@ -195,9 +195,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
+               return NULL;
+       v3d->tfu_job = job;
+-      if (job->done_fence)
+-              dma_fence_put(job->done_fence);
+-      job->done_fence = dma_fence_get(fence);
++      if (job->irq_fence)
++              dma_fence_put(job->irq_fence);
++      job->irq_fence = dma_fence_get(fence);
+       trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
diff --git a/target/linux/brcm2708/patches-4.19/950-0511-drm-v3d-Refactor-job-management.patch b/target/linux/brcm2708/patches-4.19/950-0511-drm-v3d-Refactor-job-management.patch
new file mode 100644 (file)
index 0000000..1192b16
--- /dev/null
@@ -0,0 +1,1104 @@
+From ccf319a0265bfdb4a622a52645f159461bc88079 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 27 Dec 2018 12:11:52 -0800
+Subject: [PATCH] drm/v3d: Refactor job management.
+
+The CL submission had two jobs embedded in an exec struct.  When I
+added TFU support, I had to replicate some of the exec stuff and some
+of the job stuff.  As I went to add CSD, it became clear that actually
+what was in exec should just be in the two CL jobs, and it would let
+us share a lot more code between the 4 queues.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h   |  77 ++++----
+ drivers/gpu/drm/v3d/v3d_gem.c   | 331 +++++++++++++++++---------------
+ drivers/gpu/drm/v3d/v3d_irq.c   |   8 +-
+ drivers/gpu/drm/v3d/v3d_sched.c | 264 ++++++++++++++-----------
+ 4 files changed, 373 insertions(+), 307 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -67,8 +67,8 @@ struct v3d_dev {
+       struct work_struct overflow_mem_work;
+-      struct v3d_exec_info *bin_job;
+-      struct v3d_exec_info *render_job;
++      struct v3d_bin_job *bin_job;
++      struct v3d_render_job *render_job;
+       struct v3d_tfu_job *tfu_job;
+       struct v3d_queue_state queue[V3D_MAX_QUEUES];
+@@ -132,7 +132,7 @@ struct v3d_bo {
+       struct list_head vmas;    /* list of v3d_vma */
+       /* List entry for the BO's position in
+-       * v3d_exec_info->unref_list
++       * v3d_render_job->unref_list
+        */
+       struct list_head unref_head;
+@@ -176,7 +176,15 @@ to_v3d_fence(struct dma_fence *fence)
+ struct v3d_job {
+       struct drm_sched_job base;
+-      struct v3d_exec_info *exec;
++      struct kref refcount;
++
++      struct v3d_dev *v3d;
++
++      /* This is the array of BOs that were looked up at the start
++       * of submission.
++       */
++      struct v3d_bo **bo;
++      u32 bo_count;
+       /* An optional fence userspace can pass in for the job to depend on. */
+       struct dma_fence *in_fence;
+@@ -184,59 +192,53 @@ struct v3d_job {
+       /* v3d fence to be signaled by IRQ handler when the job is complete. */
+       struct dma_fence *irq_fence;
++      /* scheduler fence for when the job is considered complete and
++       * the BO reservations can be released.
++       */
++      struct dma_fence *done_fence;
++
++      /* Callback for the freeing of the job on refcount going to 0. */
++      void (*free)(struct kref *ref);
++};
++
++struct v3d_bin_job {
++      struct v3d_job base;
++
+       /* GPU virtual addresses of the start/end of the CL job. */
+       u32 start, end;
+       u32 timedout_ctca, timedout_ctra;
+-};
+-struct v3d_exec_info {
+-      struct v3d_dev *v3d;
++      /* Corresponding render job, for attaching our overflow memory. */
++      struct v3d_render_job *render;
++
++      /* Submitted tile memory allocation start/size, tile state. */
++      u32 qma, qms, qts;
++};
+-      struct v3d_job bin, render;
++struct v3d_render_job {
++      struct v3d_job base;
+-      /* Fence for when the scheduler considers the binner to be
+-       * done, for render to depend on.
++      /* Optional fence for the binner, to depend on before starting
++       * our job.
+        */
+       struct dma_fence *bin_done_fence;
+-      /* Fence for when the scheduler considers the render to be
+-       * done, for when the BOs reservations should be complete.
+-       */
+-      struct dma_fence *render_done_fence;
+-
+-      struct kref refcount;
++      /* GPU virtual addresses of the start/end of the CL job. */
++      u32 start, end;
+-      /* This is the array of BOs that were looked up at the start of exec. */
+-      struct v3d_bo **bo;
+-      u32 bo_count;
++      u32 timedout_ctca, timedout_ctra;
+       /* List of overflow BOs used in the job that need to be
+        * released once the job is complete.
+        */
+       struct list_head unref_list;
+-
+-      /* Submitted tile memory allocation start/size, tile state. */
+-      u32 qma, qms, qts;
+ };
+ struct v3d_tfu_job {
+-      struct drm_sched_job base;
++      struct v3d_job base;
+       struct drm_v3d_submit_tfu args;
+-
+-      /* An optional fence userspace can pass in for the job to depend on. */
+-      struct dma_fence *in_fence;
+-
+-      /* v3d fence to be signaled by IRQ handler when the job is complete. */
+-      struct dma_fence *irq_fence;
+-
+-      struct v3d_dev *v3d;
+-
+-      struct kref refcount;
+-
+-      /* This is the array of BOs that were looked up at the start of exec. */
+-      struct v3d_bo *bo[4];
+ };
+ /**
+@@ -306,8 +308,7 @@ int v3d_submit_tfu_ioctl(struct drm_devi
+                        struct drm_file *file_priv);
+ int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+-void v3d_exec_put(struct v3d_exec_info *exec);
+-void v3d_tfu_job_put(struct v3d_tfu_job *exec);
++void v3d_job_put(struct v3d_job *job);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -293,11 +293,11 @@ retry:
+ }
+ /**
+- * v3d_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
++ * v3d_lookup_bos() - Sets up job->bo[] with the GEM objects
+  * referenced by the job.
+  * @dev: DRM device
+  * @file_priv: DRM file for this fd
+- * @exec: V3D job being set up
++ * @job: V3D job being set up
+  *
+  * The command validator needs to reference BOs by their index within
+  * the submitted job's BO list.  This does the validation of the job's
+@@ -307,18 +307,19 @@ retry:
+  * failure, because that will happen at v3d_exec_cleanup() time.
+  */
+ static int
+-v3d_cl_lookup_bos(struct drm_device *dev,
+-                struct drm_file *file_priv,
+-                struct drm_v3d_submit_cl *args,
+-                struct v3d_exec_info *exec)
++v3d_lookup_bos(struct drm_device *dev,
++             struct drm_file *file_priv,
++             struct v3d_job *job,
++             u64 bo_handles,
++             u32 bo_count)
+ {
+       u32 *handles;
+       int ret = 0;
+       int i;
+-      exec->bo_count = args->bo_handle_count;
++      job->bo_count = bo_count;
+-      if (!exec->bo_count) {
++      if (!job->bo_count) {
+               /* See comment on bo_index for why we have to check
+                * this.
+                */
+@@ -326,15 +327,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
+               return -EINVAL;
+       }
+-      exec->bo = kvmalloc_array(exec->bo_count,
+-                                sizeof(struct drm_gem_cma_object *),
+-                                GFP_KERNEL | __GFP_ZERO);
+-      if (!exec->bo) {
++      job->bo = kvmalloc_array(job->bo_count,
++                               sizeof(struct drm_gem_cma_object *),
++                               GFP_KERNEL | __GFP_ZERO);
++      if (!job->bo) {
+               DRM_DEBUG("Failed to allocate validated BO pointers\n");
+               return -ENOMEM;
+       }
+-      handles = kvmalloc_array(exec->bo_count, sizeof(u32), GFP_KERNEL);
++      handles = kvmalloc_array(job->bo_count, sizeof(u32), GFP_KERNEL);
+       if (!handles) {
+               ret = -ENOMEM;
+               DRM_DEBUG("Failed to allocate incoming GEM handles\n");
+@@ -342,15 +343,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
+       }
+       if (copy_from_user(handles,
+-                         (void __user *)(uintptr_t)args->bo_handles,
+-                         exec->bo_count * sizeof(u32))) {
++                         (void __user *)(uintptr_t)bo_handles,
++                         job->bo_count * sizeof(u32))) {
+               ret = -EFAULT;
+               DRM_DEBUG("Failed to copy in GEM handles\n");
+               goto fail;
+       }
+       spin_lock(&file_priv->table_lock);
+-      for (i = 0; i < exec->bo_count; i++) {
++      for (i = 0; i < job->bo_count; i++) {
+               struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
+                                                    handles[i]);
+               if (!bo) {
+@@ -361,7 +362,7 @@ v3d_cl_lookup_bos(struct drm_device *dev
+                       goto fail;
+               }
+               drm_gem_object_get(bo);
+-              exec->bo[i] = to_v3d_bo(bo);
++              job->bo[i] = to_v3d_bo(bo);
+       }
+       spin_unlock(&file_priv->table_lock);
+@@ -371,59 +372,41 @@ fail:
+ }
+ static void
+-v3d_exec_cleanup(struct kref *ref)
++v3d_job_free(struct kref *ref)
+ {
+-      struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
+-                                                refcount);
+-      unsigned int i;
+-      struct v3d_bo *bo, *save;
+-
+-      dma_fence_put(exec->bin.in_fence);
+-      dma_fence_put(exec->render.in_fence);
+-
+-      dma_fence_put(exec->bin.irq_fence);
+-      dma_fence_put(exec->render.irq_fence);
+-
+-      dma_fence_put(exec->bin_done_fence);
+-      dma_fence_put(exec->render_done_fence);
+-
+-      for (i = 0; i < exec->bo_count; i++)
+-              drm_gem_object_put_unlocked(&exec->bo[i]->base);
+-      kvfree(exec->bo);
++      struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
++      int i;
+-      list_for_each_entry_safe(bo, save, &exec->unref_list, unref_head) {
+-              drm_gem_object_put_unlocked(&bo->base);
++      for (i = 0; i < job->bo_count; i++) {
++              if (job->bo[i])
++                      drm_gem_object_put_unlocked(&job->bo[i]->base);
+       }
++      kvfree(job->bo);
+-      kfree(exec);
+-}
++      dma_fence_put(job->in_fence);
++      dma_fence_put(job->irq_fence);
++      dma_fence_put(job->done_fence);
+-void v3d_exec_put(struct v3d_exec_info *exec)
+-{
+-      kref_put(&exec->refcount, v3d_exec_cleanup);
++      kfree(job);
+ }
+ static void
+-v3d_tfu_job_cleanup(struct kref *ref)
++v3d_render_job_free(struct kref *ref)
+ {
+-      struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
+-                                             refcount);
+-      unsigned int i;
+-
+-      dma_fence_put(job->in_fence);
+-      dma_fence_put(job->irq_fence);
++      struct v3d_render_job *job = container_of(ref, struct v3d_render_job,
++                                                base.refcount);
++      struct v3d_bo *bo, *save;
+-      for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
+-              if (job->bo[i])
+-                      drm_gem_object_put_unlocked(&job->bo[i]->base);
++      list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) {
++              drm_gem_object_put_unlocked(&bo->base);
+       }
+-      kfree(job);
++      v3d_job_free(ref);
+ }
+-void v3d_tfu_job_put(struct v3d_tfu_job *job)
++void v3d_job_put(struct v3d_job *job)
+ {
+-      kref_put(&job->refcount, v3d_tfu_job_cleanup);
++      kref_put(&job->refcount, job->free);
+ }
+ int
+@@ -476,6 +459,65 @@ v3d_wait_bo_ioctl(struct drm_device *dev
+       return ret;
+ }
++static int
++v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
++           struct v3d_job *job, void (*free)(struct kref *ref),
++           u32 in_sync)
++{
++      int ret;
++
++      job->v3d = v3d;
++      job->free = free;
++
++      ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
++      if (ret == -EINVAL)
++              return ret;
++
++      kref_init(&job->refcount);
++
++      return 0;
++}
++
++static int
++v3d_push_job(struct v3d_file_priv *v3d_priv,
++           struct v3d_job *job, enum v3d_queue queue)
++{
++      int ret;
++
++      ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
++                               v3d_priv);
++      if (ret)
++              return ret;
++
++      job->done_fence = dma_fence_get(&job->base.s_fence->finished);
++
++      /* put by scheduler job completion */
++      kref_get(&job->refcount);
++
++      drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[queue]);
++
++      return 0;
++}
++
++static void
++v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
++                                       struct v3d_job *job,
++                                       struct ww_acquire_ctx *acquire_ctx,
++                                       u32 out_sync)
++{
++      struct drm_syncobj *sync_out;
++
++      v3d_attach_object_fences(job->bo, job->bo_count, job->done_fence);
++      v3d_unlock_bo_reservations(job->bo, job->bo_count, acquire_ctx);
++
++      /* Update the return sync object for the job */
++      sync_out = drm_syncobj_find(file_priv, out_sync);
++      if (sync_out) {
++              drm_syncobj_replace_fence(sync_out, job->done_fence);
++              drm_syncobj_put(sync_out);
++      }
++}
++
+ /**
+  * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.
+  * @dev: DRM device
+@@ -495,9 +537,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       struct v3d_dev *v3d = to_v3d_dev(dev);
+       struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
+       struct drm_v3d_submit_cl *args = data;
+-      struct v3d_exec_info *exec;
++      struct v3d_bin_job *bin = NULL;
++      struct v3d_render_job *render;
+       struct ww_acquire_ctx acquire_ctx;
+-      struct drm_syncobj *sync_out;
+       int ret = 0;
+       trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
+@@ -507,95 +549,84 @@ v3d_submit_cl_ioctl(struct drm_device *d
+               return -EINVAL;
+       }
+-      exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
+-      if (!exec)
++      render = kcalloc(1, sizeof(*render), GFP_KERNEL);
++      if (!render)
+               return -ENOMEM;
+-      kref_init(&exec->refcount);
++      render->start = args->rcl_start;
++      render->end = args->rcl_end;
++      INIT_LIST_HEAD(&render->unref_list);
+-      ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
+-                                   0, &exec->bin.in_fence);
+-      if (ret == -EINVAL)
+-              goto fail;
++      ret = v3d_job_init(v3d, file_priv, &render->base,
++                         v3d_render_job_free, args->in_sync_rcl);
++      if (ret) {
++              kfree(bin);
++              kfree(render);
++              return ret;
++      }
+-      ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
+-                                   0, &exec->render.in_fence);
+-      if (ret == -EINVAL)
+-              goto fail;
++      if (args->bcl_start != args->bcl_end) {
++              bin = kcalloc(1, sizeof(*bin), GFP_KERNEL);
++              if (!bin)
++                      return -ENOMEM;
++
++              ret = v3d_job_init(v3d, file_priv, &bin->base,
++                                 v3d_job_free, args->in_sync_bcl);
++              if (ret) {
++                      v3d_job_put(&render->base);
++                      return ret;
++              }
+-      exec->qma = args->qma;
+-      exec->qms = args->qms;
+-      exec->qts = args->qts;
+-      exec->bin.exec = exec;
+-      exec->bin.start = args->bcl_start;
+-      exec->bin.end = args->bcl_end;
+-      exec->render.exec = exec;
+-      exec->render.start = args->rcl_start;
+-      exec->render.end = args->rcl_end;
+-      exec->v3d = v3d;
+-      INIT_LIST_HEAD(&exec->unref_list);
++              bin->start = args->bcl_start;
++              bin->end = args->bcl_end;
++              bin->qma = args->qma;
++              bin->qms = args->qms;
++              bin->qts = args->qts;
++              bin->render = render;
++      }
+-      ret = v3d_cl_lookup_bos(dev, file_priv, args, exec);
++      ret = v3d_lookup_bos(dev, file_priv, &render->base,
++                           args->bo_handles, args->bo_handle_count);
+       if (ret)
+               goto fail;
+-      ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
++      ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
+                                      &acquire_ctx);
+       if (ret)
+               goto fail;
+       mutex_lock(&v3d->sched_lock);
+-      if (exec->bin.start != exec->bin.end) {
+-              ret = drm_sched_job_init(&exec->bin.base,
+-                                       &v3d_priv->sched_entity[V3D_BIN],
+-                                       v3d_priv);
++      if (bin) {
++              ret = v3d_push_job(v3d_priv, &bin->base, V3D_BIN);
+               if (ret)
+                       goto fail_unreserve;
+-              exec->bin_done_fence =
+-                      dma_fence_get(&exec->bin.base.s_fence->finished);
+-
+-              kref_get(&exec->refcount); /* put by scheduler job completion */
+-              drm_sched_entity_push_job(&exec->bin.base,
+-                                        &v3d_priv->sched_entity[V3D_BIN]);
++              render->bin_done_fence = dma_fence_get(bin->base.done_fence);
+       }
+-      ret = drm_sched_job_init(&exec->render.base,
+-                               &v3d_priv->sched_entity[V3D_RENDER],
+-                               v3d_priv);
++      ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
+       if (ret)
+               goto fail_unreserve;
+-
+-      exec->render_done_fence =
+-              dma_fence_get(&exec->render.base.s_fence->finished);
+-
+-      kref_get(&exec->refcount); /* put by scheduler job completion */
+-      drm_sched_entity_push_job(&exec->render.base,
+-                                &v3d_priv->sched_entity[V3D_RENDER]);
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_attach_object_fences(exec->bo, exec->bo_count,
+-                               exec->render_done_fence);
+-
+-      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
+-
+-      /* Update the return sync object for the */
+-      sync_out = drm_syncobj_find(file_priv, args->out_sync);
+-      if (sync_out) {
+-              drm_syncobj_replace_fence(sync_out,
+-                                        exec->render_done_fence);
+-              drm_syncobj_put(sync_out);
+-      }
+-
+-      v3d_exec_put(exec);
++      v3d_attach_fences_and_unlock_reservation(file_priv,
++                                               &render->base, &acquire_ctx,
++                                               args->out_sync);
++
++      if (bin)
++              v3d_job_put(&bin->base);
++      v3d_job_put(&render->base);
+       return 0;
+ fail_unreserve:
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
++      v3d_unlock_bo_reservations(render->base.bo,
++                                 render->base.bo_count, &acquire_ctx);
+ fail:
+-      v3d_exec_put(exec);
++      if (bin)
++              v3d_job_put(&bin->base);
++      v3d_job_put(&render->base);
+       return ret;
+ }
+@@ -618,10 +649,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       struct drm_v3d_submit_tfu *args = data;
+       struct v3d_tfu_job *job;
+       struct ww_acquire_ctx acquire_ctx;
+-      struct drm_syncobj *sync_out;
+-      struct dma_fence *sched_done_fence;
+       int ret = 0;
+-      int bo_count;
+       trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
+@@ -629,75 +657,66 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       if (!job)
+               return -ENOMEM;
+-      kref_init(&job->refcount);
+-
+-      ret = drm_syncobj_find_fence(file_priv, args->in_sync,
+-                                   0, &job->in_fence);
+-      if (ret == -EINVAL)
+-              goto fail;
++      ret = v3d_job_init(v3d, file_priv, &job->base,
++                         v3d_job_free, args->in_sync);
++      if (ret) {
++              kfree(job);
++              return ret;
++      }
++      job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles),
++                             sizeof(*job->base.bo), GFP_KERNEL);
+       job->args = *args;
+-      job->v3d = v3d;
+       spin_lock(&file_priv->table_lock);
+-      for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
++      for (job->base.bo_count = 0;
++           job->base.bo_count < ARRAY_SIZE(args->bo_handles);
++           job->base.bo_count++) {
+               struct drm_gem_object *bo;
+-              if (!args->bo_handles[bo_count])
++              if (!args->bo_handles[job->base.bo_count])
+                       break;
+               bo = idr_find(&file_priv->object_idr,
+-                            args->bo_handles[bo_count]);
++                            args->bo_handles[job->base.bo_count]);
+               if (!bo) {
+                       DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
+-                                bo_count, args->bo_handles[bo_count]);
++                                job->base.bo_count,
++                                args->bo_handles[job->base.bo_count]);
+                       ret = -ENOENT;
+                       spin_unlock(&file_priv->table_lock);
+                       goto fail;
+               }
+               drm_gem_object_get(bo);
+-              job->bo[bo_count] = to_v3d_bo(bo);
++              job->base.bo[job->base.bo_count] = to_v3d_bo(bo);
+       }
+       spin_unlock(&file_priv->table_lock);
+-      ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
++      ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
++                                     &acquire_ctx);
+       if (ret)
+               goto fail;
+       mutex_lock(&v3d->sched_lock);
+-      ret = drm_sched_job_init(&job->base,
+-                               &v3d_priv->sched_entity[V3D_TFU],
+-                               v3d_priv);
++      ret = v3d_push_job(v3d_priv, &job->base, V3D_TFU);
+       if (ret)
+               goto fail_unreserve;
+-
+-      sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
+-
+-      kref_get(&job->refcount); /* put by scheduler job completion */
+-      drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
+-
+-      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+-
+-      /* Update the return sync object */
+-      sync_out = drm_syncobj_find(file_priv, args->out_sync);
+-      if (sync_out) {
+-              drm_syncobj_replace_fence(sync_out, sched_done_fence);
+-              drm_syncobj_put(sync_out);
+-      }
+-      dma_fence_put(sched_done_fence);
++      v3d_attach_fences_and_unlock_reservation(file_priv,
++                                               &job->base, &acquire_ctx,
++                                               args->out_sync);
+-      v3d_tfu_job_put(job);
++      v3d_job_put(&job->base);
+       return 0;
+ fail_unreserve:
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
++      v3d_unlock_bo_reservations(job->base.bo, job->base.bo_count,
++                                 &acquire_ctx);
+ fail:
+-      v3d_tfu_job_put(job);
++      v3d_job_put(&job->base);
+       return ret;
+ }
+@@ -755,7 +774,7 @@ v3d_gem_destroy(struct drm_device *dev)
+       v3d_sched_fini(v3d);
+-      /* Waiting for exec to finish would need to be done before
++      /* Waiting for jobs to finish would need to be done before
+        * unregistering V3D.
+        */
+       WARN_ON(v3d->bin_job);
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -60,7 +60,7 @@ v3d_overflow_mem_work(struct work_struct
+       }
+       drm_gem_object_get(&bo->base);
+-      list_add_tail(&bo->unref_head, &v3d->bin_job->unref_list);
++      list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
+       spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+       V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
+@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
+       if (intsts & V3D_INT_FLDONE) {
+               struct v3d_fence *fence =
+-                      to_v3d_fence(v3d->bin_job->bin.irq_fence);
++                      to_v3d_fence(v3d->bin_job->base.irq_fence);
+               trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+               dma_fence_signal(&fence->base);
+@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
+       if (intsts & V3D_INT_FRDONE) {
+               struct v3d_fence *fence =
+-                      to_v3d_fence(v3d->render_job->render.irq_fence);
++                      to_v3d_fence(v3d->render_job->base.irq_fence);
+               trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+               dma_fence_signal(&fence->base);
+@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
+       if (intsts & V3D_HUB_INT_TFUC) {
+               struct v3d_fence *fence =
+-                      to_v3d_fence(v3d->tfu_job->irq_fence);
++                      to_v3d_fence(v3d->tfu_job->base.irq_fence);
+               trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+               dma_fence_signal(&fence->base);
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -30,39 +30,43 @@ to_v3d_job(struct drm_sched_job *sched_j
+       return container_of(sched_job, struct v3d_job, base);
+ }
+-static struct v3d_tfu_job *
+-to_tfu_job(struct drm_sched_job *sched_job)
++static struct v3d_bin_job *
++to_bin_job(struct drm_sched_job *sched_job)
+ {
+-      return container_of(sched_job, struct v3d_tfu_job, base);
++      return container_of(sched_job, struct v3d_bin_job, base.base);
+ }
+-static void
+-v3d_job_free(struct drm_sched_job *sched_job)
++static struct v3d_render_job *
++to_render_job(struct drm_sched_job *sched_job)
+ {
+-      struct v3d_job *job = to_v3d_job(sched_job);
++      return container_of(sched_job, struct v3d_render_job, base.base);
++}
+-      v3d_exec_put(job->exec);
++static struct v3d_tfu_job *
++to_tfu_job(struct drm_sched_job *sched_job)
++{
++      return container_of(sched_job, struct v3d_tfu_job, base.base);
+ }
+ static void
+-v3d_tfu_job_free(struct drm_sched_job *sched_job)
++v3d_job_free(struct drm_sched_job *sched_job)
+ {
+-      struct v3d_tfu_job *job = to_tfu_job(sched_job);
++      struct v3d_job *job = to_v3d_job(sched_job);
+-      v3d_tfu_job_put(job);
++      v3d_job_put(job);
+ }
+ /**
+- * Returns the fences that the bin or render job depends on, one by one.
+- * v3d_job_run() won't be called until all of them have been signaled.
++ * Returns the fences that the job depends on, one by one.
++ *
++ * If placed in the scheduler's .dependency method, the corresponding
++ * .run_job won't be called until all of them have been signaled.
+  */
+ static struct dma_fence *
+ v3d_job_dependency(struct drm_sched_job *sched_job,
+                  struct drm_sched_entity *s_entity)
+ {
+       struct v3d_job *job = to_v3d_job(sched_job);
+-      struct v3d_exec_info *exec = job->exec;
+-      enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+       struct dma_fence *fence;
+       fence = job->in_fence;
+@@ -71,113 +75,132 @@ v3d_job_dependency(struct drm_sched_job
+               return fence;
+       }
+-      if (q == V3D_RENDER) {
+-              /* If we had a bin job, the render job definitely depends on
+-               * it. We first have to wait for bin to be scheduled, so that
+-               * its done_fence is created.
+-               */
+-              fence = exec->bin_done_fence;
+-              if (fence) {
+-                      exec->bin_done_fence = NULL;
+-                      return fence;
+-              }
+-      }
+-
+-      /* XXX: Wait on a fence for switching the GMP if necessary,
+-       * and then do so.
+-       */
+-
+-      return fence;
++      return NULL;
+ }
+ /**
+- * Returns the fences that the TFU job depends on, one by one.
+- * v3d_tfu_job_run() won't be called until all of them have been
+- * signaled.
++ * Returns the fences that the render job depends on, one by one.
++ * v3d_job_run() won't be called until all of them have been signaled.
+  */
+ static struct dma_fence *
+-v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
+-                     struct drm_sched_entity *s_entity)
++v3d_render_job_dependency(struct drm_sched_job *sched_job,
++                        struct drm_sched_entity *s_entity)
+ {
+-      struct v3d_tfu_job *job = to_tfu_job(sched_job);
++      struct v3d_render_job *job = to_render_job(sched_job);
+       struct dma_fence *fence;
+-      fence = job->in_fence;
++      fence = v3d_job_dependency(sched_job, s_entity);
++      if (fence)
++              return fence;
++
++      /* If we had a bin job, the render job definitely depends on
++       * it. We first have to wait for bin to be scheduled, so that
++       * its done_fence is created.
++       */
++      fence = job->bin_done_fence;
+       if (fence) {
+-              job->in_fence = NULL;
++              job->bin_done_fence = NULL;
+               return fence;
+       }
+-      return NULL;
++      /* XXX: Wait on a fence for switching the GMP if necessary,
++       * and then do so.
++       */
++
++      return fence;
+ }
+-static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
++static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+ {
+-      struct v3d_job *job = to_v3d_job(sched_job);
+-      struct v3d_exec_info *exec = job->exec;
+-      enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+-      struct v3d_dev *v3d = exec->v3d;
++      struct v3d_bin_job *job = to_bin_job(sched_job);
++      struct v3d_dev *v3d = job->base.v3d;
+       struct drm_device *dev = &v3d->drm;
+       struct dma_fence *fence;
+       unsigned long irqflags;
+-      if (unlikely(job->base.s_fence->finished.error))
++      if (unlikely(job->base.base.s_fence->finished.error))
+               return NULL;
+       /* Lock required around bin_job update vs
+        * v3d_overflow_mem_work().
+        */
+       spin_lock_irqsave(&v3d->job_lock, irqflags);
+-      if (q == V3D_BIN) {
+-              v3d->bin_job = job->exec;
++      v3d->bin_job = job;
++      /* Clear out the overflow allocation, so we don't
++       * reuse the overflow attached to a previous job.
++       */
++      V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
++      spin_unlock_irqrestore(&v3d->job_lock, irqflags);
++
++      v3d_invalidate_caches(v3d);
+-              /* Clear out the overflow allocation, so we don't
+-               * reuse the overflow attached to a previous job.
+-               */
+-              V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
+-      } else {
+-              v3d->render_job = job->exec;
++      fence = v3d_fence_create(v3d, V3D_BIN);
++      if (IS_ERR(fence))
++              return NULL;
++
++      if (job->base.irq_fence)
++              dma_fence_put(job->base.irq_fence);
++      job->base.irq_fence = dma_fence_get(fence);
++
++      trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
++                          job->start, job->end);
++
++      /* Set the current and end address of the control list.
++       * Writing the end register is what starts the job.
++       */
++      if (job->qma) {
++              V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, job->qma);
++              V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, job->qms);
+       }
+-      spin_unlock_irqrestore(&v3d->job_lock, irqflags);
++      if (job->qts) {
++              V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
++                             V3D_CLE_CT0QTS_ENABLE |
++                             job->qts);
++      }
++      V3D_CORE_WRITE(0, V3D_CLE_CT0QBA, job->start);
++      V3D_CORE_WRITE(0, V3D_CLE_CT0QEA, job->end);
++
++      return fence;
++}
++
++static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
++{
++      struct v3d_render_job *job = to_render_job(sched_job);
++      struct v3d_dev *v3d = job->base.v3d;
++      struct drm_device *dev = &v3d->drm;
++      struct dma_fence *fence;
++
++      if (unlikely(job->base.base.s_fence->finished.error))
++              return NULL;
+-      /* Can we avoid this flush when q==RENDER?  We need to be
+-       * careful of scheduling, though -- imagine job0 rendering to
+-       * texture and job1 reading, and them being executed as bin0,
+-       * bin1, render0, render1, so that render1's flush at bin time
++      v3d->render_job = job;
++
++      /* Can we avoid this flush?  We need to be careful of
++       * scheduling, though -- imagine job0 rendering to texture and
++       * job1 reading, and them being executed as bin0, bin1,
++       * render0, render1, so that render1's flush at bin time
+        * wasn't enough.
+        */
+       v3d_invalidate_caches(v3d);
+-      fence = v3d_fence_create(v3d, q);
++      fence = v3d_fence_create(v3d, V3D_RENDER);
+       if (IS_ERR(fence))
+               return NULL;
+-      if (job->irq_fence)
+-              dma_fence_put(job->irq_fence);
+-      job->irq_fence = dma_fence_get(fence);
++      if (job->base.irq_fence)
++              dma_fence_put(job->base.irq_fence);
++      job->base.irq_fence = dma_fence_get(fence);
+-      trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
++      trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
+                           job->start, job->end);
+-      if (q == V3D_BIN) {
+-              if (exec->qma) {
+-                      V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, exec->qma);
+-                      V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, exec->qms);
+-              }
+-              if (exec->qts) {
+-                      V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
+-                                     V3D_CLE_CT0QTS_ENABLE |
+-                                     exec->qts);
+-              }
+-      } else {
+-              /* XXX: Set the QCFG */
+-      }
++      /* XXX: Set the QCFG */
+       /* Set the current and end address of the control list.
+        * Writing the end register is what starts the job.
+        */
+-      V3D_CORE_WRITE(0, V3D_CLE_CTNQBA(q), job->start);
+-      V3D_CORE_WRITE(0, V3D_CLE_CTNQEA(q), job->end);
++      V3D_CORE_WRITE(0, V3D_CLE_CT1QBA, job->start);
++      V3D_CORE_WRITE(0, V3D_CLE_CT1QEA, job->end);
+       return fence;
+ }
+@@ -186,7 +209,7 @@ static struct dma_fence *
+ v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ {
+       struct v3d_tfu_job *job = to_tfu_job(sched_job);
+-      struct v3d_dev *v3d = job->v3d;
++      struct v3d_dev *v3d = job->base.v3d;
+       struct drm_device *dev = &v3d->drm;
+       struct dma_fence *fence;
+@@ -195,9 +218,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
+               return NULL;
+       v3d->tfu_job = job;
+-      if (job->irq_fence)
+-              dma_fence_put(job->irq_fence);
+-      job->irq_fence = dma_fence_get(fence);
++      if (job->base.irq_fence)
++              dma_fence_put(job->base.irq_fence);
++      job->base.irq_fence = dma_fence_get(fence);
+       trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
+@@ -247,25 +270,23 @@ v3d_gpu_reset_for_timeout(struct v3d_dev
+       mutex_unlock(&v3d->reset_lock);
+ }
++/* If the current address or return address have changed, then the GPU
++ * has probably made progress and we should delay the reset.  This
++ * could fail if the GPU got in an infinite loop in the CL, but that
++ * is pretty unlikely outside of an i-g-t testcase.
++ */
+ static void
+-v3d_job_timedout(struct drm_sched_job *sched_job)
++v3d_cl_job_timedout(struct drm_sched_job *sched_job, enum v3d_queue q,
++                    u32 *timedout_ctca, u32 *timedout_ctra)
+ {
+       struct v3d_job *job = to_v3d_job(sched_job);
+-      struct v3d_exec_info *exec = job->exec;
+-      struct v3d_dev *v3d = exec->v3d;
+-      enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+-      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
+-      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
+-
+-      /* If the current address or return address have changed, then
+-       * the GPU has probably made progress and we should delay the
+-       * reset.  This could fail if the GPU got in an infinite loop
+-       * in the CL, but that is pretty unlikely outside of an i-g-t
+-       * testcase.
+-       */
+-      if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
+-              job->timedout_ctca = ctca;
+-              job->timedout_ctra = ctra;
++      struct v3d_dev *v3d = job->v3d;
++      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(q));
++      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(q));
++
++      if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
++              *timedout_ctca = ctca;
++              *timedout_ctra = ctra;
+               schedule_delayed_work(&job->base.work_tdr,
+                                     job->base.sched->timeout);
+               return;
+@@ -275,25 +296,50 @@ v3d_job_timedout(struct drm_sched_job *s
+ }
+ static void
++v3d_bin_job_timedout(struct drm_sched_job *sched_job)
++{
++      struct v3d_bin_job *job = to_bin_job(sched_job);
++
++      v3d_cl_job_timedout(sched_job, V3D_BIN,
++                          &job->timedout_ctca, &job->timedout_ctra);
++}
++
++static void
++v3d_render_job_timedout(struct drm_sched_job *sched_job)
++{
++      struct v3d_render_job *job = to_render_job(sched_job);
++
++      v3d_cl_job_timedout(sched_job, V3D_RENDER,
++                          &job->timedout_ctca, &job->timedout_ctra);
++}
++
++static void
+ v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
+ {
+-      struct v3d_tfu_job *job = to_tfu_job(sched_job);
++      struct v3d_job *job = to_v3d_job(sched_job);
+       v3d_gpu_reset_for_timeout(job->v3d, sched_job);
+ }
+-static const struct drm_sched_backend_ops v3d_sched_ops = {
++static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
+       .dependency = v3d_job_dependency,
+-      .run_job = v3d_job_run,
+-      .timedout_job = v3d_job_timedout,
+-      .free_job = v3d_job_free
++      .run_job = v3d_bin_job_run,
++      .timedout_job = v3d_bin_job_timedout,
++      .free_job = v3d_job_free,
++};
++
++static const struct drm_sched_backend_ops v3d_render_sched_ops = {
++      .dependency = v3d_render_job_dependency,
++      .run_job = v3d_render_job_run,
++      .timedout_job = v3d_render_job_timedout,
++      .free_job = v3d_job_free,
+ };
+ static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
+-      .dependency = v3d_tfu_job_dependency,
++      .dependency = v3d_job_dependency,
+       .run_job = v3d_tfu_job_run,
+       .timedout_job = v3d_tfu_job_timedout,
+-      .free_job = v3d_tfu_job_free
++      .free_job = v3d_job_free,
+ };
+ int
+@@ -305,7 +351,7 @@ v3d_sched_init(struct v3d_dev *v3d)
+       int ret;
+       ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,
+-                           &v3d_sched_ops,
++                           &v3d_bin_sched_ops,
+                            hw_jobs_limit, job_hang_limit,
+                            msecs_to_jiffies(hang_limit_ms),
+                            "v3d_bin");
+@@ -315,7 +361,7 @@ v3d_sched_init(struct v3d_dev *v3d)
+       }
+       ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
+-                           &v3d_sched_ops,
++                           &v3d_render_sched_ops,
+                            hw_jobs_limit, job_hang_limit,
+                            msecs_to_jiffies(hang_limit_ms),
+                            "v3d_render");
diff --git a/target/linux/brcm2708/patches-4.19/950-0511-drm-v3d-Update-to-upstream-IRQ-code.patch b/target/linux/brcm2708/patches-4.19/950-0511-drm-v3d-Update-to-upstream-IRQ-code.patch
deleted file mode 100644 (file)
index 3c15cc1..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 50088003d803f04e536eb09ac2635df35b5c8ae4 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 12 Mar 2019 09:08:10 -0700
-Subject: [PATCH] drm/v3d: Update to upstream IRQ code.
-
----
- drivers/gpu/drm/v3d/v3d_irq.c | 25 +++++++++++++++----------
- 1 file changed, 15 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -168,7 +168,7 @@ v3d_hub_irq(int irq, void *arg)
- int
- v3d_irq_init(struct v3d_dev *v3d)
- {
--      int ret, core;
-+      int irq1, ret, core;
-       INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work);
-@@ -179,24 +179,29 @@ v3d_irq_init(struct v3d_dev *v3d)
-               V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
-       V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
--      if (platform_get_irq(v3d->pdev, 1) < 0) {
--              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-+      irq1 = platform_get_irq(v3d->pdev, 1);
-+      if (irq1 == -EPROBE_DEFER)
-+              return irq1;
-+      if (irq1 > 0) {
-+              ret = devm_request_irq(v3d->dev, irq1,
-                                      v3d_irq, IRQF_SHARED,
--                                     "v3d", v3d);
--              v3d->single_irq_line = true;
--      } else {
-+                                     "v3d_core0", v3d);
-+              if (ret)
-+                      goto fail;
-               ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-                                      v3d_hub_irq, IRQF_SHARED,
-                                      "v3d_hub", v3d);
-               if (ret)
-                       goto fail;
-+      } else {
-+              v3d->single_irq_line = true;
--              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
-+              ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-                                      v3d_irq, IRQF_SHARED,
--                                     "v3d_core0", v3d);
-+                                     "v3d", v3d);
-+              if (ret)
-+                      goto fail;
-       }
--      if (ret)
--              goto fail;
-       v3d_irq_enable(v3d);
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0512-drm-v3d-Add-missing-implicit-synchronization.patch b/target/linux/brcm2708/patches-4.19/950-0512-drm-v3d-Add-missing-implicit-synchronization.patch
new file mode 100644 (file)
index 0000000..9c902c6
--- /dev/null
@@ -0,0 +1,279 @@
+From 7713f79b0a5473eb0b8456d36b99ae00815dd8a1 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 27 Mar 2019 17:44:40 -0700
+Subject: [PATCH] drm/v3d: Add missing implicit synchronization.
+
+It is the expectation of existing userspace (X11 + Mesa, in
+particular) that jobs submitted to the kernel against a shared BO will
+get implicitly synchronized by their submission order.  If we want to
+allow clever userspace to disable implicit synchronization, we should
+do that under its own submit flag (as amdgpu and lima do).
+
+Note that we currently only implicitly sync for the rendering pass,
+not binning -- if you texture-from-pixmap in the binning vertex shader
+(vertex coordinate generation), you'll miss out on synchronization.
+
+Fixes flickering when multiple clients are running in parallel,
+particularly GL apps and compositors.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h   | 10 +---
+ drivers/gpu/drm/v3d/v3d_gem.c   | 98 ++++++++++++++++++++++++++++++---
+ drivers/gpu/drm/v3d/v3d_sched.c | 45 ++-------------
+ 3 files changed, 96 insertions(+), 57 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -186,8 +186,9 @@ struct v3d_job {
+       struct v3d_bo **bo;
+       u32 bo_count;
+-      /* An optional fence userspace can pass in for the job to depend on. */
+-      struct dma_fence *in_fence;
++      struct dma_fence **deps;
++      int deps_count;
++      int deps_size;
+       /* v3d fence to be signaled by IRQ handler when the job is complete. */
+       struct dma_fence *irq_fence;
+@@ -219,11 +220,6 @@ struct v3d_bin_job {
+ struct v3d_render_job {
+       struct v3d_job base;
+-      /* Optional fence for the binner, to depend on before starting
+-       * our job.
+-       */
+-      struct dma_fence *bin_done_fence;
+-
+       /* GPU virtual addresses of the start/end of the CL job. */
+       u32 start, end;
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -218,6 +218,71 @@ v3d_unlock_bo_reservations(struct v3d_bo
+       ww_acquire_fini(acquire_ctx);
+ }
++static int
++v3d_add_dep(struct v3d_job *job, struct dma_fence *fence)
++{
++      if (!fence)
++              return 0;
++
++      if (job->deps_size == job->deps_count) {
++              int new_deps_size = max(job->deps_size * 2, 4);
++              struct dma_fence **new_deps =
++                      krealloc(job->deps, new_deps_size * sizeof(*new_deps),
++                               GFP_KERNEL);
++              if (!new_deps) {
++                      dma_fence_put(fence);
++                      return -ENOMEM;
++              }
++
++              job->deps = new_deps;
++              job->deps_size = new_deps_size;
++      }
++
++      job->deps[job->deps_count++] = fence;
++
++      return 0;
++}
++
++/**
++ * Adds the required implicit fences before executing the job
++ *
++ * Userspace (X11 + Mesa) requires that a job submitted against a shared BO
++ * from one fd will implicitly synchronize against previous jobs submitted
++ * against that BO from other fds.
++ *
++ * Currently we don't bother trying to track the shared BOs, and instead just
++ * sync everything.  However, our synchronization is only for the render pass
++ * -- the binning stage (VS coordinate calculations) ignores implicit sync,
++ * since using shared buffers for texture coordinates seems unlikely, and
++ * implicitly syncing them would break bin/render parallelism.  If we want to
++ * fix that, we should introduce a flag when VS texturing has been used in the
++ * binning stage, or a set of flags for which BOs are sampled during binning.
++ */
++static int
++v3d_add_implicit_fences(struct v3d_job *job, struct v3d_bo *bo)
++{
++      int i, ret, nr_fences;
++      struct dma_fence **fences;
++
++      ret = reservation_object_get_fences_rcu(bo->resv, NULL,
++                                              &nr_fences, &fences);
++      if (ret || !nr_fences)
++              return ret;
++
++      for (i = 0; i < nr_fences; i++) {
++              ret = v3d_add_dep(job, fences[i]);
++              if (ret)
++                      break;
++      }
++
++      /* Free any remaining fences after error. */
++      for (; i < nr_fences; i++)
++              dma_fence_put(fences[i]);
++      kfree(fences);
++
++      return ret;
++}
++
+ /* Takes the reservation lock on all the BOs being referenced, so that
+  * at queue submit time we can update the reservations.
+  *
+@@ -226,10 +291,11 @@ v3d_unlock_bo_reservations(struct v3d_bo
+  * to v3d, so we don't attach dma-buf fences to them.
+  */
+ static int
+-v3d_lock_bo_reservations(struct v3d_bo **bos,
+-                       int bo_count,
++v3d_lock_bo_reservations(struct v3d_job *job,
+                        struct ww_acquire_ctx *acquire_ctx)
+ {
++      struct v3d_bo **bos = job->bo;
++      int bo_count = job->bo_count;
+       int contended_lock = -1;
+       int i, ret;
+@@ -281,6 +347,13 @@ retry:
+        * before we commit the CL to the hardware.
+        */
+       for (i = 0; i < bo_count; i++) {
++              ret = v3d_add_implicit_fences(job, bos[i]);
++              if (ret) {
++                      v3d_unlock_bo_reservations(bos, bo_count,
++                                                 acquire_ctx);
++                      return ret;
++              }
++
+               ret = reservation_object_reserve_shared(bos[i]->resv);
+               if (ret) {
+                       v3d_unlock_bo_reservations(bos, bo_count,
+@@ -383,7 +456,10 @@ v3d_job_free(struct kref *ref)
+       }
+       kvfree(job->bo);
+-      dma_fence_put(job->in_fence);
++      for (i = 0; i < job->deps_count; i++)
++              dma_fence_put(job->deps[i]);
++      kfree(job->deps);
++
+       dma_fence_put(job->irq_fence);
+       dma_fence_put(job->done_fence);
+@@ -464,15 +540,20 @@ v3d_job_init(struct v3d_dev *v3d, struct
+            struct v3d_job *job, void (*free)(struct kref *ref),
+            u32 in_sync)
+ {
++      struct dma_fence *in_fence = NULL;
+       int ret;
+       job->v3d = v3d;
+       job->free = free;
+-      ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
++      ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &in_fence);
+       if (ret == -EINVAL)
+               return ret;
++      ret = v3d_add_dep(job, in_fence);
++      if (ret)
++              return ret;
++
+       kref_init(&job->refcount);
+       return 0;
+@@ -590,8 +671,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       if (ret)
+               goto fail;
+-      ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
+-                                     &acquire_ctx);
++      ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
+       if (ret)
+               goto fail;
+@@ -601,7 +681,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
+               if (ret)
+                       goto fail_unreserve;
+-              render->bin_done_fence = dma_fence_get(bin->base.done_fence);
++              ret = v3d_add_dep(&render->base,
++                                dma_fence_get(bin->base.done_fence));
+       }
+       ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
+@@ -692,8 +773,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       }
+       spin_unlock(&file_priv->table_lock);
+-      ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
+-                                     &acquire_ctx);
++      ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
+       if (ret)
+               goto fail;
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -67,47 +67,10 @@ v3d_job_dependency(struct drm_sched_job
+                  struct drm_sched_entity *s_entity)
+ {
+       struct v3d_job *job = to_v3d_job(sched_job);
+-      struct dma_fence *fence;
+-
+-      fence = job->in_fence;
+-      if (fence) {
+-              job->in_fence = NULL;
+-              return fence;
+-      }
+-
+-      return NULL;
+-}
+-/**
+- * Returns the fences that the render job depends on, one by one.
+- * v3d_job_run() won't be called until all of them have been signaled.
+- */
+-static struct dma_fence *
+-v3d_render_job_dependency(struct drm_sched_job *sched_job,
+-                        struct drm_sched_entity *s_entity)
+-{
+-      struct v3d_render_job *job = to_render_job(sched_job);
+-      struct dma_fence *fence;
+-
+-      fence = v3d_job_dependency(sched_job, s_entity);
+-      if (fence)
+-              return fence;
+-
+-      /* If we had a bin job, the render job definitely depends on
+-       * it. We first have to wait for bin to be scheduled, so that
+-       * its done_fence is created.
+-       */
+-      fence = job->bin_done_fence;
+-      if (fence) {
+-              job->bin_done_fence = NULL;
+-              return fence;
+-      }
+-
+-      /* XXX: Wait on a fence for switching the GMP if necessary,
+-       * and then do so.
+-       */
+-
+-      return fence;
++      if (!job->deps_count)
++              return NULL;
++      return job->deps[--job->deps_count];
+ }
+ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+@@ -329,7 +292,7 @@ static const struct drm_sched_backend_op
+ };
+ static const struct drm_sched_backend_ops v3d_render_sched_ops = {
+-      .dependency = v3d_render_job_dependency,
++      .dependency = v3d_job_dependency,
+       .run_job = v3d_render_job_run,
+       .timedout_job = v3d_render_job_timedout,
+       .free_job = v3d_job_free,
diff --git a/target/linux/brcm2708/patches-4.19/950-0512-drm-v3d-Rename-the-fence-signaled-from-IRQs-to-irq_f.patch b/target/linux/brcm2708/patches-4.19/950-0512-drm-v3d-Rename-the-fence-signaled-from-IRQs-to-irq_f.patch
deleted file mode 100644 (file)
index 55408a0..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-From 0d00e0340c1aa9ce36bdff46f927916fe4903cee Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 27 Dec 2018 14:04:44 -0800
-Subject: [PATCH] drm/v3d: Rename the fence signaled from IRQs to
- "irq_fence".
-
-We have another thing called the "done fence" that tracks when the
-scheduler considers the job done, and having the shared name was
-confusing.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.h   |  4 ++--
- drivers/gpu/drm/v3d/v3d_gem.c   |  6 +++---
- drivers/gpu/drm/v3d/v3d_irq.c   |  6 +++---
- drivers/gpu/drm/v3d/v3d_sched.c | 12 ++++++------
- 4 files changed, 14 insertions(+), 14 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -182,7 +182,7 @@ struct v3d_job {
-       struct dma_fence *in_fence;
-       /* v3d fence to be signaled by IRQ handler when the job is complete. */
--      struct dma_fence *done_fence;
-+      struct dma_fence *irq_fence;
-       /* GPU virtual addresses of the start/end of the CL job. */
-       u32 start, end;
-@@ -229,7 +229,7 @@ struct v3d_tfu_job {
-       struct dma_fence *in_fence;
-       /* v3d fence to be signaled by IRQ handler when the job is complete. */
--      struct dma_fence *done_fence;
-+      struct dma_fence *irq_fence;
-       struct v3d_dev *v3d;
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -381,8 +381,8 @@ v3d_exec_cleanup(struct kref *ref)
-       dma_fence_put(exec->bin.in_fence);
-       dma_fence_put(exec->render.in_fence);
--      dma_fence_put(exec->bin.done_fence);
--      dma_fence_put(exec->render.done_fence);
-+      dma_fence_put(exec->bin.irq_fence);
-+      dma_fence_put(exec->render.irq_fence);
-       dma_fence_put(exec->bin_done_fence);
-       dma_fence_put(exec->render_done_fence);
-@@ -411,7 +411,7 @@ v3d_tfu_job_cleanup(struct kref *ref)
-       unsigned int i;
-       dma_fence_put(job->in_fence);
--      dma_fence_put(job->done_fence);
-+      dma_fence_put(job->irq_fence);
-       for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
-               if (job->bo[i])
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
-       if (intsts & V3D_INT_FLDONE) {
-               struct v3d_fence *fence =
--                      to_v3d_fence(v3d->bin_job->bin.done_fence);
-+                      to_v3d_fence(v3d->bin_job->bin.irq_fence);
-               trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
-               dma_fence_signal(&fence->base);
-@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
-       if (intsts & V3D_INT_FRDONE) {
-               struct v3d_fence *fence =
--                      to_v3d_fence(v3d->render_job->render.done_fence);
-+                      to_v3d_fence(v3d->render_job->render.irq_fence);
-               trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
-               dma_fence_signal(&fence->base);
-@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
-       if (intsts & V3D_HUB_INT_TFUC) {
-               struct v3d_fence *fence =
--                      to_v3d_fence(v3d->tfu_job->done_fence);
-+                      to_v3d_fence(v3d->tfu_job->irq_fence);
-               trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
-               dma_fence_signal(&fence->base);
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -152,9 +152,9 @@ static struct dma_fence *v3d_job_run(str
-       if (IS_ERR(fence))
-               return NULL;
--      if (job->done_fence)
--              dma_fence_put(job->done_fence);
--      job->done_fence = dma_fence_get(fence);
-+      if (job->irq_fence)
-+              dma_fence_put(job->irq_fence);
-+      job->irq_fence = dma_fence_get(fence);
-       trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
-                           job->start, job->end);
-@@ -195,9 +195,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
-               return NULL;
-       v3d->tfu_job = job;
--      if (job->done_fence)
--              dma_fence_put(job->done_fence);
--      job->done_fence = dma_fence_get(fence);
-+      if (job->irq_fence)
-+              dma_fence_put(job->irq_fence);
-+      job->irq_fence = dma_fence_get(fence);
-       trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
diff --git a/target/linux/brcm2708/patches-4.19/950-0513-drm-v3d-Refactor-job-management.patch b/target/linux/brcm2708/patches-4.19/950-0513-drm-v3d-Refactor-job-management.patch
deleted file mode 100644 (file)
index 1192b16..0000000
+++ /dev/null
@@ -1,1104 +0,0 @@
-From ccf319a0265bfdb4a622a52645f159461bc88079 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 27 Dec 2018 12:11:52 -0800
-Subject: [PATCH] drm/v3d: Refactor job management.
-
-The CL submission had two jobs embedded in an exec struct.  When I
-added TFU support, I had to replicate some of the exec stuff and some
-of the job stuff.  As I went to add CSD, it became clear that actually
-what was in exec should just be in the two CL jobs, and it would let
-us share a lot more code between the 4 queues.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.h   |  77 ++++----
- drivers/gpu/drm/v3d/v3d_gem.c   | 331 +++++++++++++++++---------------
- drivers/gpu/drm/v3d/v3d_irq.c   |   8 +-
- drivers/gpu/drm/v3d/v3d_sched.c | 264 ++++++++++++++-----------
- 4 files changed, 373 insertions(+), 307 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -67,8 +67,8 @@ struct v3d_dev {
-       struct work_struct overflow_mem_work;
--      struct v3d_exec_info *bin_job;
--      struct v3d_exec_info *render_job;
-+      struct v3d_bin_job *bin_job;
-+      struct v3d_render_job *render_job;
-       struct v3d_tfu_job *tfu_job;
-       struct v3d_queue_state queue[V3D_MAX_QUEUES];
-@@ -132,7 +132,7 @@ struct v3d_bo {
-       struct list_head vmas;    /* list of v3d_vma */
-       /* List entry for the BO's position in
--       * v3d_exec_info->unref_list
-+       * v3d_render_job->unref_list
-        */
-       struct list_head unref_head;
-@@ -176,7 +176,15 @@ to_v3d_fence(struct dma_fence *fence)
- struct v3d_job {
-       struct drm_sched_job base;
--      struct v3d_exec_info *exec;
-+      struct kref refcount;
-+
-+      struct v3d_dev *v3d;
-+
-+      /* This is the array of BOs that were looked up at the start
-+       * of submission.
-+       */
-+      struct v3d_bo **bo;
-+      u32 bo_count;
-       /* An optional fence userspace can pass in for the job to depend on. */
-       struct dma_fence *in_fence;
-@@ -184,59 +192,53 @@ struct v3d_job {
-       /* v3d fence to be signaled by IRQ handler when the job is complete. */
-       struct dma_fence *irq_fence;
-+      /* scheduler fence for when the job is considered complete and
-+       * the BO reservations can be released.
-+       */
-+      struct dma_fence *done_fence;
-+
-+      /* Callback for the freeing of the job on refcount going to 0. */
-+      void (*free)(struct kref *ref);
-+};
-+
-+struct v3d_bin_job {
-+      struct v3d_job base;
-+
-       /* GPU virtual addresses of the start/end of the CL job. */
-       u32 start, end;
-       u32 timedout_ctca, timedout_ctra;
--};
--struct v3d_exec_info {
--      struct v3d_dev *v3d;
-+      /* Corresponding render job, for attaching our overflow memory. */
-+      struct v3d_render_job *render;
-+
-+      /* Submitted tile memory allocation start/size, tile state. */
-+      u32 qma, qms, qts;
-+};
--      struct v3d_job bin, render;
-+struct v3d_render_job {
-+      struct v3d_job base;
--      /* Fence for when the scheduler considers the binner to be
--       * done, for render to depend on.
-+      /* Optional fence for the binner, to depend on before starting
-+       * our job.
-        */
-       struct dma_fence *bin_done_fence;
--      /* Fence for when the scheduler considers the render to be
--       * done, for when the BOs reservations should be complete.
--       */
--      struct dma_fence *render_done_fence;
--
--      struct kref refcount;
-+      /* GPU virtual addresses of the start/end of the CL job. */
-+      u32 start, end;
--      /* This is the array of BOs that were looked up at the start of exec. */
--      struct v3d_bo **bo;
--      u32 bo_count;
-+      u32 timedout_ctca, timedout_ctra;
-       /* List of overflow BOs used in the job that need to be
-        * released once the job is complete.
-        */
-       struct list_head unref_list;
--
--      /* Submitted tile memory allocation start/size, tile state. */
--      u32 qma, qms, qts;
- };
- struct v3d_tfu_job {
--      struct drm_sched_job base;
-+      struct v3d_job base;
-       struct drm_v3d_submit_tfu args;
--
--      /* An optional fence userspace can pass in for the job to depend on. */
--      struct dma_fence *in_fence;
--
--      /* v3d fence to be signaled by IRQ handler when the job is complete. */
--      struct dma_fence *irq_fence;
--
--      struct v3d_dev *v3d;
--
--      struct kref refcount;
--
--      /* This is the array of BOs that were looked up at the start of exec. */
--      struct v3d_bo *bo[4];
- };
- /**
-@@ -306,8 +308,7 @@ int v3d_submit_tfu_ioctl(struct drm_devi
-                        struct drm_file *file_priv);
- int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
--void v3d_exec_put(struct v3d_exec_info *exec);
--void v3d_tfu_job_put(struct v3d_tfu_job *exec);
-+void v3d_job_put(struct v3d_job *job);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -293,11 +293,11 @@ retry:
- }
- /**
-- * v3d_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
-+ * v3d_lookup_bos() - Sets up job->bo[] with the GEM objects
-  * referenced by the job.
-  * @dev: DRM device
-  * @file_priv: DRM file for this fd
-- * @exec: V3D job being set up
-+ * @job: V3D job being set up
-  *
-  * The command validator needs to reference BOs by their index within
-  * the submitted job's BO list.  This does the validation of the job's
-@@ -307,18 +307,19 @@ retry:
-  * failure, because that will happen at v3d_exec_cleanup() time.
-  */
- static int
--v3d_cl_lookup_bos(struct drm_device *dev,
--                struct drm_file *file_priv,
--                struct drm_v3d_submit_cl *args,
--                struct v3d_exec_info *exec)
-+v3d_lookup_bos(struct drm_device *dev,
-+             struct drm_file *file_priv,
-+             struct v3d_job *job,
-+             u64 bo_handles,
-+             u32 bo_count)
- {
-       u32 *handles;
-       int ret = 0;
-       int i;
--      exec->bo_count = args->bo_handle_count;
-+      job->bo_count = bo_count;
--      if (!exec->bo_count) {
-+      if (!job->bo_count) {
-               /* See comment on bo_index for why we have to check
-                * this.
-                */
-@@ -326,15 +327,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
-               return -EINVAL;
-       }
--      exec->bo = kvmalloc_array(exec->bo_count,
--                                sizeof(struct drm_gem_cma_object *),
--                                GFP_KERNEL | __GFP_ZERO);
--      if (!exec->bo) {
-+      job->bo = kvmalloc_array(job->bo_count,
-+                               sizeof(struct drm_gem_cma_object *),
-+                               GFP_KERNEL | __GFP_ZERO);
-+      if (!job->bo) {
-               DRM_DEBUG("Failed to allocate validated BO pointers\n");
-               return -ENOMEM;
-       }
--      handles = kvmalloc_array(exec->bo_count, sizeof(u32), GFP_KERNEL);
-+      handles = kvmalloc_array(job->bo_count, sizeof(u32), GFP_KERNEL);
-       if (!handles) {
-               ret = -ENOMEM;
-               DRM_DEBUG("Failed to allocate incoming GEM handles\n");
-@@ -342,15 +343,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
-       }
-       if (copy_from_user(handles,
--                         (void __user *)(uintptr_t)args->bo_handles,
--                         exec->bo_count * sizeof(u32))) {
-+                         (void __user *)(uintptr_t)bo_handles,
-+                         job->bo_count * sizeof(u32))) {
-               ret = -EFAULT;
-               DRM_DEBUG("Failed to copy in GEM handles\n");
-               goto fail;
-       }
-       spin_lock(&file_priv->table_lock);
--      for (i = 0; i < exec->bo_count; i++) {
-+      for (i = 0; i < job->bo_count; i++) {
-               struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
-                                                    handles[i]);
-               if (!bo) {
-@@ -361,7 +362,7 @@ v3d_cl_lookup_bos(struct drm_device *dev
-                       goto fail;
-               }
-               drm_gem_object_get(bo);
--              exec->bo[i] = to_v3d_bo(bo);
-+              job->bo[i] = to_v3d_bo(bo);
-       }
-       spin_unlock(&file_priv->table_lock);
-@@ -371,59 +372,41 @@ fail:
- }
- static void
--v3d_exec_cleanup(struct kref *ref)
-+v3d_job_free(struct kref *ref)
- {
--      struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
--                                                refcount);
--      unsigned int i;
--      struct v3d_bo *bo, *save;
--
--      dma_fence_put(exec->bin.in_fence);
--      dma_fence_put(exec->render.in_fence);
--
--      dma_fence_put(exec->bin.irq_fence);
--      dma_fence_put(exec->render.irq_fence);
--
--      dma_fence_put(exec->bin_done_fence);
--      dma_fence_put(exec->render_done_fence);
--
--      for (i = 0; i < exec->bo_count; i++)
--              drm_gem_object_put_unlocked(&exec->bo[i]->base);
--      kvfree(exec->bo);
-+      struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
-+      int i;
--      list_for_each_entry_safe(bo, save, &exec->unref_list, unref_head) {
--              drm_gem_object_put_unlocked(&bo->base);
-+      for (i = 0; i < job->bo_count; i++) {
-+              if (job->bo[i])
-+                      drm_gem_object_put_unlocked(&job->bo[i]->base);
-       }
-+      kvfree(job->bo);
--      kfree(exec);
--}
-+      dma_fence_put(job->in_fence);
-+      dma_fence_put(job->irq_fence);
-+      dma_fence_put(job->done_fence);
--void v3d_exec_put(struct v3d_exec_info *exec)
--{
--      kref_put(&exec->refcount, v3d_exec_cleanup);
-+      kfree(job);
- }
- static void
--v3d_tfu_job_cleanup(struct kref *ref)
-+v3d_render_job_free(struct kref *ref)
- {
--      struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
--                                             refcount);
--      unsigned int i;
--
--      dma_fence_put(job->in_fence);
--      dma_fence_put(job->irq_fence);
-+      struct v3d_render_job *job = container_of(ref, struct v3d_render_job,
-+                                                base.refcount);
-+      struct v3d_bo *bo, *save;
--      for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
--              if (job->bo[i])
--                      drm_gem_object_put_unlocked(&job->bo[i]->base);
-+      list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) {
-+              drm_gem_object_put_unlocked(&bo->base);
-       }
--      kfree(job);
-+      v3d_job_free(ref);
- }
--void v3d_tfu_job_put(struct v3d_tfu_job *job)
-+void v3d_job_put(struct v3d_job *job)
- {
--      kref_put(&job->refcount, v3d_tfu_job_cleanup);
-+      kref_put(&job->refcount, job->free);
- }
- int
-@@ -476,6 +459,65 @@ v3d_wait_bo_ioctl(struct drm_device *dev
-       return ret;
- }
-+static int
-+v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
-+           struct v3d_job *job, void (*free)(struct kref *ref),
-+           u32 in_sync)
-+{
-+      int ret;
-+
-+      job->v3d = v3d;
-+      job->free = free;
-+
-+      ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
-+      if (ret == -EINVAL)
-+              return ret;
-+
-+      kref_init(&job->refcount);
-+
-+      return 0;
-+}
-+
-+static int
-+v3d_push_job(struct v3d_file_priv *v3d_priv,
-+           struct v3d_job *job, enum v3d_queue queue)
-+{
-+      int ret;
-+
-+      ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
-+                               v3d_priv);
-+      if (ret)
-+              return ret;
-+
-+      job->done_fence = dma_fence_get(&job->base.s_fence->finished);
-+
-+      /* put by scheduler job completion */
-+      kref_get(&job->refcount);
-+
-+      drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[queue]);
-+
-+      return 0;
-+}
-+
-+static void
-+v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
-+                                       struct v3d_job *job,
-+                                       struct ww_acquire_ctx *acquire_ctx,
-+                                       u32 out_sync)
-+{
-+      struct drm_syncobj *sync_out;
-+
-+      v3d_attach_object_fences(job->bo, job->bo_count, job->done_fence);
-+      v3d_unlock_bo_reservations(job->bo, job->bo_count, acquire_ctx);
-+
-+      /* Update the return sync object for the job */
-+      sync_out = drm_syncobj_find(file_priv, out_sync);
-+      if (sync_out) {
-+              drm_syncobj_replace_fence(sync_out, job->done_fence);
-+              drm_syncobj_put(sync_out);
-+      }
-+}
-+
- /**
-  * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.
-  * @dev: DRM device
-@@ -495,9 +537,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       struct v3d_dev *v3d = to_v3d_dev(dev);
-       struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
-       struct drm_v3d_submit_cl *args = data;
--      struct v3d_exec_info *exec;
-+      struct v3d_bin_job *bin = NULL;
-+      struct v3d_render_job *render;
-       struct ww_acquire_ctx acquire_ctx;
--      struct drm_syncobj *sync_out;
-       int ret = 0;
-       trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
-@@ -507,95 +549,84 @@ v3d_submit_cl_ioctl(struct drm_device *d
-               return -EINVAL;
-       }
--      exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
--      if (!exec)
-+      render = kcalloc(1, sizeof(*render), GFP_KERNEL);
-+      if (!render)
-               return -ENOMEM;
--      kref_init(&exec->refcount);
-+      render->start = args->rcl_start;
-+      render->end = args->rcl_end;
-+      INIT_LIST_HEAD(&render->unref_list);
--      ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
--                                   0, &exec->bin.in_fence);
--      if (ret == -EINVAL)
--              goto fail;
-+      ret = v3d_job_init(v3d, file_priv, &render->base,
-+                         v3d_render_job_free, args->in_sync_rcl);
-+      if (ret) {
-+              kfree(bin);
-+              kfree(render);
-+              return ret;
-+      }
--      ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
--                                   0, &exec->render.in_fence);
--      if (ret == -EINVAL)
--              goto fail;
-+      if (args->bcl_start != args->bcl_end) {
-+              bin = kcalloc(1, sizeof(*bin), GFP_KERNEL);
-+              if (!bin)
-+                      return -ENOMEM;
-+
-+              ret = v3d_job_init(v3d, file_priv, &bin->base,
-+                                 v3d_job_free, args->in_sync_bcl);
-+              if (ret) {
-+                      v3d_job_put(&render->base);
-+                      return ret;
-+              }
--      exec->qma = args->qma;
--      exec->qms = args->qms;
--      exec->qts = args->qts;
--      exec->bin.exec = exec;
--      exec->bin.start = args->bcl_start;
--      exec->bin.end = args->bcl_end;
--      exec->render.exec = exec;
--      exec->render.start = args->rcl_start;
--      exec->render.end = args->rcl_end;
--      exec->v3d = v3d;
--      INIT_LIST_HEAD(&exec->unref_list);
-+              bin->start = args->bcl_start;
-+              bin->end = args->bcl_end;
-+              bin->qma = args->qma;
-+              bin->qms = args->qms;
-+              bin->qts = args->qts;
-+              bin->render = render;
-+      }
--      ret = v3d_cl_lookup_bos(dev, file_priv, args, exec);
-+      ret = v3d_lookup_bos(dev, file_priv, &render->base,
-+                           args->bo_handles, args->bo_handle_count);
-       if (ret)
-               goto fail;
--      ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
-+      ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
-                                      &acquire_ctx);
-       if (ret)
-               goto fail;
-       mutex_lock(&v3d->sched_lock);
--      if (exec->bin.start != exec->bin.end) {
--              ret = drm_sched_job_init(&exec->bin.base,
--                                       &v3d_priv->sched_entity[V3D_BIN],
--                                       v3d_priv);
-+      if (bin) {
-+              ret = v3d_push_job(v3d_priv, &bin->base, V3D_BIN);
-               if (ret)
-                       goto fail_unreserve;
--              exec->bin_done_fence =
--                      dma_fence_get(&exec->bin.base.s_fence->finished);
--
--              kref_get(&exec->refcount); /* put by scheduler job completion */
--              drm_sched_entity_push_job(&exec->bin.base,
--                                        &v3d_priv->sched_entity[V3D_BIN]);
-+              render->bin_done_fence = dma_fence_get(bin->base.done_fence);
-       }
--      ret = drm_sched_job_init(&exec->render.base,
--                               &v3d_priv->sched_entity[V3D_RENDER],
--                               v3d_priv);
-+      ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
-       if (ret)
-               goto fail_unreserve;
--
--      exec->render_done_fence =
--              dma_fence_get(&exec->render.base.s_fence->finished);
--
--      kref_get(&exec->refcount); /* put by scheduler job completion */
--      drm_sched_entity_push_job(&exec->render.base,
--                                &v3d_priv->sched_entity[V3D_RENDER]);
-       mutex_unlock(&v3d->sched_lock);
--      v3d_attach_object_fences(exec->bo, exec->bo_count,
--                               exec->render_done_fence);
--
--      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
--
--      /* Update the return sync object for the */
--      sync_out = drm_syncobj_find(file_priv, args->out_sync);
--      if (sync_out) {
--              drm_syncobj_replace_fence(sync_out,
--                                        exec->render_done_fence);
--              drm_syncobj_put(sync_out);
--      }
--
--      v3d_exec_put(exec);
-+      v3d_attach_fences_and_unlock_reservation(file_priv,
-+                                               &render->base, &acquire_ctx,
-+                                               args->out_sync);
-+
-+      if (bin)
-+              v3d_job_put(&bin->base);
-+      v3d_job_put(&render->base);
-       return 0;
- fail_unreserve:
-       mutex_unlock(&v3d->sched_lock);
--      v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
-+      v3d_unlock_bo_reservations(render->base.bo,
-+                                 render->base.bo_count, &acquire_ctx);
- fail:
--      v3d_exec_put(exec);
-+      if (bin)
-+              v3d_job_put(&bin->base);
-+      v3d_job_put(&render->base);
-       return ret;
- }
-@@ -618,10 +649,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       struct drm_v3d_submit_tfu *args = data;
-       struct v3d_tfu_job *job;
-       struct ww_acquire_ctx acquire_ctx;
--      struct drm_syncobj *sync_out;
--      struct dma_fence *sched_done_fence;
-       int ret = 0;
--      int bo_count;
-       trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
-@@ -629,75 +657,66 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       if (!job)
-               return -ENOMEM;
--      kref_init(&job->refcount);
--
--      ret = drm_syncobj_find_fence(file_priv, args->in_sync,
--                                   0, &job->in_fence);
--      if (ret == -EINVAL)
--              goto fail;
-+      ret = v3d_job_init(v3d, file_priv, &job->base,
-+                         v3d_job_free, args->in_sync);
-+      if (ret) {
-+              kfree(job);
-+              return ret;
-+      }
-+      job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles),
-+                             sizeof(*job->base.bo), GFP_KERNEL);
-       job->args = *args;
--      job->v3d = v3d;
-       spin_lock(&file_priv->table_lock);
--      for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
-+      for (job->base.bo_count = 0;
-+           job->base.bo_count < ARRAY_SIZE(args->bo_handles);
-+           job->base.bo_count++) {
-               struct drm_gem_object *bo;
--              if (!args->bo_handles[bo_count])
-+              if (!args->bo_handles[job->base.bo_count])
-                       break;
-               bo = idr_find(&file_priv->object_idr,
--                            args->bo_handles[bo_count]);
-+                            args->bo_handles[job->base.bo_count]);
-               if (!bo) {
-                       DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
--                                bo_count, args->bo_handles[bo_count]);
-+                                job->base.bo_count,
-+                                args->bo_handles[job->base.bo_count]);
-                       ret = -ENOENT;
-                       spin_unlock(&file_priv->table_lock);
-                       goto fail;
-               }
-               drm_gem_object_get(bo);
--              job->bo[bo_count] = to_v3d_bo(bo);
-+              job->base.bo[job->base.bo_count] = to_v3d_bo(bo);
-       }
-       spin_unlock(&file_priv->table_lock);
--      ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
-+      ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
-+                                     &acquire_ctx);
-       if (ret)
-               goto fail;
-       mutex_lock(&v3d->sched_lock);
--      ret = drm_sched_job_init(&job->base,
--                               &v3d_priv->sched_entity[V3D_TFU],
--                               v3d_priv);
-+      ret = v3d_push_job(v3d_priv, &job->base, V3D_TFU);
-       if (ret)
-               goto fail_unreserve;
--
--      sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
--
--      kref_get(&job->refcount); /* put by scheduler job completion */
--      drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
-       mutex_unlock(&v3d->sched_lock);
--      v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
--
--      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
--
--      /* Update the return sync object */
--      sync_out = drm_syncobj_find(file_priv, args->out_sync);
--      if (sync_out) {
--              drm_syncobj_replace_fence(sync_out, sched_done_fence);
--              drm_syncobj_put(sync_out);
--      }
--      dma_fence_put(sched_done_fence);
-+      v3d_attach_fences_and_unlock_reservation(file_priv,
-+                                               &job->base, &acquire_ctx,
-+                                               args->out_sync);
--      v3d_tfu_job_put(job);
-+      v3d_job_put(&job->base);
-       return 0;
- fail_unreserve:
-       mutex_unlock(&v3d->sched_lock);
--      v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
-+      v3d_unlock_bo_reservations(job->base.bo, job->base.bo_count,
-+                                 &acquire_ctx);
- fail:
--      v3d_tfu_job_put(job);
-+      v3d_job_put(&job->base);
-       return ret;
- }
-@@ -755,7 +774,7 @@ v3d_gem_destroy(struct drm_device *dev)
-       v3d_sched_fini(v3d);
--      /* Waiting for exec to finish would need to be done before
-+      /* Waiting for jobs to finish would need to be done before
-        * unregistering V3D.
-        */
-       WARN_ON(v3d->bin_job);
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -60,7 +60,7 @@ v3d_overflow_mem_work(struct work_struct
-       }
-       drm_gem_object_get(&bo->base);
--      list_add_tail(&bo->unref_head, &v3d->bin_job->unref_list);
-+      list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
-       spin_unlock_irqrestore(&v3d->job_lock, irqflags);
-       V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
-@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
-       if (intsts & V3D_INT_FLDONE) {
-               struct v3d_fence *fence =
--                      to_v3d_fence(v3d->bin_job->bin.irq_fence);
-+                      to_v3d_fence(v3d->bin_job->base.irq_fence);
-               trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
-               dma_fence_signal(&fence->base);
-@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
-       if (intsts & V3D_INT_FRDONE) {
-               struct v3d_fence *fence =
--                      to_v3d_fence(v3d->render_job->render.irq_fence);
-+                      to_v3d_fence(v3d->render_job->base.irq_fence);
-               trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
-               dma_fence_signal(&fence->base);
-@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
-       if (intsts & V3D_HUB_INT_TFUC) {
-               struct v3d_fence *fence =
--                      to_v3d_fence(v3d->tfu_job->irq_fence);
-+                      to_v3d_fence(v3d->tfu_job->base.irq_fence);
-               trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
-               dma_fence_signal(&fence->base);
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -30,39 +30,43 @@ to_v3d_job(struct drm_sched_job *sched_j
-       return container_of(sched_job, struct v3d_job, base);
- }
--static struct v3d_tfu_job *
--to_tfu_job(struct drm_sched_job *sched_job)
-+static struct v3d_bin_job *
-+to_bin_job(struct drm_sched_job *sched_job)
- {
--      return container_of(sched_job, struct v3d_tfu_job, base);
-+      return container_of(sched_job, struct v3d_bin_job, base.base);
- }
--static void
--v3d_job_free(struct drm_sched_job *sched_job)
-+static struct v3d_render_job *
-+to_render_job(struct drm_sched_job *sched_job)
- {
--      struct v3d_job *job = to_v3d_job(sched_job);
-+      return container_of(sched_job, struct v3d_render_job, base.base);
-+}
--      v3d_exec_put(job->exec);
-+static struct v3d_tfu_job *
-+to_tfu_job(struct drm_sched_job *sched_job)
-+{
-+      return container_of(sched_job, struct v3d_tfu_job, base.base);
- }
- static void
--v3d_tfu_job_free(struct drm_sched_job *sched_job)
-+v3d_job_free(struct drm_sched_job *sched_job)
- {
--      struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+      struct v3d_job *job = to_v3d_job(sched_job);
--      v3d_tfu_job_put(job);
-+      v3d_job_put(job);
- }
- /**
-- * Returns the fences that the bin or render job depends on, one by one.
-- * v3d_job_run() won't be called until all of them have been signaled.
-+ * Returns the fences that the job depends on, one by one.
-+ *
-+ * If placed in the scheduler's .dependency method, the corresponding
-+ * .run_job won't be called until all of them have been signaled.
-  */
- static struct dma_fence *
- v3d_job_dependency(struct drm_sched_job *sched_job,
-                  struct drm_sched_entity *s_entity)
- {
-       struct v3d_job *job = to_v3d_job(sched_job);
--      struct v3d_exec_info *exec = job->exec;
--      enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
-       struct dma_fence *fence;
-       fence = job->in_fence;
-@@ -71,113 +75,132 @@ v3d_job_dependency(struct drm_sched_job
-               return fence;
-       }
--      if (q == V3D_RENDER) {
--              /* If we had a bin job, the render job definitely depends on
--               * it. We first have to wait for bin to be scheduled, so that
--               * its done_fence is created.
--               */
--              fence = exec->bin_done_fence;
--              if (fence) {
--                      exec->bin_done_fence = NULL;
--                      return fence;
--              }
--      }
--
--      /* XXX: Wait on a fence for switching the GMP if necessary,
--       * and then do so.
--       */
--
--      return fence;
-+      return NULL;
- }
- /**
-- * Returns the fences that the TFU job depends on, one by one.
-- * v3d_tfu_job_run() won't be called until all of them have been
-- * signaled.
-+ * Returns the fences that the render job depends on, one by one.
-+ * v3d_job_run() won't be called until all of them have been signaled.
-  */
- static struct dma_fence *
--v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
--                     struct drm_sched_entity *s_entity)
-+v3d_render_job_dependency(struct drm_sched_job *sched_job,
-+                        struct drm_sched_entity *s_entity)
- {
--      struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+      struct v3d_render_job *job = to_render_job(sched_job);
-       struct dma_fence *fence;
--      fence = job->in_fence;
-+      fence = v3d_job_dependency(sched_job, s_entity);
-+      if (fence)
-+              return fence;
-+
-+      /* If we had a bin job, the render job definitely depends on
-+       * it. We first have to wait for bin to be scheduled, so that
-+       * its done_fence is created.
-+       */
-+      fence = job->bin_done_fence;
-       if (fence) {
--              job->in_fence = NULL;
-+              job->bin_done_fence = NULL;
-               return fence;
-       }
--      return NULL;
-+      /* XXX: Wait on a fence for switching the GMP if necessary,
-+       * and then do so.
-+       */
-+
-+      return fence;
- }
--static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
-+static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
- {
--      struct v3d_job *job = to_v3d_job(sched_job);
--      struct v3d_exec_info *exec = job->exec;
--      enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
--      struct v3d_dev *v3d = exec->v3d;
-+      struct v3d_bin_job *job = to_bin_job(sched_job);
-+      struct v3d_dev *v3d = job->base.v3d;
-       struct drm_device *dev = &v3d->drm;
-       struct dma_fence *fence;
-       unsigned long irqflags;
--      if (unlikely(job->base.s_fence->finished.error))
-+      if (unlikely(job->base.base.s_fence->finished.error))
-               return NULL;
-       /* Lock required around bin_job update vs
-        * v3d_overflow_mem_work().
-        */
-       spin_lock_irqsave(&v3d->job_lock, irqflags);
--      if (q == V3D_BIN) {
--              v3d->bin_job = job->exec;
-+      v3d->bin_job = job;
-+      /* Clear out the overflow allocation, so we don't
-+       * reuse the overflow attached to a previous job.
-+       */
-+      V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
-+      spin_unlock_irqrestore(&v3d->job_lock, irqflags);
-+
-+      v3d_invalidate_caches(v3d);
--              /* Clear out the overflow allocation, so we don't
--               * reuse the overflow attached to a previous job.
--               */
--              V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
--      } else {
--              v3d->render_job = job->exec;
-+      fence = v3d_fence_create(v3d, V3D_BIN);
-+      if (IS_ERR(fence))
-+              return NULL;
-+
-+      if (job->base.irq_fence)
-+              dma_fence_put(job->base.irq_fence);
-+      job->base.irq_fence = dma_fence_get(fence);
-+
-+      trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
-+                          job->start, job->end);
-+
-+      /* Set the current and end address of the control list.
-+       * Writing the end register is what starts the job.
-+       */
-+      if (job->qma) {
-+              V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, job->qma);
-+              V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, job->qms);
-       }
--      spin_unlock_irqrestore(&v3d->job_lock, irqflags);
-+      if (job->qts) {
-+              V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
-+                             V3D_CLE_CT0QTS_ENABLE |
-+                             job->qts);
-+      }
-+      V3D_CORE_WRITE(0, V3D_CLE_CT0QBA, job->start);
-+      V3D_CORE_WRITE(0, V3D_CLE_CT0QEA, job->end);
-+
-+      return fence;
-+}
-+
-+static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_render_job *job = to_render_job(sched_job);
-+      struct v3d_dev *v3d = job->base.v3d;
-+      struct drm_device *dev = &v3d->drm;
-+      struct dma_fence *fence;
-+
-+      if (unlikely(job->base.base.s_fence->finished.error))
-+              return NULL;
--      /* Can we avoid this flush when q==RENDER?  We need to be
--       * careful of scheduling, though -- imagine job0 rendering to
--       * texture and job1 reading, and them being executed as bin0,
--       * bin1, render0, render1, so that render1's flush at bin time
-+      v3d->render_job = job;
-+
-+      /* Can we avoid this flush?  We need to be careful of
-+       * scheduling, though -- imagine job0 rendering to texture and
-+       * job1 reading, and them being executed as bin0, bin1,
-+       * render0, render1, so that render1's flush at bin time
-        * wasn't enough.
-        */
-       v3d_invalidate_caches(v3d);
--      fence = v3d_fence_create(v3d, q);
-+      fence = v3d_fence_create(v3d, V3D_RENDER);
-       if (IS_ERR(fence))
-               return NULL;
--      if (job->irq_fence)
--              dma_fence_put(job->irq_fence);
--      job->irq_fence = dma_fence_get(fence);
-+      if (job->base.irq_fence)
-+              dma_fence_put(job->base.irq_fence);
-+      job->base.irq_fence = dma_fence_get(fence);
--      trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
-+      trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
-                           job->start, job->end);
--      if (q == V3D_BIN) {
--              if (exec->qma) {
--                      V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, exec->qma);
--                      V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, exec->qms);
--              }
--              if (exec->qts) {
--                      V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
--                                     V3D_CLE_CT0QTS_ENABLE |
--                                     exec->qts);
--              }
--      } else {
--              /* XXX: Set the QCFG */
--      }
-+      /* XXX: Set the QCFG */
-       /* Set the current and end address of the control list.
-        * Writing the end register is what starts the job.
-        */
--      V3D_CORE_WRITE(0, V3D_CLE_CTNQBA(q), job->start);
--      V3D_CORE_WRITE(0, V3D_CLE_CTNQEA(q), job->end);
-+      V3D_CORE_WRITE(0, V3D_CLE_CT1QBA, job->start);
-+      V3D_CORE_WRITE(0, V3D_CLE_CT1QEA, job->end);
-       return fence;
- }
-@@ -186,7 +209,7 @@ static struct dma_fence *
- v3d_tfu_job_run(struct drm_sched_job *sched_job)
- {
-       struct v3d_tfu_job *job = to_tfu_job(sched_job);
--      struct v3d_dev *v3d = job->v3d;
-+      struct v3d_dev *v3d = job->base.v3d;
-       struct drm_device *dev = &v3d->drm;
-       struct dma_fence *fence;
-@@ -195,9 +218,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
-               return NULL;
-       v3d->tfu_job = job;
--      if (job->irq_fence)
--              dma_fence_put(job->irq_fence);
--      job->irq_fence = dma_fence_get(fence);
-+      if (job->base.irq_fence)
-+              dma_fence_put(job->base.irq_fence);
-+      job->base.irq_fence = dma_fence_get(fence);
-       trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
-@@ -247,25 +270,23 @@ v3d_gpu_reset_for_timeout(struct v3d_dev
-       mutex_unlock(&v3d->reset_lock);
- }
-+/* If the current address or return address have changed, then the GPU
-+ * has probably made progress and we should delay the reset.  This
-+ * could fail if the GPU got in an infinite loop in the CL, but that
-+ * is pretty unlikely outside of an i-g-t testcase.
-+ */
- static void
--v3d_job_timedout(struct drm_sched_job *sched_job)
-+v3d_cl_job_timedout(struct drm_sched_job *sched_job, enum v3d_queue q,
-+                    u32 *timedout_ctca, u32 *timedout_ctra)
- {
-       struct v3d_job *job = to_v3d_job(sched_job);
--      struct v3d_exec_info *exec = job->exec;
--      struct v3d_dev *v3d = exec->v3d;
--      enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
--      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
--      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
--
--      /* If the current address or return address have changed, then
--       * the GPU has probably made progress and we should delay the
--       * reset.  This could fail if the GPU got in an infinite loop
--       * in the CL, but that is pretty unlikely outside of an i-g-t
--       * testcase.
--       */
--      if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
--              job->timedout_ctca = ctca;
--              job->timedout_ctra = ctra;
-+      struct v3d_dev *v3d = job->v3d;
-+      u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(q));
-+      u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(q));
-+
-+      if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
-+              *timedout_ctca = ctca;
-+              *timedout_ctra = ctra;
-               schedule_delayed_work(&job->base.work_tdr,
-                                     job->base.sched->timeout);
-               return;
-@@ -275,25 +296,50 @@ v3d_job_timedout(struct drm_sched_job *s
- }
- static void
-+v3d_bin_job_timedout(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_bin_job *job = to_bin_job(sched_job);
-+
-+      v3d_cl_job_timedout(sched_job, V3D_BIN,
-+                          &job->timedout_ctca, &job->timedout_ctra);
-+}
-+
-+static void
-+v3d_render_job_timedout(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_render_job *job = to_render_job(sched_job);
-+
-+      v3d_cl_job_timedout(sched_job, V3D_RENDER,
-+                          &job->timedout_ctca, &job->timedout_ctra);
-+}
-+
-+static void
- v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
- {
--      struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+      struct v3d_job *job = to_v3d_job(sched_job);
-       v3d_gpu_reset_for_timeout(job->v3d, sched_job);
- }
--static const struct drm_sched_backend_ops v3d_sched_ops = {
-+static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
-       .dependency = v3d_job_dependency,
--      .run_job = v3d_job_run,
--      .timedout_job = v3d_job_timedout,
--      .free_job = v3d_job_free
-+      .run_job = v3d_bin_job_run,
-+      .timedout_job = v3d_bin_job_timedout,
-+      .free_job = v3d_job_free,
-+};
-+
-+static const struct drm_sched_backend_ops v3d_render_sched_ops = {
-+      .dependency = v3d_render_job_dependency,
-+      .run_job = v3d_render_job_run,
-+      .timedout_job = v3d_render_job_timedout,
-+      .free_job = v3d_job_free,
- };
- static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
--      .dependency = v3d_tfu_job_dependency,
-+      .dependency = v3d_job_dependency,
-       .run_job = v3d_tfu_job_run,
-       .timedout_job = v3d_tfu_job_timedout,
--      .free_job = v3d_tfu_job_free
-+      .free_job = v3d_job_free,
- };
- int
-@@ -305,7 +351,7 @@ v3d_sched_init(struct v3d_dev *v3d)
-       int ret;
-       ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,
--                           &v3d_sched_ops,
-+                           &v3d_bin_sched_ops,
-                            hw_jobs_limit, job_hang_limit,
-                            msecs_to_jiffies(hang_limit_ms),
-                            "v3d_bin");
-@@ -315,7 +361,7 @@ v3d_sched_init(struct v3d_dev *v3d)
-       }
-       ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
--                           &v3d_sched_ops,
-+                           &v3d_render_sched_ops,
-                            hw_jobs_limit, job_hang_limit,
-                            msecs_to_jiffies(hang_limit_ms),
-                            "v3d_render");
diff --git a/target/linux/brcm2708/patches-4.19/950-0513-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch b/target/linux/brcm2708/patches-4.19/950-0513-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch
new file mode 100644 (file)
index 0000000..6a3a6b1
--- /dev/null
@@ -0,0 +1,44 @@
+From b0fedd829bb6725fef7b2667c85badc6b4a8e5e0 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 28 Mar 2019 11:58:51 -0700
+Subject: [PATCH] drm/vc4: Fix synchronization firmwarekms against GL
+ rendering.
+
+We would present the framebuffer immediately without waiting for
+rendering to finish first, resulting in stuttering and flickering as a
+window was dragged around when the GPU was busy enough to not just win
+the race.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -15,6 +15,7 @@
+  */
+ #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"
+@@ -291,7 +292,7 @@ static const struct drm_plane_funcs vc4_
+ };
+ static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
+-      .prepare_fb = NULL,
++      .prepare_fb = drm_gem_fb_prepare_fb,
+       .cleanup_fb = NULL,
+       .atomic_check = vc4_plane_atomic_check,
+       .atomic_update = vc4_primary_plane_atomic_update,
+@@ -299,7 +300,7 @@ static const struct drm_plane_helper_fun
+ };
+ static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
+-      .prepare_fb = NULL,
++      .prepare_fb = drm_gem_fb_prepare_fb,
+       .cleanup_fb = NULL,
+       .atomic_check = vc4_plane_atomic_check,
+       .atomic_update = vc4_cursor_plane_atomic_update,
diff --git a/target/linux/brcm2708/patches-4.19/950-0514-drm-v3d-Add-missing-implicit-synchronization.patch b/target/linux/brcm2708/patches-4.19/950-0514-drm-v3d-Add-missing-implicit-synchronization.patch
deleted file mode 100644 (file)
index 9c902c6..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-From 7713f79b0a5473eb0b8456d36b99ae00815dd8a1 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 27 Mar 2019 17:44:40 -0700
-Subject: [PATCH] drm/v3d: Add missing implicit synchronization.
-
-It is the expectation of existing userspace (X11 + Mesa, in
-particular) that jobs submitted to the kernel against a shared BO will
-get implicitly synchronized by their submission order.  If we want to
-allow clever userspace to disable implicit synchronization, we should
-do that under its own submit flag (as amdgpu and lima do).
-
-Note that we currently only implicitly sync for the rendering pass,
-not binning -- if you texture-from-pixmap in the binning vertex shader
-(vertex coordinate generation), you'll miss out on synchronization.
-
-Fixes flickering when multiple clients are running in parallel,
-particularly GL apps and compositors.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.h   | 10 +---
- drivers/gpu/drm/v3d/v3d_gem.c   | 98 ++++++++++++++++++++++++++++++---
- drivers/gpu/drm/v3d/v3d_sched.c | 45 ++-------------
- 3 files changed, 96 insertions(+), 57 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -186,8 +186,9 @@ struct v3d_job {
-       struct v3d_bo **bo;
-       u32 bo_count;
--      /* An optional fence userspace can pass in for the job to depend on. */
--      struct dma_fence *in_fence;
-+      struct dma_fence **deps;
-+      int deps_count;
-+      int deps_size;
-       /* v3d fence to be signaled by IRQ handler when the job is complete. */
-       struct dma_fence *irq_fence;
-@@ -219,11 +220,6 @@ struct v3d_bin_job {
- struct v3d_render_job {
-       struct v3d_job base;
--      /* Optional fence for the binner, to depend on before starting
--       * our job.
--       */
--      struct dma_fence *bin_done_fence;
--
-       /* GPU virtual addresses of the start/end of the CL job. */
-       u32 start, end;
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -218,6 +218,71 @@ v3d_unlock_bo_reservations(struct v3d_bo
-       ww_acquire_fini(acquire_ctx);
- }
-+static int
-+v3d_add_dep(struct v3d_job *job, struct dma_fence *fence)
-+{
-+      if (!fence)
-+              return 0;
-+
-+      if (job->deps_size == job->deps_count) {
-+              int new_deps_size = max(job->deps_size * 2, 4);
-+              struct dma_fence **new_deps =
-+                      krealloc(job->deps, new_deps_size * sizeof(*new_deps),
-+                               GFP_KERNEL);
-+              if (!new_deps) {
-+                      dma_fence_put(fence);
-+                      return -ENOMEM;
-+              }
-+
-+              job->deps = new_deps;
-+              job->deps_size = new_deps_size;
-+      }
-+
-+      job->deps[job->deps_count++] = fence;
-+
-+      return 0;
-+}
-+
-+/**
-+ * Adds the required implicit fences before executing the job
-+ *
-+ * Userspace (X11 + Mesa) requires that a job submitted against a shared BO
-+ * from one fd will implicitly synchronize against previous jobs submitted
-+ * against that BO from other fds.
-+ *
-+ * Currently we don't bother trying to track the shared BOs, and instead just
-+ * sync everything.  However, our synchronization is only for the render pass
-+ * -- the binning stage (VS coordinate calculations) ignores implicit sync,
-+ * since using shared buffers for texture coordinates seems unlikely, and
-+ * implicitly syncing them would break bin/render parallelism.  If we want to
-+ * fix that, we should introduce a flag when VS texturing has been used in the
-+ * binning stage, or a set of flags for which BOs are sampled during binning.
-+ */
-+static int
-+v3d_add_implicit_fences(struct v3d_job *job, struct v3d_bo *bo)
-+{
-+      int i, ret, nr_fences;
-+      struct dma_fence **fences;
-+
-+      ret = reservation_object_get_fences_rcu(bo->resv, NULL,
-+                                              &nr_fences, &fences);
-+      if (ret || !nr_fences)
-+              return ret;
-+
-+      for (i = 0; i < nr_fences; i++) {
-+              ret = v3d_add_dep(job, fences[i]);
-+              if (ret)
-+                      break;
-+      }
-+
-+      /* Free any remaining fences after error. */
-+      for (; i < nr_fences; i++)
-+              dma_fence_put(fences[i]);
-+      kfree(fences);
-+
-+      return ret;
-+}
-+
- /* Takes the reservation lock on all the BOs being referenced, so that
-  * at queue submit time we can update the reservations.
-  *
-@@ -226,10 +291,11 @@ v3d_unlock_bo_reservations(struct v3d_bo
-  * to v3d, so we don't attach dma-buf fences to them.
-  */
- static int
--v3d_lock_bo_reservations(struct v3d_bo **bos,
--                       int bo_count,
-+v3d_lock_bo_reservations(struct v3d_job *job,
-                        struct ww_acquire_ctx *acquire_ctx)
- {
-+      struct v3d_bo **bos = job->bo;
-+      int bo_count = job->bo_count;
-       int contended_lock = -1;
-       int i, ret;
-@@ -281,6 +347,13 @@ retry:
-        * before we commit the CL to the hardware.
-        */
-       for (i = 0; i < bo_count; i++) {
-+              ret = v3d_add_implicit_fences(job, bos[i]);
-+              if (ret) {
-+                      v3d_unlock_bo_reservations(bos, bo_count,
-+                                                 acquire_ctx);
-+                      return ret;
-+              }
-+
-               ret = reservation_object_reserve_shared(bos[i]->resv);
-               if (ret) {
-                       v3d_unlock_bo_reservations(bos, bo_count,
-@@ -383,7 +456,10 @@ v3d_job_free(struct kref *ref)
-       }
-       kvfree(job->bo);
--      dma_fence_put(job->in_fence);
-+      for (i = 0; i < job->deps_count; i++)
-+              dma_fence_put(job->deps[i]);
-+      kfree(job->deps);
-+
-       dma_fence_put(job->irq_fence);
-       dma_fence_put(job->done_fence);
-@@ -464,15 +540,20 @@ v3d_job_init(struct v3d_dev *v3d, struct
-            struct v3d_job *job, void (*free)(struct kref *ref),
-            u32 in_sync)
- {
-+      struct dma_fence *in_fence = NULL;
-       int ret;
-       job->v3d = v3d;
-       job->free = free;
--      ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
-+      ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &in_fence);
-       if (ret == -EINVAL)
-               return ret;
-+      ret = v3d_add_dep(job, in_fence);
-+      if (ret)
-+              return ret;
-+
-       kref_init(&job->refcount);
-       return 0;
-@@ -590,8 +671,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       if (ret)
-               goto fail;
--      ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
--                                     &acquire_ctx);
-+      ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
-       if (ret)
-               goto fail;
-@@ -601,7 +681,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
-               if (ret)
-                       goto fail_unreserve;
--              render->bin_done_fence = dma_fence_get(bin->base.done_fence);
-+              ret = v3d_add_dep(&render->base,
-+                                dma_fence_get(bin->base.done_fence));
-       }
-       ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
-@@ -692,8 +773,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       }
-       spin_unlock(&file_priv->table_lock);
--      ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
--                                     &acquire_ctx);
-+      ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
-       if (ret)
-               goto fail;
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -67,47 +67,10 @@ v3d_job_dependency(struct drm_sched_job
-                  struct drm_sched_entity *s_entity)
- {
-       struct v3d_job *job = to_v3d_job(sched_job);
--      struct dma_fence *fence;
--
--      fence = job->in_fence;
--      if (fence) {
--              job->in_fence = NULL;
--              return fence;
--      }
--
--      return NULL;
--}
--/**
-- * Returns the fences that the render job depends on, one by one.
-- * v3d_job_run() won't be called until all of them have been signaled.
-- */
--static struct dma_fence *
--v3d_render_job_dependency(struct drm_sched_job *sched_job,
--                        struct drm_sched_entity *s_entity)
--{
--      struct v3d_render_job *job = to_render_job(sched_job);
--      struct dma_fence *fence;
--
--      fence = v3d_job_dependency(sched_job, s_entity);
--      if (fence)
--              return fence;
--
--      /* If we had a bin job, the render job definitely depends on
--       * it. We first have to wait for bin to be scheduled, so that
--       * its done_fence is created.
--       */
--      fence = job->bin_done_fence;
--      if (fence) {
--              job->bin_done_fence = NULL;
--              return fence;
--      }
--
--      /* XXX: Wait on a fence for switching the GMP if necessary,
--       * and then do so.
--       */
--
--      return fence;
-+      if (!job->deps_count)
-+              return NULL;
-+      return job->deps[--job->deps_count];
- }
- static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
-@@ -329,7 +292,7 @@ static const struct drm_sched_backend_op
- };
- static const struct drm_sched_backend_ops v3d_render_sched_ops = {
--      .dependency = v3d_render_job_dependency,
-+      .dependency = v3d_job_dependency,
-       .run_job = v3d_render_job_run,
-       .timedout_job = v3d_render_job_timedout,
-       .free_job = v3d_job_free,
diff --git a/target/linux/brcm2708/patches-4.19/950-0514-drm-vc4-Make-sure-that-vblank-waits-work-without-v3d.patch b/target/linux/brcm2708/patches-4.19/950-0514-drm-vc4-Make-sure-that-vblank-waits-work-without-v3d.patch
new file mode 100644 (file)
index 0000000..32eba1c
--- /dev/null
@@ -0,0 +1,27 @@
+From 561918ec5e668f9d940051737d861ee0592816f6 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 29 Mar 2019 12:04:36 -0700
+Subject: [PATCH] drm/vc4: Make sure that vblank waits work without v3d
+ loaded.
+
+This flag exists to protect legacy drivers, but when vc4's v3d doesn't
+probe, it doesn't get set up by vc4_v3d.c's call of drm_irq_install.
+This resulted in applications running as fast as possible, and laggy
+performance from compton as it had to wait for the latest rendering by
+the application for its presentation.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -422,6 +422,7 @@ int vc4_kms_load(struct drm_device *dev)
+       /* Set support for vblank irq fast disable, before drm_vblank_init() */
+       dev->vblank_disable_immediate = true;
++      dev->irq_enabled = true;
+       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+       if (ret < 0) {
+               dev_err(dev->dev, "failed to initialize vblank\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0515-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch b/target/linux/brcm2708/patches-4.19/950-0515-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch
new file mode 100644 (file)
index 0000000..7eb5a95
--- /dev/null
@@ -0,0 +1,80 @@
+From c7fc1e1cf922bd548ac983ef48b883b6f83e35ae Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 18 Mar 2019 16:38:32 -0700
+Subject: [PATCH] drm/vc4: Expose the format modifiers for firmware
+ kms.
+
+This should technically not expose VC4_T_TILED on pi4.  However, if we
+don't expose anything, then userspace will assume that display can
+handle whatever modifiers 3d can do (UIF on 2711).  By exposing a
+list, that will get intersected with what 3D can do so that we get T
+tiling for display on 2710 and linear on 2711.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 33 +++++++++++++++++++++++++-
+ 1 file changed, 32 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -281,6 +281,27 @@ static void vc4_plane_destroy(struct drm
+       drm_plane_cleanup(plane);
+ }
++static bool vc4_fkms_format_mod_supported(struct drm_plane *plane,
++                                        uint32_t format,
++                                        uint64_t modifier)
++{
++      /* Support T_TILING for RGB formats only. */
++      switch (format) {
++      case DRM_FORMAT_XRGB8888:
++      case DRM_FORMAT_ARGB8888:
++              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;
++              }
++      default:
++              return false;
++      }
++}
++
+ static const struct drm_plane_funcs vc4_plane_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+@@ -289,6 +310,7 @@ static const struct drm_plane_funcs vc4_
+       .reset = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
++      .format_mod_supported = vc4_fkms_format_mod_supported,
+ };
+ static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
+@@ -316,6 +338,14 @@ static struct drm_plane *vc4_fkms_plane_
+       u32 argb8888 = DRM_FORMAT_ARGB8888;
+       int ret = 0;
+       bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
++      static const uint64_t modifiers[] = {
++              DRM_FORMAT_MOD_LINEAR,
++              /* VC4_T_TILED should come after linear, because we
++               * would prefer to scan out linear (less bus traffic).
++               */
++              DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
++              DRM_FORMAT_MOD_INVALID,
++      };
+       vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
+                                GFP_KERNEL);
+@@ -327,7 +357,8 @@ static struct drm_plane *vc4_fkms_plane_
+       plane = &vc4_plane->base;
+       ret = drm_universal_plane_init(dev, plane, 0xff,
+                                      &vc4_plane_funcs,
+-                                     primary ? &xrgb8888 : &argb8888, 1, NULL,
++                                     primary ? &xrgb8888 : &argb8888, 1,
++                                     modifiers,
+                                      type, primary ? "primary" : "cursor");
+       if (type == DRM_PLANE_TYPE_PRIMARY) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0515-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch b/target/linux/brcm2708/patches-4.19/950-0515-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch
deleted file mode 100644 (file)
index 6a3a6b1..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From b0fedd829bb6725fef7b2667c85badc6b4a8e5e0 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 28 Mar 2019 11:58:51 -0700
-Subject: [PATCH] drm/vc4: Fix synchronization firmwarekms against GL
- rendering.
-
-We would present the framebuffer immediately without waiting for
-rendering to finish first, resulting in stuttering and flickering as a
-window was dragged around when the GPU was busy enough to not just win
-the race.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -15,6 +15,7 @@
-  */
- #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"
-@@ -291,7 +292,7 @@ static const struct drm_plane_funcs vc4_
- };
- static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
--      .prepare_fb = NULL,
-+      .prepare_fb = drm_gem_fb_prepare_fb,
-       .cleanup_fb = NULL,
-       .atomic_check = vc4_plane_atomic_check,
-       .atomic_update = vc4_primary_plane_atomic_update,
-@@ -299,7 +300,7 @@ static const struct drm_plane_helper_fun
- };
- static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
--      .prepare_fb = NULL,
-+      .prepare_fb = drm_gem_fb_prepare_fb,
-       .cleanup_fb = NULL,
-       .atomic_check = vc4_plane_atomic_check,
-       .atomic_update = vc4_cursor_plane_atomic_update,
diff --git a/target/linux/brcm2708/patches-4.19/950-0516-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch b/target/linux/brcm2708/patches-4.19/950-0516-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch
new file mode 100644 (file)
index 0000000..4fb6f66
--- /dev/null
@@ -0,0 +1,45 @@
+From c0041a9fe33d6031267d9f3e2372833908e97337 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 2 Apr 2019 13:29:00 -0700
+Subject: [PATCH] drm/vc4: Fix vblank timestamping for firmwarekms.
+
+The core doesn't expect a false return from the scanoutpos function in
+normal usage, so we were doing the precise vblank timestamping path
+and thus "immediate" vblank disables (even though firmwarekms can't
+actually disable vblanks interrupts, sigh), and the kernel would get
+confused when getting timestamp info when also turning vblanks back
+on.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c         | 3 ---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -133,9 +133,6 @@ bool vc4_crtc_get_scanoutpos(struct drm_
+       int vblank_lines;
+       bool ret = false;
+-      if (vc4->firmware_kms)
+-              return 0;
+-
+       /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
+       /* Get optional system timestamp before query. */
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -673,6 +673,12 @@ static int vc4_fkms_bind(struct device *
+       vc4->firmware_kms = true;
++      /* firmware kms doesn't have precise a scanoutpos implementation, so
++       * we can't do the precise vblank timestamp mode.
++       */
++      drm->driver->get_scanout_position = NULL;
++      drm->driver->get_vblank_timestamp = NULL;
++
+       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+       if (!vc4_crtc)
+               return -ENOMEM;
diff --git a/target/linux/brcm2708/patches-4.19/950-0516-drm-vc4-Make-sure-that-vblank-waits-work-without-v3d.patch b/target/linux/brcm2708/patches-4.19/950-0516-drm-vc4-Make-sure-that-vblank-waits-work-without-v3d.patch
deleted file mode 100644 (file)
index 32eba1c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 561918ec5e668f9d940051737d861ee0592816f6 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 29 Mar 2019 12:04:36 -0700
-Subject: [PATCH] drm/vc4: Make sure that vblank waits work without v3d
- loaded.
-
-This flag exists to protect legacy drivers, but when vc4's v3d doesn't
-probe, it doesn't get set up by vc4_v3d.c's call of drm_irq_install.
-This resulted in applications running as fast as possible, and laggy
-performance from compton as it had to wait for the latest rendering by
-the application for its presentation.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -422,6 +422,7 @@ int vc4_kms_load(struct drm_device *dev)
-       /* Set support for vblank irq fast disable, before drm_vblank_init() */
-       dev->vblank_disable_immediate = true;
-+      dev->irq_enabled = true;
-       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
-       if (ret < 0) {
-               dev_err(dev->dev, "failed to initialize vblank\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0517-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch b/target/linux/brcm2708/patches-4.19/950-0517-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch
deleted file mode 100644 (file)
index 7eb5a95..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-From c7fc1e1cf922bd548ac983ef48b883b6f83e35ae Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 18 Mar 2019 16:38:32 -0700
-Subject: [PATCH] drm/vc4: Expose the format modifiers for firmware
- kms.
-
-This should technically not expose VC4_T_TILED on pi4.  However, if we
-don't expose anything, then userspace will assume that display can
-handle whatever modifiers 3d can do (UIF on 2711).  By exposing a
-list, that will get intersected with what 3D can do so that we get T
-tiling for display on 2710 and linear on 2711.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 33 +++++++++++++++++++++++++-
- 1 file changed, 32 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -281,6 +281,27 @@ static void vc4_plane_destroy(struct drm
-       drm_plane_cleanup(plane);
- }
-+static bool vc4_fkms_format_mod_supported(struct drm_plane *plane,
-+                                        uint32_t format,
-+                                        uint64_t modifier)
-+{
-+      /* Support T_TILING for RGB formats only. */
-+      switch (format) {
-+      case DRM_FORMAT_XRGB8888:
-+      case DRM_FORMAT_ARGB8888:
-+              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;
-+              }
-+      default:
-+              return false;
-+      }
-+}
-+
- static const struct drm_plane_funcs vc4_plane_funcs = {
-       .update_plane = drm_atomic_helper_update_plane,
-       .disable_plane = drm_atomic_helper_disable_plane,
-@@ -289,6 +310,7 @@ static const struct drm_plane_funcs vc4_
-       .reset = drm_atomic_helper_plane_reset,
-       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-+      .format_mod_supported = vc4_fkms_format_mod_supported,
- };
- static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
-@@ -316,6 +338,14 @@ static struct drm_plane *vc4_fkms_plane_
-       u32 argb8888 = DRM_FORMAT_ARGB8888;
-       int ret = 0;
-       bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
-+      static const uint64_t modifiers[] = {
-+              DRM_FORMAT_MOD_LINEAR,
-+              /* VC4_T_TILED should come after linear, because we
-+               * would prefer to scan out linear (less bus traffic).
-+               */
-+              DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
-+              DRM_FORMAT_MOD_INVALID,
-+      };
-       vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
-                                GFP_KERNEL);
-@@ -327,7 +357,8 @@ static struct drm_plane *vc4_fkms_plane_
-       plane = &vc4_plane->base;
-       ret = drm_universal_plane_init(dev, plane, 0xff,
-                                      &vc4_plane_funcs,
--                                     primary ? &xrgb8888 : &argb8888, 1, NULL,
-+                                     primary ? &xrgb8888 : &argb8888, 1,
-+                                     modifiers,
-                                      type, primary ? "primary" : "cursor");
-       if (type == DRM_PLANE_TYPE_PRIMARY) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0517-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch b/target/linux/brcm2708/patches-4.19/950-0517-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch
new file mode 100644 (file)
index 0000000..ad729c5
--- /dev/null
@@ -0,0 +1,216 @@
+From 3819888738de087ba726ceaa2ab20503f164f1ed Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 26 Mar 2019 14:43:06 +0000
+Subject: [PATCH] gpu: vc4-fkms: Switch to the newer mailbox frame
+ buffer API.
+
+The old mailbox FB API was ideally deprecated but still used by
+the FKMS driver.
+Update to the newer API.
+
+NB This needs current firmware that accepts ARM allocated buffers
+through the newer API.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 109 +++++++++++----------
+ include/soc/bcm2835/raspberrypi-firmware.h |  10 ++
+ 2 files changed, 67 insertions(+), 52 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -28,6 +28,25 @@
+ #include "vc4_regs.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
++struct fb_alloc_tags {
++      struct rpi_firmware_property_tag_header tag1;
++      u32 xres, yres;
++      struct rpi_firmware_property_tag_header tag2;
++      u32 xres_virtual, yres_virtual;
++      struct rpi_firmware_property_tag_header tag3;
++      u32 bpp;
++      struct rpi_firmware_property_tag_header tag4;
++      u32 xoffset, yoffset;
++      struct rpi_firmware_property_tag_header tag5;
++      u32 base, screen_size;
++      struct rpi_firmware_property_tag_header tag6;
++      u32 pitch;
++      struct rpi_firmware_property_tag_header tag7;
++      u32 alpha_mode;
++      struct rpi_firmware_property_tag_header tag8;
++      u32 layer;
++};
++
+ /* The firmware delivers a vblank interrupt to us through the SMI
+  * hardware, which has only this one register.
+  */
+@@ -121,45 +140,39 @@ static void vc4_primary_plane_atomic_upd
+                                           struct drm_plane_state *old_state)
+ {
+       struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+-      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+       struct drm_plane_state *state = plane->state;
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+-      volatile struct fbinfo_s *fbinfo = vc4_plane->fbinfo;
++      u32 format = fb->format->format;
++      struct fb_alloc_tags fbinfo = {
++              .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
++                        8, 0, },
++                      .xres = state->crtc_w,
++                      .yres = state->crtc_h,
++              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
++                        8, 0, },
++                      .xres_virtual = state->crtc_w,
++                      .yres_virtual = state->crtc_h,
++              .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
++                      .bpp = 32,
++              .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
++                      .xoffset = 0,
++                      .yoffset = 0,
++              .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
++                      .base = bo->paddr + fb->offsets[0],
++                      .screen_size = state->crtc_w * state->crtc_h * 4,
++              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
++                      .pitch = fb->pitches[0],
++              .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
++                      .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
++              .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
++                      .layer = -127,
++      };
+       u32 bpp = 32;
+       int ret;
+-      fbinfo->xres = state->crtc_w;
+-      fbinfo->yres = state->crtc_h;
+-      fbinfo->xres_virtual = state->crtc_w;
+-      fbinfo->yres_virtual = state->crtc_h;
+-      fbinfo->bpp = bpp;
+-      fbinfo->xoffset = state->crtc_x;
+-      fbinfo->yoffset = state->crtc_y;
+-      fbinfo->base = bo->paddr + fb->offsets[0];
+-      fbinfo->pitch = fb->pitches[0];
+-
+       if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
+-              fbinfo->bpp |= BIT(31);
+-
+-      /* A bug in the firmware makes it so that if the fb->base is
+-       * set to nonzero, the configured pitch gets overwritten with
+-       * the previous pitch.  So, to get the configured pitch
+-       * recomputed, we have to make it allocate itself a new buffer
+-       * in VC memory, first.
+-       */
+-      if (vc4_plane->pitch != fb->pitches[0]) {
+-              u32 saved_base = fbinfo->base;
+-              fbinfo->base = 0;
+-
+-              ret = rpi_firmware_transaction(vc4->firmware,
+-                                             RPI_FIRMWARE_CHAN_FB,
+-                                             vc4_plane->fbinfo_bus_addr);
+-              fbinfo->base = saved_base;
+-
+-              vc4_plane->pitch = fbinfo->pitch;
+-              WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]);
+-      }
++              fbinfo.bpp |= BIT(31);
+       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
+                        plane->base.id, plane->name,
+@@ -168,14 +181,13 @@ static void vc4_primary_plane_atomic_upd
+                        bpp,
+                        state->crtc_x,
+                        state->crtc_y,
+-                       &fbinfo->base,
++                       &fbinfo.base,
+                        fb->pitches[0]);
+-      ret = rpi_firmware_transaction(vc4->firmware,
+-                                     RPI_FIRMWARE_CHAN_FB,
+-                                     vc4_plane->fbinfo_bus_addr);
+-      WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]);
+-      WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[0]);
++      ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
++                                       sizeof(fbinfo));
++      WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
++      WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
+       /* If the CRTC is on (or going to be on) and we're enabled,
+        * then unblank.  Otherwise, stay blank until CRTC enable.
+@@ -332,10 +344,10 @@ static const struct drm_plane_helper_fun
+ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
+                                            enum drm_plane_type type)
+ {
++      /* Primary and cursor planes only */
+       struct drm_plane *plane = NULL;
+       struct vc4_fkms_plane *vc4_plane;
+-      u32 xrgb8888 = DRM_FORMAT_XRGB8888;
+-      u32 argb8888 = DRM_FORMAT_ARGB8888;
++      u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
+       int ret = 0;
+       bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
+       static const uint64_t modifiers[] = {
+@@ -357,22 +369,15 @@ static struct drm_plane *vc4_fkms_plane_
+       plane = &vc4_plane->base;
+       ret = drm_universal_plane_init(dev, plane, 0xff,
+                                      &vc4_plane_funcs,
+-                                     primary ? &xrgb8888 : &argb8888, 1,
+-                                     modifiers,
++                                     formats, primary ? 2 : 1, modifiers,
+                                      type, primary ? "primary" : "cursor");
+-      if (type == DRM_PLANE_TYPE_PRIMARY) {
+-              vc4_plane->fbinfo =
+-                      dma_alloc_coherent(dev->dev,
+-                                         sizeof(*vc4_plane->fbinfo),
+-                                         &vc4_plane->fbinfo_bus_addr,
+-                                         GFP_KERNEL);
+-              memset(vc4_plane->fbinfo, 0, sizeof(*vc4_plane->fbinfo));
+-
++      if (type == DRM_PLANE_TYPE_PRIMARY)
+               drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
+-      } else {
++      else
+               drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
+-      }
++
++      drm_plane_create_alpha_property(plane);
+       return plane;
+ fail:
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -111,9 +111,15 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET =         0x00040009,
+       RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN =               0x0004000a,
+       RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE =                0x0004000b,
++      RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER =                  0x0004000c,
++      RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM =              0x0004000d,
++      RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC =                  0x0004000e,
+       RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF =               0x0004000f,
+       RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF =            0x00040010,
+       RPI_FIRMWARE_FRAMEBUFFER_RELEASE =                    0x00048001,
++      RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM =            0x00048013,
++      RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS =           0x00040013,
++      RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS =       0x00040014,
+       RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
+       RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT =  0x00044004,
+       RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH =                 0x00044005,
+@@ -122,6 +128,8 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET =        0x00044009,
+       RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN =              0x0004400a,
+       RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE =               0x0004400b,
++      RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER =                 0x0004400c,
++      RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM =             0x0004400d,
+       RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC =                 0x0004400e,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT =  0x00048003,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT =   0x00048004,
+@@ -134,6 +142,8 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF =               0x0004801f,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF =            0x00048020,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC =                  0x0004800e,
++      RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER =                  0x0004800c,
++      RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM =              0x0004800d,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT =              0x0004800f,
+       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
diff --git a/target/linux/brcm2708/patches-4.19/950-0518-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch b/target/linux/brcm2708/patches-4.19/950-0518-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch
new file mode 100644 (file)
index 0000000..f3e2851
--- /dev/null
@@ -0,0 +1,853 @@
+From 953d85d97f59691dccbbca743c478a8b01f92b59 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 27 Mar 2019 17:45:01 +0000
+Subject: [PATCH] drm: vc4: Add an overlay plane to vc4-firmware-kms
+
+This uses a new API that is exposed via the mailbox service
+to stick an element straight on the screen using DispmanX.
+
+The primary and cursor planes have also been switched to using
+the new plane API, and it supports layering based on the DRM
+zpos parameter.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 518 ++++++++++++++-------
+ drivers/gpu/drm/vc4/vc4_kms.c              |   1 +
+ drivers/gpu/drm/vc4/vc_image_types.h       | 143 ++++++
+ include/soc/bcm2835/raspberrypi-firmware.h |   2 +
+ 4 files changed, 495 insertions(+), 169 deletions(-)
+ create mode 100644 drivers/gpu/drm/vc4/vc_image_types.h
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -26,8 +26,46 @@
+ #include "linux/of_device.h"
+ #include "vc4_drv.h"
+ #include "vc4_regs.h"
++#include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
++struct set_plane {
++      u8 display;
++      u8 plane_id;
++      u8 vc_image_type;
++      s8 layer;
++
++      u16 width;
++      u16 height;
++
++      u16 pitch;
++      u16 vpitch;
++
++      u32 src_x;      /* 16p16 */
++      u32 src_y;      /* 16p16 */
++
++      u32 src_w;      /* 16p16 */
++      u32 src_h;      /* 16p16 */
++
++      s16 dst_x;
++      s16 dst_y;
++
++      u16 dst_w;
++      u16 dst_h;
++
++      u8 alpha;
++      u8 num_planes;
++      u8 is_vu;
++      u8 padding;
++
++      u32 planes[4];  /* DMA address of each plane */
++};
++
++struct mailbox_set_plane {
++      struct rpi_firmware_property_tag_header tag;
++      struct set_plane plane;
++};
++
+ struct fb_alloc_tags {
+       struct rpi_firmware_property_tag_header tag1;
+       u32 xres, yres;
+@@ -47,6 +85,79 @@ struct fb_alloc_tags {
+       u32 layer;
+ };
++static const struct vc_image_format {
++      u32 drm;        /* DRM_FORMAT_* */
++      u32 vc_image;   /* VC_IMAGE_* */
++      u32 is_vu;
++} vc_image_formats[] = {
++      {
++              .drm = DRM_FORMAT_XRGB8888,
++              .vc_image = VC_IMAGE_XRGB8888,
++      },
++      {
++              .drm = DRM_FORMAT_ARGB8888,
++              .vc_image = VC_IMAGE_ARGB8888,
++      },
++/*
++ *    FIXME: Need to resolve which DRM format goes to which vc_image format
++ *    for the remaining RGBA and RGBX formats.
++ *    {
++ *            .drm = DRM_FORMAT_ABGR8888,
++ *            .vc_image = VC_IMAGE_RGBA8888,
++ *    },
++ *    {
++ *            .drm = DRM_FORMAT_XBGR8888,
++ *            .vc_image = VC_IMAGE_RGBA8888,
++ *    },
++ */
++      {
++              .drm = DRM_FORMAT_RGB565,
++              .vc_image = VC_IMAGE_RGB565,
++      },
++      {
++              .drm = DRM_FORMAT_RGB888,
++              .vc_image = VC_IMAGE_BGR888,
++      },
++      {
++              .drm = DRM_FORMAT_BGR888,
++              .vc_image = VC_IMAGE_RGB888,
++      },
++      {
++              .drm = DRM_FORMAT_YUV422,
++              .vc_image = VC_IMAGE_YUV422PLANAR,
++      },
++      {
++              .drm = DRM_FORMAT_YUV420,
++              .vc_image = VC_IMAGE_YUV420,
++      },
++      {
++              .drm = DRM_FORMAT_YVU420,
++              .vc_image = VC_IMAGE_YUV420,
++              .is_vu = 1,
++      },
++      {
++              .drm = DRM_FORMAT_NV12,
++              .vc_image = VC_IMAGE_YUV420SP,
++      },
++      {
++              .drm = DRM_FORMAT_NV21,
++              .vc_image = VC_IMAGE_YUV420SP,
++              .is_vu = 1,
++      },
++};
++
++static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format)
++{
++      unsigned int i;
++
++      for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) {
++              if (vc_image_formats[i].drm == drm_format)
++                      return &vc_image_formats[i];
++      }
++
++      return NULL;
++}
++
+ /* The firmware delivers a vblank interrupt to us through the SMI
+  * hardware, which has only this one register.
+  */
+@@ -113,6 +224,7 @@ struct vc4_fkms_plane {
+       struct fbinfo_s *fbinfo;
+       dma_addr_t fbinfo_bus_addr;
+       u32 pitch;
++      struct mailbox_set_plane mb;
+ };
+ static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane)
+@@ -120,165 +232,183 @@ static inline struct vc4_fkms_plane *to_
+       return (struct vc4_fkms_plane *)plane;
+ }
+-/* Turns the display on/off. */
+-static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank)
++static int vc4_plane_set_blank(struct drm_plane *plane, bool blank)
+ {
+       struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
++      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
++      struct mailbox_set_plane blank_mb = {
++              .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 },
++              .plane = {
++                      .display = vc4_plane->mb.plane.display,
++                      .plane_id = vc4_plane->mb.plane.plane_id,
++              }
++      };
++      int ret;
+-      u32 packet = blank;
+-
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s",
++      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
+                        plane->base.id, plane->name,
+                        blank ? "blank" : "unblank");
+-      return rpi_firmware_property(vc4->firmware,
+-                                   RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+-                                   &packet, sizeof(packet));
++      if (blank)
++              ret = rpi_firmware_property_list(vc4->firmware, &blank_mb,
++                                               sizeof(blank_mb));
++      else
++              ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb,
++                                               sizeof(vc4_plane->mb));
++
++      WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware",
++                __func__);
++      return ret;
+ }
+-static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
+-                                          struct drm_plane_state *old_state)
++static void vc4_plane_atomic_update(struct drm_plane *plane,
++                                  struct drm_plane_state *old_state)
+ {
+-      struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+       struct drm_plane_state *state = plane->state;
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+-      u32 format = fb->format->format;
+-      struct fb_alloc_tags fbinfo = {
+-              .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
+-                        8, 0, },
+-                      .xres = state->crtc_w,
+-                      .yres = state->crtc_h,
+-              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
+-                        8, 0, },
+-                      .xres_virtual = state->crtc_w,
+-                      .yres_virtual = state->crtc_h,
+-              .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
+-                      .bpp = 32,
+-              .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
+-                      .xoffset = 0,
+-                      .yoffset = 0,
+-              .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+-                      .base = bo->paddr + fb->offsets[0],
+-                      .screen_size = state->crtc_w * state->crtc_h * 4,
+-              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
+-                      .pitch = fb->pitches[0],
+-              .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
+-                      .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
+-              .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
+-                      .layer = -127,
+-      };
+-      u32 bpp = 32;
+-      int ret;
++      const struct drm_format_info *drm_fmt = fb->format;
++      const struct vc_image_format *vc_fmt =
++                                      vc4_get_vc_image_fmt(drm_fmt->format);
++      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
++      struct mailbox_set_plane *mb = &vc4_plane->mb;
++      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
++      int num_planes = fb->format->num_planes;
++      struct drm_display_mode *mode = &state->crtc->mode;
+-      if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
+-              fbinfo.bpp |= BIT(31);
++      mb->plane.vc_image_type = vc_fmt->vc_image;
++      mb->plane.width = fb->width;
++      mb->plane.height = fb->height;
++      mb->plane.pitch = fb->pitches[0];
++      mb->plane.src_w = state->src_w;
++      mb->plane.src_h = state->src_h;
++      mb->plane.src_x = state->src_x;
++      mb->plane.src_y = state->src_y;
++      mb->plane.dst_w = state->crtc_w;
++      mb->plane.dst_h = state->crtc_h;
++      mb->plane.dst_x = state->crtc_x;
++      mb->plane.dst_y = state->crtc_y;
++      mb->plane.alpha = state->alpha >> 8;
++      mb->plane.layer = state->normalized_zpos ?
++                                      state->normalized_zpos : -127;
++      mb->plane.num_planes = num_planes;
++      mb->plane.is_vu = vc_fmt->is_vu;
++      mb->plane.planes[0] = bo->paddr + fb->offsets[0];
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
++      /* FIXME: If the dest rect goes off screen then clip the src rect so we
++       * don't have off-screen pixels.
++       */
++      if (plane->type == DRM_PLANE_TYPE_CURSOR) {
++              /* There is no scaling on the cursor plane, therefore the calcs
++               * to alter the source crop as the cursor goes off the screen
++               * are simple.
++               */
++              if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
++                      mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
++                      mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
++                                                                      << 16;
++              }
++              if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
++                      mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
++                      mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
++                                                                      << 16;
++              }
++      }
++
++      if (num_planes > 1) {
++              /* Assume this must be YUV */
++              /* Makes assumptions on the stride for the chroma planes as we
++               * can't easily plumb in non-standard pitches.
++               */
++              mb->plane.planes[1] = bo->paddr + fb->offsets[1];
++              if (num_planes > 2)
++                      mb->plane.planes[2] = bo->paddr + fb->offsets[2];
++              else
++                      mb->plane.planes[2] = 0;
++
++              /* Special case the YUV420 with U and V as line interleaved
++               * planes as we have special handling for that case.
++               */
++              if (num_planes == 3 &&
++                  (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
++                      mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
++      } else {
++              mb->plane.planes[1] = 0;
++              mb->plane.planes[2] = 0;
++      }
++      mb->plane.planes[3] = 0;
++
++      switch (fb->modifier) {
++      case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
++              switch (mb->plane.vc_image_type) {
++              case VC_IMAGE_RGBX32:
++                      mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
++                      break;
++              case VC_IMAGE_RGBA32:
++                      mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
++                      break;
++              case VC_IMAGE_RGB565:
++                      mb->plane.vc_image_type = VC_IMAGE_TF_RGB565;
++                      break;
++              }
++              break;
++      case DRM_FORMAT_MOD_BROADCOM_SAND128:
++              mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
++              mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
++              break;
++      }
++
++      if (vc4_crtc) {
++              mb->plane.dst_x += vc4_crtc->overscan[0];
++              mb->plane.dst_y += vc4_crtc->overscan[1];
++      }
++
++      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
+                        plane->base.id, plane->name,
+-                       state->crtc_w,
+-                       state->crtc_h,
+-                       bpp,
++                       mb->plane.width,
++                       mb->plane.height,
++                       mb->plane.vc_image_type,
+                        state->crtc_x,
+                        state->crtc_y,
+-                       &fbinfo.base,
+-                       fb->pitches[0]);
+-
+-      ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
+-                                       sizeof(fbinfo));
+-      WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
+-      WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
+-
+-      /* If the CRTC is on (or going to be on) and we're enabled,
++                       state->crtc_w,
++                       state->crtc_h,
++                       mb->plane.src_x,
++                       mb->plane.src_y,
++                       mb->plane.src_w,
++                       mb->plane.src_h,
++                       mb->plane.planes[0],
++                       mb->plane.planes[1],
++                       mb->plane.planes[2],
++                       fb->pitches[0],
++                       state->alpha,
++                       state->normalized_zpos);
++
++      /*
++       * Do NOT set now, as we haven't checked if the crtc is active or not.
++       * Set from vc4_plane_set_blank instead.
++       *
++       * If the CRTC is on (or going to be on) and we're enabled,
+        * then unblank.  Otherwise, stay blank until CRTC enable.
+-      */
++       */
+       if (state->crtc->state->active)
+-              vc4_plane_set_primary_blank(plane, false);
++              vc4_plane_set_blank(plane, false);
+ }
+-static void vc4_primary_plane_atomic_disable(struct drm_plane *plane,
+-                                           struct drm_plane_state *old_state)
++static void vc4_plane_atomic_disable(struct drm_plane *plane,
++                                   struct drm_plane_state *old_state)
+ {
+-      vc4_plane_set_primary_blank(plane, true);
+-}
+-
+-static void vc4_cursor_plane_atomic_update(struct drm_plane *plane,
+-                                         struct drm_plane_state *old_state)
+-{
+-      struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
++      //struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+       struct drm_plane_state *state = plane->state;
+-      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+-      struct drm_framebuffer *fb = state->fb;
+-      struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+-      dma_addr_t addr = bo->paddr + fb->offsets[0];
+-      int ret;
+-      u32 packet_state[] = {
+-              state->crtc->state->active,
+-              state->crtc_x,
+-              state->crtc_y,
+-              0
+-      };
+-      WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
++      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
++      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
+                        plane->base.id, plane->name,
+                        state->crtc_w,
+                        state->crtc_h,
++                       vc4_plane->mb.plane.vc_image_type,
+                        state->crtc_x,
+-                       state->crtc_y,
+-                       &addr,
+-                       fb->pitches[0]);
+-
+-      /* add on the top/left offsets when overscan is active */
+-      if (vc4_crtc) {
+-              packet_state[1] += vc4_crtc->overscan[0];
+-              packet_state[2] += vc4_crtc->overscan[1];
+-      }
+-
+-      ret = rpi_firmware_property(vc4->firmware,
+-                                  RPI_FIRMWARE_SET_CURSOR_STATE,
+-                                  &packet_state,
+-                                  sizeof(packet_state));
+-      if (ret || packet_state[0] != 0)
+-              DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
+-
+-      /* Note: When the cursor contents change, the modesetting
+-       * driver calls drm_mode_cursor_univeral() with
+-       * DRM_MODE_CURSOR_BO, which means a new fb will be allocated.
+-       */
+-      if (!old_state ||
+-          state->crtc_w != old_state->crtc_w ||
+-          state->crtc_h != old_state->crtc_h ||
+-          fb != old_state->fb) {
+-              u32 packet_info[] = { state->crtc_w, state->crtc_h,
+-                                    0, /* unused */
+-                                    addr,
+-                                    0, 0, /* hotx, hoty */};
+-
+-              ret = rpi_firmware_property(vc4->firmware,
+-                                          RPI_FIRMWARE_SET_CURSOR_INFO,
+-                                          &packet_info,
+-                                          sizeof(packet_info));
+-              if (ret || packet_info[0] != 0)
+-                      DRM_ERROR("Failed to set cursor info: 0x%08x\n", packet_info[0]);
+-      }
+-}
+-
+-static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane,
+-                                          struct drm_plane_state *old_state)
+-{
+-      struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+-      u32 packet_state[] = { false, 0, 0, 0 };
+-      int ret;
+-
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] disabling cursor", plane->base.id, plane->name);
+-
+-      ret = rpi_firmware_property(vc4->firmware,
+-                                  RPI_FIRMWARE_SET_CURSOR_STATE,
+-                                  &packet_state,
+-                                  sizeof(packet_state));
+-      if (ret || packet_state[0] != 0)
+-              DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
++                       state->crtc_y);
++      vc4_plane_set_blank(plane, true);
+ }
+ static int vc4_plane_atomic_check(struct drm_plane *plane,
+@@ -301,6 +431,7 @@ static bool vc4_fkms_format_mod_supporte
+       switch (format) {
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_ARGB8888:
++      case DRM_FORMAT_RGB565:
+               switch (modifier) {
+               case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+               case DRM_FORMAT_MOD_LINEAR:
+@@ -309,8 +440,22 @@ static bool vc4_fkms_format_mod_supporte
+               default:
+                       return false;
+               }
++      case DRM_FORMAT_NV12:
++      case DRM_FORMAT_NV21:
++              switch (fourcc_mod_broadcom_mod(modifier)) {
++              case DRM_FORMAT_MOD_LINEAR:
++              case DRM_FORMAT_MOD_BROADCOM_SAND128:
++                      return true;
++              default:
++                      return false;
++              }
++      case DRM_FORMAT_RGB888:
++      case DRM_FORMAT_BGR888:
++      case DRM_FORMAT_YUV422:
++      case DRM_FORMAT_YUV420:
++      case DRM_FORMAT_YVU420:
+       default:
+-              return false;
++              return (modifier == DRM_FORMAT_MOD_LINEAR);
+       }
+ }
+@@ -325,31 +470,24 @@ static const struct drm_plane_funcs vc4_
+       .format_mod_supported = vc4_fkms_format_mod_supported,
+ };
+-static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
+-      .prepare_fb = drm_gem_fb_prepare_fb,
+-      .cleanup_fb = NULL,
+-      .atomic_check = vc4_plane_atomic_check,
+-      .atomic_update = vc4_primary_plane_atomic_update,
+-      .atomic_disable = vc4_primary_plane_atomic_disable,
+-};
+-
+-static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
++static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
+       .prepare_fb = drm_gem_fb_prepare_fb,
+       .cleanup_fb = NULL,
+       .atomic_check = vc4_plane_atomic_check,
+-      .atomic_update = vc4_cursor_plane_atomic_update,
+-      .atomic_disable = vc4_cursor_plane_atomic_disable,
++      .atomic_update = vc4_plane_atomic_update,
++      .atomic_disable = vc4_plane_atomic_disable,
+ };
+ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
+-                                           enum drm_plane_type type)
++                                           enum drm_plane_type type,
++                                           u8 plane_id)
+ {
+-      /* Primary and cursor planes only */
+       struct drm_plane *plane = NULL;
+       struct vc4_fkms_plane *vc4_plane;
+-      u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
++      u32 formats[ARRAY_SIZE(vc_image_formats)];
++      unsigned int default_zpos;
++      u32 num_formats = 0;
+       int ret = 0;
+-      bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
+       static const uint64_t modifiers[] = {
+               DRM_FORMAT_MOD_LINEAR,
+               /* VC4_T_TILED should come after linear, because we
+@@ -358,6 +496,7 @@ static struct drm_plane *vc4_fkms_plane_
+               DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
+               DRM_FORMAT_MOD_INVALID,
+       };
++      int i;
+       vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
+                                GFP_KERNEL);
+@@ -366,19 +505,48 @@ static struct drm_plane *vc4_fkms_plane_
+               goto fail;
+       }
++      for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++)
++              formats[num_formats++] = vc_image_formats[i].drm;
++
+       plane = &vc4_plane->base;
+       ret = drm_universal_plane_init(dev, plane, 0xff,
+                                      &vc4_plane_funcs,
+-                                     formats, primary ? 2 : 1, modifiers,
+-                                     type, primary ? "primary" : "cursor");
++                                     formats, num_formats, modifiers,
++                                     type, NULL);
+-      if (type == DRM_PLANE_TYPE_PRIMARY)
+-              drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
+-      else
+-              drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
++      drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
+       drm_plane_create_alpha_property(plane);
++      /*
++       * Default frame buffer setup is with FB on -127, and raspistill etc
++       * tend to drop overlays on layer 2. Cursor plane was on layer +127.
++       *
++       * For F-KMS the mailbox call allows for a s8.
++       * Remap zpos 0 to -127 for the background layer, but leave all the
++       * other layers as requested by KMS.
++       */
++      switch (type) {
++      case DRM_PLANE_TYPE_PRIMARY:
++              default_zpos = 0;
++              break;
++      case DRM_PLANE_TYPE_OVERLAY:
++              default_zpos = 1;
++              break;
++      case DRM_PLANE_TYPE_CURSOR:
++              default_zpos = 2;
++              break;
++      }
++      drm_plane_create_zpos_property(plane, default_zpos, 0, 127);
++
++      /* Prepare the static elements of the mailbox structure */
++      vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
++      vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
++      vc4_plane->mb.tag.req_resp_size = 0;
++      vc4_plane->mb.plane.display = 0;
++      vc4_plane->mb.plane.plane_id = plane_id;
++      vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
++
+       return plane;
+ fail:
+       if (plane)
+@@ -400,19 +568,23 @@ static void vc4_crtc_disable(struct drm_
+        * whether anything scans out at all, but the firmware doesn't
+        * give us a CRTC-level control for that.
+        */
+-      vc4_cursor_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
+-      vc4_plane_set_primary_blank(crtc->primary, true);
++
++      vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
++      vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
++
++      /* FIXME: Disable overlay planes */
+ }
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
+       /* Unblank the planes (if they're supposed to be displayed). */
++
+       if (crtc->primary->state->fb)
+-              vc4_plane_set_primary_blank(crtc->primary, false);
+-      if (crtc->cursor->state->fb) {
+-              vc4_cursor_plane_atomic_update(crtc->cursor,
+-                                             crtc->cursor->state);
+-      }
++              vc4_plane_set_blank(crtc->primary, false);
++      if (crtc->cursor->state->fb)
++              vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
++
++      /* FIXME: Enable overlay planes */
+ }
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+@@ -672,8 +844,10 @@ static int vc4_fkms_bind(struct device *
+       struct vc4_crtc *vc4_crtc;
+       struct vc4_fkms_encoder *vc4_encoder;
+       struct drm_crtc *crtc;
+-      struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp;
++      struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
++      struct drm_plane *destroy_plane, *temp;
+       struct device_node *firmware_node;
++      u32 blank = 1;
+       int ret;
+       vc4->firmware_kms = true;
+@@ -702,20 +876,26 @@ static int vc4_fkms_bind(struct device *
+       if (IS_ERR(vc4_crtc->regs))
+               return PTR_ERR(vc4_crtc->regs);
+-      /* For now, we create just the primary and the legacy cursor
+-       * planes.  We should be able to stack more planes on easily,
+-       * but to do that we would need to compute the bandwidth
+-       * requirement of the plane configuration, and reject ones
+-       * that will take too much.
+-       */
+-      primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
++      /* Blank the firmware provided framebuffer */
++      rpi_firmware_property(vc4->firmware,
++                            RPI_FIRMWARE_FRAMEBUFFER_BLANK,
++                            &blank, sizeof(blank));
++
++      primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
+       if (IS_ERR(primary_plane)) {
+               dev_err(dev, "failed to construct primary plane\n");
+               ret = PTR_ERR(primary_plane);
+               goto err;
+       }
+-      cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
++      overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1);
++      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, 2);
+       if (IS_ERR(cursor_plane)) {
+               dev_err(dev, "failed to construct cursor plane\n");
+               ret = PTR_ERR(cursor_plane);
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -435,6 +435,7 @@ int vc4_kms_load(struct drm_device *dev)
+       dev->mode_config.preferred_depth = 24;
+       dev->mode_config.async_page_flip = true;
+       dev->mode_config.allow_fb_modifiers = true;
++      dev->mode_config.normalize_zpos = true;
+       drm_modeset_lock_init(&vc4->ctm_state_lock);
+--- /dev/null
++++ b/drivers/gpu/drm/vc4/vc_image_types.h
+@@ -0,0 +1,143 @@
++
++/*
++ * Copyright (c) 2012, Broadcom Europe Ltd
++ *
++ * Values taken from vc_image_types.h released by Broadcom at
++ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
++ *
++ * 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.
++ */
++
++enum {
++      VC_IMAGE_MIN = 0, //bounds for error checking
++
++      VC_IMAGE_RGB565 = 1,
++      VC_IMAGE_1BPP,
++      VC_IMAGE_YUV420,
++      VC_IMAGE_48BPP,
++      VC_IMAGE_RGB888,
++      VC_IMAGE_8BPP,
++      /* 4bpp palettised image */
++      VC_IMAGE_4BPP,
++      /* A separated format of 16 colour/light shorts followed by 16 z
++       * values
++       */
++      VC_IMAGE_3D32,
++      /* 16 colours followed by 16 z values */
++      VC_IMAGE_3D32B,
++      /* A separated format of 16 material/colour/light shorts followed by
++       * 16 z values
++       */
++      VC_IMAGE_3D32MAT,
++      /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
++      VC_IMAGE_RGB2X9,
++      /* 32-bit format holding 18 bits of 6.6.6 RGB */
++      VC_IMAGE_RGB666,
++      /* 4bpp palettised image with embedded palette */
++      VC_IMAGE_PAL4_OBSOLETE,
++      /* 8bpp palettised image with embedded palette */
++      VC_IMAGE_PAL8_OBSOLETE,
++      /* RGB888 with an alpha byte after each pixel */
++      VC_IMAGE_RGBA32,
++      /* a line of Y (32-byte padded), a line of U (16-byte padded), and a
++       * line of V (16-byte padded)
++       */
++      VC_IMAGE_YUV422,
++      /* RGB565 with a transparent patch */
++      VC_IMAGE_RGBA565,
++      /* Compressed (4444) version of RGBA32 */
++      VC_IMAGE_RGBA16,
++      /* VCIII codec format */
++      VC_IMAGE_YUV_UV,
++      /* VCIII T-format RGBA8888 */
++      VC_IMAGE_TF_RGBA32,
++      /* VCIII T-format RGBx8888 */
++      VC_IMAGE_TF_RGBX32,
++      /* VCIII T-format float */
++      VC_IMAGE_TF_FLOAT,
++      /* VCIII T-format RGBA4444 */
++      VC_IMAGE_TF_RGBA16,
++      /* VCIII T-format RGB5551 */
++      VC_IMAGE_TF_RGBA5551,
++      /* VCIII T-format RGB565 */
++      VC_IMAGE_TF_RGB565,
++      /* VCIII T-format 8-bit luma and 8-bit alpha */
++      VC_IMAGE_TF_YA88,
++      /* VCIII T-format 8 bit generic sample */
++      VC_IMAGE_TF_BYTE,
++      /* VCIII T-format 8-bit palette */
++      VC_IMAGE_TF_PAL8,
++      /* VCIII T-format 4-bit palette */
++      VC_IMAGE_TF_PAL4,
++      /* VCIII T-format Ericsson Texture Compressed */
++      VC_IMAGE_TF_ETC1,
++      /* RGB888 with R & B swapped */
++      VC_IMAGE_BGR888,
++      /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after
++       * each row of pixels
++       */
++      VC_IMAGE_BGR888_NP,
++      /* Bayer image, extra defines which variant is being used */
++      VC_IMAGE_BAYER,
++      /* General wrapper for codec images e.g. JPEG from camera */
++      VC_IMAGE_CODEC,
++      /* VCIII codec format */
++      VC_IMAGE_YUV_UV32,
++      /* VCIII T-format 8-bit luma */
++      VC_IMAGE_TF_Y8,
++      /* VCIII T-format 8-bit alpha */
++      VC_IMAGE_TF_A8,
++      /* VCIII T-format 16-bit generic sample */
++      VC_IMAGE_TF_SHORT,
++      /* VCIII T-format 1bpp black/white */
++      VC_IMAGE_TF_1BPP,
++      VC_IMAGE_OPENGL,
++      /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
++      VC_IMAGE_YUV444I,
++      /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on
++       * a per line basis)
++       */
++      VC_IMAGE_YUV422PLANAR,
++      /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
++      VC_IMAGE_ARGB8888,
++      /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
++      VC_IMAGE_XRGB8888,
++
++      /* interleaved 8 bit samples of Y, U, Y, V (4 flavours) */
++      VC_IMAGE_YUV422YUYV,
++      VC_IMAGE_YUV422YVYU,
++      VC_IMAGE_YUV422UYVY,
++      VC_IMAGE_YUV422VYUY,
++
++      /* 32bpp like RGBA32 but with unused alpha */
++      VC_IMAGE_RGBX32,
++      /* 32bpp, corresponding to RGBA with unused alpha */
++      VC_IMAGE_RGBX8888,
++      /* 32bpp, corresponding to BGRA with unused alpha */
++      VC_IMAGE_BGRX8888,
++
++      /* Y as a plane, then UV byte interleaved in plane with with same pitch,
++       * half height
++       */
++      VC_IMAGE_YUV420SP,
++
++      /* Y, U, & V planes separately 4:4:4 */
++      VC_IMAGE_YUV444PLANAR,
++
++      /* T-format 8-bit U - same as TF_Y8 buf from U plane */
++      VC_IMAGE_TF_U8,
++      /* T-format 8-bit U - same as TF_Y8 buf from V plane */
++      VC_IMAGE_TF_V8,
++
++      /* YUV4:2:0 planar, 16bit values */
++      VC_IMAGE_YUV420_16,
++      /* YUV4:2:0 codec format, 16bit values */
++      VC_IMAGE_YUV_UV_16,
++      /* YUV4:2:0 with U,V in side-by-side format */
++      VC_IMAGE_YUV420_S,
++
++      VC_IMAGE_MAX,     /* bounds for error checking */
++      VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
++};
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -148,6 +148,8 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
++      RPI_FIRMWARE_SET_PLANE =                              0x00048015,
++
+       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
+       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0518-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch b/target/linux/brcm2708/patches-4.19/950-0518-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch
deleted file mode 100644 (file)
index 4fb6f66..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From c0041a9fe33d6031267d9f3e2372833908e97337 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 2 Apr 2019 13:29:00 -0700
-Subject: [PATCH] drm/vc4: Fix vblank timestamping for firmwarekms.
-
-The core doesn't expect a false return from the scanoutpos function in
-normal usage, so we were doing the precise vblank timestamping path
-and thus "immediate" vblank disables (even though firmwarekms can't
-actually disable vblanks interrupts, sigh), and the kernel would get
-confused when getting timestamp info when also turning vblanks back
-on.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_crtc.c         | 3 ---
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
- 2 files changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_crtc.c
-+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
-@@ -133,9 +133,6 @@ bool vc4_crtc_get_scanoutpos(struct drm_
-       int vblank_lines;
-       bool ret = false;
--      if (vc4->firmware_kms)
--              return 0;
--
-       /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
-       /* Get optional system timestamp before query. */
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -673,6 +673,12 @@ static int vc4_fkms_bind(struct device *
-       vc4->firmware_kms = true;
-+      /* firmware kms doesn't have precise a scanoutpos implementation, so
-+       * we can't do the precise vblank timestamp mode.
-+       */
-+      drm->driver->get_scanout_position = NULL;
-+      drm->driver->get_vblank_timestamp = NULL;
-+
-       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
-       if (!vc4_crtc)
-               return -ENOMEM;
diff --git a/target/linux/brcm2708/patches-4.19/950-0519-drm-vc4-Increase-max-screen-size-to-4096x4096.patch b/target/linux/brcm2708/patches-4.19/950-0519-drm-vc4-Increase-max-screen-size-to-4096x4096.patch
new file mode 100644 (file)
index 0000000..c81e7fc
--- /dev/null
@@ -0,0 +1,26 @@
+From 7c4a99448be56e288a5845f3de77b7eef006a450 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 3 Apr 2019 15:20:05 +0100
+Subject: [PATCH] drm: vc4: Increase max screen size to 4096x4096.
+
+We now should support 4k screens, therefore this limit needs to
+be increased.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
+               return ret;
+       }
+-      dev->mode_config.max_width = 2048;
+-      dev->mode_config.max_height = 2048;
++      dev->mode_config.max_width = 4096;
++      dev->mode_config.max_height = 4096;
+       dev->mode_config.funcs = &vc4_mode_funcs;
+       dev->mode_config.preferred_depth = 24;
+       dev->mode_config.async_page_flip = true;
diff --git a/target/linux/brcm2708/patches-4.19/950-0519-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch b/target/linux/brcm2708/patches-4.19/950-0519-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch
deleted file mode 100644 (file)
index ad729c5..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-From 3819888738de087ba726ceaa2ab20503f164f1ed Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 26 Mar 2019 14:43:06 +0000
-Subject: [PATCH] gpu: vc4-fkms: Switch to the newer mailbox frame
- buffer API.
-
-The old mailbox FB API was ideally deprecated but still used by
-the FKMS driver.
-Update to the newer API.
-
-NB This needs current firmware that accepts ARM allocated buffers
-through the newer API.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 109 +++++++++++----------
- include/soc/bcm2835/raspberrypi-firmware.h |  10 ++
- 2 files changed, 67 insertions(+), 52 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -28,6 +28,25 @@
- #include "vc4_regs.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-+struct fb_alloc_tags {
-+      struct rpi_firmware_property_tag_header tag1;
-+      u32 xres, yres;
-+      struct rpi_firmware_property_tag_header tag2;
-+      u32 xres_virtual, yres_virtual;
-+      struct rpi_firmware_property_tag_header tag3;
-+      u32 bpp;
-+      struct rpi_firmware_property_tag_header tag4;
-+      u32 xoffset, yoffset;
-+      struct rpi_firmware_property_tag_header tag5;
-+      u32 base, screen_size;
-+      struct rpi_firmware_property_tag_header tag6;
-+      u32 pitch;
-+      struct rpi_firmware_property_tag_header tag7;
-+      u32 alpha_mode;
-+      struct rpi_firmware_property_tag_header tag8;
-+      u32 layer;
-+};
-+
- /* The firmware delivers a vblank interrupt to us through the SMI
-  * hardware, which has only this one register.
-  */
-@@ -121,45 +140,39 @@ static void vc4_primary_plane_atomic_upd
-                                           struct drm_plane_state *old_state)
- {
-       struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
--      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-       struct drm_plane_state *state = plane->state;
-       struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
--      volatile struct fbinfo_s *fbinfo = vc4_plane->fbinfo;
-+      u32 format = fb->format->format;
-+      struct fb_alloc_tags fbinfo = {
-+              .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
-+                        8, 0, },
-+                      .xres = state->crtc_w,
-+                      .yres = state->crtc_h,
-+              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
-+                        8, 0, },
-+                      .xres_virtual = state->crtc_w,
-+                      .yres_virtual = state->crtc_h,
-+              .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
-+                      .bpp = 32,
-+              .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
-+                      .xoffset = 0,
-+                      .yoffset = 0,
-+              .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
-+                      .base = bo->paddr + fb->offsets[0],
-+                      .screen_size = state->crtc_w * state->crtc_h * 4,
-+              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-+                      .pitch = fb->pitches[0],
-+              .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
-+                      .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
-+              .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
-+                      .layer = -127,
-+      };
-       u32 bpp = 32;
-       int ret;
--      fbinfo->xres = state->crtc_w;
--      fbinfo->yres = state->crtc_h;
--      fbinfo->xres_virtual = state->crtc_w;
--      fbinfo->yres_virtual = state->crtc_h;
--      fbinfo->bpp = bpp;
--      fbinfo->xoffset = state->crtc_x;
--      fbinfo->yoffset = state->crtc_y;
--      fbinfo->base = bo->paddr + fb->offsets[0];
--      fbinfo->pitch = fb->pitches[0];
--
-       if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
--              fbinfo->bpp |= BIT(31);
--
--      /* A bug in the firmware makes it so that if the fb->base is
--       * set to nonzero, the configured pitch gets overwritten with
--       * the previous pitch.  So, to get the configured pitch
--       * recomputed, we have to make it allocate itself a new buffer
--       * in VC memory, first.
--       */
--      if (vc4_plane->pitch != fb->pitches[0]) {
--              u32 saved_base = fbinfo->base;
--              fbinfo->base = 0;
--
--              ret = rpi_firmware_transaction(vc4->firmware,
--                                             RPI_FIRMWARE_CHAN_FB,
--                                             vc4_plane->fbinfo_bus_addr);
--              fbinfo->base = saved_base;
--
--              vc4_plane->pitch = fbinfo->pitch;
--              WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]);
--      }
-+              fbinfo.bpp |= BIT(31);
-       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
-                        plane->base.id, plane->name,
-@@ -168,14 +181,13 @@ static void vc4_primary_plane_atomic_upd
-                        bpp,
-                        state->crtc_x,
-                        state->crtc_y,
--                       &fbinfo->base,
-+                       &fbinfo.base,
-                        fb->pitches[0]);
--      ret = rpi_firmware_transaction(vc4->firmware,
--                                     RPI_FIRMWARE_CHAN_FB,
--                                     vc4_plane->fbinfo_bus_addr);
--      WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]);
--      WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[0]);
-+      ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
-+                                       sizeof(fbinfo));
-+      WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
-+      WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
-       /* If the CRTC is on (or going to be on) and we're enabled,
-        * then unblank.  Otherwise, stay blank until CRTC enable.
-@@ -332,10 +344,10 @@ static const struct drm_plane_helper_fun
- static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
-                                            enum drm_plane_type type)
- {
-+      /* Primary and cursor planes only */
-       struct drm_plane *plane = NULL;
-       struct vc4_fkms_plane *vc4_plane;
--      u32 xrgb8888 = DRM_FORMAT_XRGB8888;
--      u32 argb8888 = DRM_FORMAT_ARGB8888;
-+      u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
-       int ret = 0;
-       bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
-       static const uint64_t modifiers[] = {
-@@ -357,22 +369,15 @@ static struct drm_plane *vc4_fkms_plane_
-       plane = &vc4_plane->base;
-       ret = drm_universal_plane_init(dev, plane, 0xff,
-                                      &vc4_plane_funcs,
--                                     primary ? &xrgb8888 : &argb8888, 1,
--                                     modifiers,
-+                                     formats, primary ? 2 : 1, modifiers,
-                                      type, primary ? "primary" : "cursor");
--      if (type == DRM_PLANE_TYPE_PRIMARY) {
--              vc4_plane->fbinfo =
--                      dma_alloc_coherent(dev->dev,
--                                         sizeof(*vc4_plane->fbinfo),
--                                         &vc4_plane->fbinfo_bus_addr,
--                                         GFP_KERNEL);
--              memset(vc4_plane->fbinfo, 0, sizeof(*vc4_plane->fbinfo));
--
-+      if (type == DRM_PLANE_TYPE_PRIMARY)
-               drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
--      } else {
-+      else
-               drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
--      }
-+
-+      drm_plane_create_alpha_property(plane);
-       return plane;
- fail:
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -111,9 +111,15 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET =         0x00040009,
-       RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN =               0x0004000a,
-       RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE =                0x0004000b,
-+      RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER =                  0x0004000c,
-+      RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM =              0x0004000d,
-+      RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC =                  0x0004000e,
-       RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF =               0x0004000f,
-       RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF =            0x00040010,
-       RPI_FIRMWARE_FRAMEBUFFER_RELEASE =                    0x00048001,
-+      RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM =            0x00048013,
-+      RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS =           0x00040013,
-+      RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS =       0x00040014,
-       RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
-       RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT =  0x00044004,
-       RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH =                 0x00044005,
-@@ -122,6 +128,8 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET =        0x00044009,
-       RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN =              0x0004400a,
-       RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE =               0x0004400b,
-+      RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER =                 0x0004400c,
-+      RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM =             0x0004400d,
-       RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC =                 0x0004400e,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT =  0x00048003,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT =   0x00048004,
-@@ -134,6 +142,8 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF =               0x0004801f,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF =            0x00048020,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC =                  0x0004800e,
-+      RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER =                  0x0004800c,
-+      RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM =              0x0004800d,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT =              0x0004800f,
-       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
diff --git a/target/linux/brcm2708/patches-4.19/950-0520-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch b/target/linux/brcm2708/patches-4.19/950-0520-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch
deleted file mode 100644 (file)
index f3e2851..0000000
+++ /dev/null
@@ -1,853 +0,0 @@
-From 953d85d97f59691dccbbca743c478a8b01f92b59 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 27 Mar 2019 17:45:01 +0000
-Subject: [PATCH] drm: vc4: Add an overlay plane to vc4-firmware-kms
-
-This uses a new API that is exposed via the mailbox service
-to stick an element straight on the screen using DispmanX.
-
-The primary and cursor planes have also been switched to using
-the new plane API, and it supports layering based on the DRM
-zpos parameter.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 518 ++++++++++++++-------
- drivers/gpu/drm/vc4/vc4_kms.c              |   1 +
- drivers/gpu/drm/vc4/vc_image_types.h       | 143 ++++++
- include/soc/bcm2835/raspberrypi-firmware.h |   2 +
- 4 files changed, 495 insertions(+), 169 deletions(-)
- create mode 100644 drivers/gpu/drm/vc4/vc_image_types.h
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -26,8 +26,46 @@
- #include "linux/of_device.h"
- #include "vc4_drv.h"
- #include "vc4_regs.h"
-+#include "vc_image_types.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-+struct set_plane {
-+      u8 display;
-+      u8 plane_id;
-+      u8 vc_image_type;
-+      s8 layer;
-+
-+      u16 width;
-+      u16 height;
-+
-+      u16 pitch;
-+      u16 vpitch;
-+
-+      u32 src_x;      /* 16p16 */
-+      u32 src_y;      /* 16p16 */
-+
-+      u32 src_w;      /* 16p16 */
-+      u32 src_h;      /* 16p16 */
-+
-+      s16 dst_x;
-+      s16 dst_y;
-+
-+      u16 dst_w;
-+      u16 dst_h;
-+
-+      u8 alpha;
-+      u8 num_planes;
-+      u8 is_vu;
-+      u8 padding;
-+
-+      u32 planes[4];  /* DMA address of each plane */
-+};
-+
-+struct mailbox_set_plane {
-+      struct rpi_firmware_property_tag_header tag;
-+      struct set_plane plane;
-+};
-+
- struct fb_alloc_tags {
-       struct rpi_firmware_property_tag_header tag1;
-       u32 xres, yres;
-@@ -47,6 +85,79 @@ struct fb_alloc_tags {
-       u32 layer;
- };
-+static const struct vc_image_format {
-+      u32 drm;        /* DRM_FORMAT_* */
-+      u32 vc_image;   /* VC_IMAGE_* */
-+      u32 is_vu;
-+} vc_image_formats[] = {
-+      {
-+              .drm = DRM_FORMAT_XRGB8888,
-+              .vc_image = VC_IMAGE_XRGB8888,
-+      },
-+      {
-+              .drm = DRM_FORMAT_ARGB8888,
-+              .vc_image = VC_IMAGE_ARGB8888,
-+      },
-+/*
-+ *    FIXME: Need to resolve which DRM format goes to which vc_image format
-+ *    for the remaining RGBA and RGBX formats.
-+ *    {
-+ *            .drm = DRM_FORMAT_ABGR8888,
-+ *            .vc_image = VC_IMAGE_RGBA8888,
-+ *    },
-+ *    {
-+ *            .drm = DRM_FORMAT_XBGR8888,
-+ *            .vc_image = VC_IMAGE_RGBA8888,
-+ *    },
-+ */
-+      {
-+              .drm = DRM_FORMAT_RGB565,
-+              .vc_image = VC_IMAGE_RGB565,
-+      },
-+      {
-+              .drm = DRM_FORMAT_RGB888,
-+              .vc_image = VC_IMAGE_BGR888,
-+      },
-+      {
-+              .drm = DRM_FORMAT_BGR888,
-+              .vc_image = VC_IMAGE_RGB888,
-+      },
-+      {
-+              .drm = DRM_FORMAT_YUV422,
-+              .vc_image = VC_IMAGE_YUV422PLANAR,
-+      },
-+      {
-+              .drm = DRM_FORMAT_YUV420,
-+              .vc_image = VC_IMAGE_YUV420,
-+      },
-+      {
-+              .drm = DRM_FORMAT_YVU420,
-+              .vc_image = VC_IMAGE_YUV420,
-+              .is_vu = 1,
-+      },
-+      {
-+              .drm = DRM_FORMAT_NV12,
-+              .vc_image = VC_IMAGE_YUV420SP,
-+      },
-+      {
-+              .drm = DRM_FORMAT_NV21,
-+              .vc_image = VC_IMAGE_YUV420SP,
-+              .is_vu = 1,
-+      },
-+};
-+
-+static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format)
-+{
-+      unsigned int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) {
-+              if (vc_image_formats[i].drm == drm_format)
-+                      return &vc_image_formats[i];
-+      }
-+
-+      return NULL;
-+}
-+
- /* The firmware delivers a vblank interrupt to us through the SMI
-  * hardware, which has only this one register.
-  */
-@@ -113,6 +224,7 @@ struct vc4_fkms_plane {
-       struct fbinfo_s *fbinfo;
-       dma_addr_t fbinfo_bus_addr;
-       u32 pitch;
-+      struct mailbox_set_plane mb;
- };
- static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane)
-@@ -120,165 +232,183 @@ static inline struct vc4_fkms_plane *to_
-       return (struct vc4_fkms_plane *)plane;
- }
--/* Turns the display on/off. */
--static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank)
-+static int vc4_plane_set_blank(struct drm_plane *plane, bool blank)
- {
-       struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
-+      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-+      struct mailbox_set_plane blank_mb = {
-+              .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 },
-+              .plane = {
-+                      .display = vc4_plane->mb.plane.display,
-+                      .plane_id = vc4_plane->mb.plane.plane_id,
-+              }
-+      };
-+      int ret;
--      u32 packet = blank;
--
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s",
-+      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
-                        plane->base.id, plane->name,
-                        blank ? "blank" : "unblank");
--      return rpi_firmware_property(vc4->firmware,
--                                   RPI_FIRMWARE_FRAMEBUFFER_BLANK,
--                                   &packet, sizeof(packet));
-+      if (blank)
-+              ret = rpi_firmware_property_list(vc4->firmware, &blank_mb,
-+                                               sizeof(blank_mb));
-+      else
-+              ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb,
-+                                               sizeof(vc4_plane->mb));
-+
-+      WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware",
-+                __func__);
-+      return ret;
- }
--static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
--                                          struct drm_plane_state *old_state)
-+static void vc4_plane_atomic_update(struct drm_plane *plane,
-+                                  struct drm_plane_state *old_state)
- {
--      struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
-       struct drm_plane_state *state = plane->state;
-       struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
--      u32 format = fb->format->format;
--      struct fb_alloc_tags fbinfo = {
--              .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
--                        8, 0, },
--                      .xres = state->crtc_w,
--                      .yres = state->crtc_h,
--              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
--                        8, 0, },
--                      .xres_virtual = state->crtc_w,
--                      .yres_virtual = state->crtc_h,
--              .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
--                      .bpp = 32,
--              .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
--                      .xoffset = 0,
--                      .yoffset = 0,
--              .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
--                      .base = bo->paddr + fb->offsets[0],
--                      .screen_size = state->crtc_w * state->crtc_h * 4,
--              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
--                      .pitch = fb->pitches[0],
--              .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
--                      .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
--              .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
--                      .layer = -127,
--      };
--      u32 bpp = 32;
--      int ret;
-+      const struct drm_format_info *drm_fmt = fb->format;
-+      const struct vc_image_format *vc_fmt =
-+                                      vc4_get_vc_image_fmt(drm_fmt->format);
-+      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-+      struct mailbox_set_plane *mb = &vc4_plane->mb;
-+      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
-+      int num_planes = fb->format->num_planes;
-+      struct drm_display_mode *mode = &state->crtc->mode;
--      if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
--              fbinfo.bpp |= BIT(31);
-+      mb->plane.vc_image_type = vc_fmt->vc_image;
-+      mb->plane.width = fb->width;
-+      mb->plane.height = fb->height;
-+      mb->plane.pitch = fb->pitches[0];
-+      mb->plane.src_w = state->src_w;
-+      mb->plane.src_h = state->src_h;
-+      mb->plane.src_x = state->src_x;
-+      mb->plane.src_y = state->src_y;
-+      mb->plane.dst_w = state->crtc_w;
-+      mb->plane.dst_h = state->crtc_h;
-+      mb->plane.dst_x = state->crtc_x;
-+      mb->plane.dst_y = state->crtc_y;
-+      mb->plane.alpha = state->alpha >> 8;
-+      mb->plane.layer = state->normalized_zpos ?
-+                                      state->normalized_zpos : -127;
-+      mb->plane.num_planes = num_planes;
-+      mb->plane.is_vu = vc_fmt->is_vu;
-+      mb->plane.planes[0] = bo->paddr + fb->offsets[0];
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
-+      /* FIXME: If the dest rect goes off screen then clip the src rect so we
-+       * don't have off-screen pixels.
-+       */
-+      if (plane->type == DRM_PLANE_TYPE_CURSOR) {
-+              /* There is no scaling on the cursor plane, therefore the calcs
-+               * to alter the source crop as the cursor goes off the screen
-+               * are simple.
-+               */
-+              if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
-+                      mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
-+                      mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
-+                                                                      << 16;
-+              }
-+              if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
-+                      mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
-+                      mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
-+                                                                      << 16;
-+              }
-+      }
-+
-+      if (num_planes > 1) {
-+              /* Assume this must be YUV */
-+              /* Makes assumptions on the stride for the chroma planes as we
-+               * can't easily plumb in non-standard pitches.
-+               */
-+              mb->plane.planes[1] = bo->paddr + fb->offsets[1];
-+              if (num_planes > 2)
-+                      mb->plane.planes[2] = bo->paddr + fb->offsets[2];
-+              else
-+                      mb->plane.planes[2] = 0;
-+
-+              /* Special case the YUV420 with U and V as line interleaved
-+               * planes as we have special handling for that case.
-+               */
-+              if (num_planes == 3 &&
-+                  (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
-+                      mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
-+      } else {
-+              mb->plane.planes[1] = 0;
-+              mb->plane.planes[2] = 0;
-+      }
-+      mb->plane.planes[3] = 0;
-+
-+      switch (fb->modifier) {
-+      case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
-+              switch (mb->plane.vc_image_type) {
-+              case VC_IMAGE_RGBX32:
-+                      mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
-+                      break;
-+              case VC_IMAGE_RGBA32:
-+                      mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
-+                      break;
-+              case VC_IMAGE_RGB565:
-+                      mb->plane.vc_image_type = VC_IMAGE_TF_RGB565;
-+                      break;
-+              }
-+              break;
-+      case DRM_FORMAT_MOD_BROADCOM_SAND128:
-+              mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
-+              mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
-+              break;
-+      }
-+
-+      if (vc4_crtc) {
-+              mb->plane.dst_x += vc4_crtc->overscan[0];
-+              mb->plane.dst_y += vc4_crtc->overscan[1];
-+      }
-+
-+      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
-                        plane->base.id, plane->name,
--                       state->crtc_w,
--                       state->crtc_h,
--                       bpp,
-+                       mb->plane.width,
-+                       mb->plane.height,
-+                       mb->plane.vc_image_type,
-                        state->crtc_x,
-                        state->crtc_y,
--                       &fbinfo.base,
--                       fb->pitches[0]);
--
--      ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
--                                       sizeof(fbinfo));
--      WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
--      WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
--
--      /* If the CRTC is on (or going to be on) and we're enabled,
-+                       state->crtc_w,
-+                       state->crtc_h,
-+                       mb->plane.src_x,
-+                       mb->plane.src_y,
-+                       mb->plane.src_w,
-+                       mb->plane.src_h,
-+                       mb->plane.planes[0],
-+                       mb->plane.planes[1],
-+                       mb->plane.planes[2],
-+                       fb->pitches[0],
-+                       state->alpha,
-+                       state->normalized_zpos);
-+
-+      /*
-+       * Do NOT set now, as we haven't checked if the crtc is active or not.
-+       * Set from vc4_plane_set_blank instead.
-+       *
-+       * If the CRTC is on (or going to be on) and we're enabled,
-        * then unblank.  Otherwise, stay blank until CRTC enable.
--      */
-+       */
-       if (state->crtc->state->active)
--              vc4_plane_set_primary_blank(plane, false);
-+              vc4_plane_set_blank(plane, false);
- }
--static void vc4_primary_plane_atomic_disable(struct drm_plane *plane,
--                                           struct drm_plane_state *old_state)
-+static void vc4_plane_atomic_disable(struct drm_plane *plane,
-+                                   struct drm_plane_state *old_state)
- {
--      vc4_plane_set_primary_blank(plane, true);
--}
--
--static void vc4_cursor_plane_atomic_update(struct drm_plane *plane,
--                                         struct drm_plane_state *old_state)
--{
--      struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
-+      //struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
-       struct drm_plane_state *state = plane->state;
--      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
--      struct drm_framebuffer *fb = state->fb;
--      struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
--      dma_addr_t addr = bo->paddr + fb->offsets[0];
--      int ret;
--      u32 packet_state[] = {
--              state->crtc->state->active,
--              state->crtc_x,
--              state->crtc_y,
--              0
--      };
--      WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
-+      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
-+      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
-                        plane->base.id, plane->name,
-                        state->crtc_w,
-                        state->crtc_h,
-+                       vc4_plane->mb.plane.vc_image_type,
-                        state->crtc_x,
--                       state->crtc_y,
--                       &addr,
--                       fb->pitches[0]);
--
--      /* add on the top/left offsets when overscan is active */
--      if (vc4_crtc) {
--              packet_state[1] += vc4_crtc->overscan[0];
--              packet_state[2] += vc4_crtc->overscan[1];
--      }
--
--      ret = rpi_firmware_property(vc4->firmware,
--                                  RPI_FIRMWARE_SET_CURSOR_STATE,
--                                  &packet_state,
--                                  sizeof(packet_state));
--      if (ret || packet_state[0] != 0)
--              DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
--
--      /* Note: When the cursor contents change, the modesetting
--       * driver calls drm_mode_cursor_univeral() with
--       * DRM_MODE_CURSOR_BO, which means a new fb will be allocated.
--       */
--      if (!old_state ||
--          state->crtc_w != old_state->crtc_w ||
--          state->crtc_h != old_state->crtc_h ||
--          fb != old_state->fb) {
--              u32 packet_info[] = { state->crtc_w, state->crtc_h,
--                                    0, /* unused */
--                                    addr,
--                                    0, 0, /* hotx, hoty */};
--
--              ret = rpi_firmware_property(vc4->firmware,
--                                          RPI_FIRMWARE_SET_CURSOR_INFO,
--                                          &packet_info,
--                                          sizeof(packet_info));
--              if (ret || packet_info[0] != 0)
--                      DRM_ERROR("Failed to set cursor info: 0x%08x\n", packet_info[0]);
--      }
--}
--
--static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane,
--                                          struct drm_plane_state *old_state)
--{
--      struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
--      u32 packet_state[] = { false, 0, 0, 0 };
--      int ret;
--
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] disabling cursor", plane->base.id, plane->name);
--
--      ret = rpi_firmware_property(vc4->firmware,
--                                  RPI_FIRMWARE_SET_CURSOR_STATE,
--                                  &packet_state,
--                                  sizeof(packet_state));
--      if (ret || packet_state[0] != 0)
--              DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
-+                       state->crtc_y);
-+      vc4_plane_set_blank(plane, true);
- }
- static int vc4_plane_atomic_check(struct drm_plane *plane,
-@@ -301,6 +431,7 @@ static bool vc4_fkms_format_mod_supporte
-       switch (format) {
-       case DRM_FORMAT_XRGB8888:
-       case DRM_FORMAT_ARGB8888:
-+      case DRM_FORMAT_RGB565:
-               switch (modifier) {
-               case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
-               case DRM_FORMAT_MOD_LINEAR:
-@@ -309,8 +440,22 @@ static bool vc4_fkms_format_mod_supporte
-               default:
-                       return false;
-               }
-+      case DRM_FORMAT_NV12:
-+      case DRM_FORMAT_NV21:
-+              switch (fourcc_mod_broadcom_mod(modifier)) {
-+              case DRM_FORMAT_MOD_LINEAR:
-+              case DRM_FORMAT_MOD_BROADCOM_SAND128:
-+                      return true;
-+              default:
-+                      return false;
-+              }
-+      case DRM_FORMAT_RGB888:
-+      case DRM_FORMAT_BGR888:
-+      case DRM_FORMAT_YUV422:
-+      case DRM_FORMAT_YUV420:
-+      case DRM_FORMAT_YVU420:
-       default:
--              return false;
-+              return (modifier == DRM_FORMAT_MOD_LINEAR);
-       }
- }
-@@ -325,31 +470,24 @@ static const struct drm_plane_funcs vc4_
-       .format_mod_supported = vc4_fkms_format_mod_supported,
- };
--static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
--      .prepare_fb = drm_gem_fb_prepare_fb,
--      .cleanup_fb = NULL,
--      .atomic_check = vc4_plane_atomic_check,
--      .atomic_update = vc4_primary_plane_atomic_update,
--      .atomic_disable = vc4_primary_plane_atomic_disable,
--};
--
--static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
-+static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
-       .prepare_fb = drm_gem_fb_prepare_fb,
-       .cleanup_fb = NULL,
-       .atomic_check = vc4_plane_atomic_check,
--      .atomic_update = vc4_cursor_plane_atomic_update,
--      .atomic_disable = vc4_cursor_plane_atomic_disable,
-+      .atomic_update = vc4_plane_atomic_update,
-+      .atomic_disable = vc4_plane_atomic_disable,
- };
- static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
--                                           enum drm_plane_type type)
-+                                           enum drm_plane_type type,
-+                                           u8 plane_id)
- {
--      /* Primary and cursor planes only */
-       struct drm_plane *plane = NULL;
-       struct vc4_fkms_plane *vc4_plane;
--      u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
-+      u32 formats[ARRAY_SIZE(vc_image_formats)];
-+      unsigned int default_zpos;
-+      u32 num_formats = 0;
-       int ret = 0;
--      bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
-       static const uint64_t modifiers[] = {
-               DRM_FORMAT_MOD_LINEAR,
-               /* VC4_T_TILED should come after linear, because we
-@@ -358,6 +496,7 @@ static struct drm_plane *vc4_fkms_plane_
-               DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
-               DRM_FORMAT_MOD_INVALID,
-       };
-+      int i;
-       vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
-                                GFP_KERNEL);
-@@ -366,19 +505,48 @@ static struct drm_plane *vc4_fkms_plane_
-               goto fail;
-       }
-+      for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++)
-+              formats[num_formats++] = vc_image_formats[i].drm;
-+
-       plane = &vc4_plane->base;
-       ret = drm_universal_plane_init(dev, plane, 0xff,
-                                      &vc4_plane_funcs,
--                                     formats, primary ? 2 : 1, modifiers,
--                                     type, primary ? "primary" : "cursor");
-+                                     formats, num_formats, modifiers,
-+                                     type, NULL);
--      if (type == DRM_PLANE_TYPE_PRIMARY)
--              drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
--      else
--              drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
-+      drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
-       drm_plane_create_alpha_property(plane);
-+      /*
-+       * Default frame buffer setup is with FB on -127, and raspistill etc
-+       * tend to drop overlays on layer 2. Cursor plane was on layer +127.
-+       *
-+       * For F-KMS the mailbox call allows for a s8.
-+       * Remap zpos 0 to -127 for the background layer, but leave all the
-+       * other layers as requested by KMS.
-+       */
-+      switch (type) {
-+      case DRM_PLANE_TYPE_PRIMARY:
-+              default_zpos = 0;
-+              break;
-+      case DRM_PLANE_TYPE_OVERLAY:
-+              default_zpos = 1;
-+              break;
-+      case DRM_PLANE_TYPE_CURSOR:
-+              default_zpos = 2;
-+              break;
-+      }
-+      drm_plane_create_zpos_property(plane, default_zpos, 0, 127);
-+
-+      /* Prepare the static elements of the mailbox structure */
-+      vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
-+      vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
-+      vc4_plane->mb.tag.req_resp_size = 0;
-+      vc4_plane->mb.plane.display = 0;
-+      vc4_plane->mb.plane.plane_id = plane_id;
-+      vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
-+
-       return plane;
- fail:
-       if (plane)
-@@ -400,19 +568,23 @@ static void vc4_crtc_disable(struct drm_
-        * whether anything scans out at all, but the firmware doesn't
-        * give us a CRTC-level control for that.
-        */
--      vc4_cursor_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
--      vc4_plane_set_primary_blank(crtc->primary, true);
-+
-+      vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
-+      vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
-+
-+      /* FIXME: Disable overlay planes */
- }
- static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-       /* Unblank the planes (if they're supposed to be displayed). */
-+
-       if (crtc->primary->state->fb)
--              vc4_plane_set_primary_blank(crtc->primary, false);
--      if (crtc->cursor->state->fb) {
--              vc4_cursor_plane_atomic_update(crtc->cursor,
--                                             crtc->cursor->state);
--      }
-+              vc4_plane_set_blank(crtc->primary, false);
-+      if (crtc->cursor->state->fb)
-+              vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
-+
-+      /* FIXME: Enable overlay planes */
- }
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
-@@ -672,8 +844,10 @@ static int vc4_fkms_bind(struct device *
-       struct vc4_crtc *vc4_crtc;
-       struct vc4_fkms_encoder *vc4_encoder;
-       struct drm_crtc *crtc;
--      struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp;
-+      struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
-+      struct drm_plane *destroy_plane, *temp;
-       struct device_node *firmware_node;
-+      u32 blank = 1;
-       int ret;
-       vc4->firmware_kms = true;
-@@ -702,20 +876,26 @@ static int vc4_fkms_bind(struct device *
-       if (IS_ERR(vc4_crtc->regs))
-               return PTR_ERR(vc4_crtc->regs);
--      /* For now, we create just the primary and the legacy cursor
--       * planes.  We should be able to stack more planes on easily,
--       * but to do that we would need to compute the bandwidth
--       * requirement of the plane configuration, and reject ones
--       * that will take too much.
--       */
--      primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
-+      /* Blank the firmware provided framebuffer */
-+      rpi_firmware_property(vc4->firmware,
-+                            RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-+                            &blank, sizeof(blank));
-+
-+      primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
-       if (IS_ERR(primary_plane)) {
-               dev_err(dev, "failed to construct primary plane\n");
-               ret = PTR_ERR(primary_plane);
-               goto err;
-       }
--      cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
-+      overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1);
-+      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, 2);
-       if (IS_ERR(cursor_plane)) {
-               dev_err(dev, "failed to construct cursor plane\n");
-               ret = PTR_ERR(cursor_plane);
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -435,6 +435,7 @@ int vc4_kms_load(struct drm_device *dev)
-       dev->mode_config.preferred_depth = 24;
-       dev->mode_config.async_page_flip = true;
-       dev->mode_config.allow_fb_modifiers = true;
-+      dev->mode_config.normalize_zpos = true;
-       drm_modeset_lock_init(&vc4->ctm_state_lock);
---- /dev/null
-+++ b/drivers/gpu/drm/vc4/vc_image_types.h
-@@ -0,0 +1,143 @@
-+
-+/*
-+ * Copyright (c) 2012, Broadcom Europe Ltd
-+ *
-+ * Values taken from vc_image_types.h released by Broadcom at
-+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
-+ *
-+ * 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.
-+ */
-+
-+enum {
-+      VC_IMAGE_MIN = 0, //bounds for error checking
-+
-+      VC_IMAGE_RGB565 = 1,
-+      VC_IMAGE_1BPP,
-+      VC_IMAGE_YUV420,
-+      VC_IMAGE_48BPP,
-+      VC_IMAGE_RGB888,
-+      VC_IMAGE_8BPP,
-+      /* 4bpp palettised image */
-+      VC_IMAGE_4BPP,
-+      /* A separated format of 16 colour/light shorts followed by 16 z
-+       * values
-+       */
-+      VC_IMAGE_3D32,
-+      /* 16 colours followed by 16 z values */
-+      VC_IMAGE_3D32B,
-+      /* A separated format of 16 material/colour/light shorts followed by
-+       * 16 z values
-+       */
-+      VC_IMAGE_3D32MAT,
-+      /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
-+      VC_IMAGE_RGB2X9,
-+      /* 32-bit format holding 18 bits of 6.6.6 RGB */
-+      VC_IMAGE_RGB666,
-+      /* 4bpp palettised image with embedded palette */
-+      VC_IMAGE_PAL4_OBSOLETE,
-+      /* 8bpp palettised image with embedded palette */
-+      VC_IMAGE_PAL8_OBSOLETE,
-+      /* RGB888 with an alpha byte after each pixel */
-+      VC_IMAGE_RGBA32,
-+      /* a line of Y (32-byte padded), a line of U (16-byte padded), and a
-+       * line of V (16-byte padded)
-+       */
-+      VC_IMAGE_YUV422,
-+      /* RGB565 with a transparent patch */
-+      VC_IMAGE_RGBA565,
-+      /* Compressed (4444) version of RGBA32 */
-+      VC_IMAGE_RGBA16,
-+      /* VCIII codec format */
-+      VC_IMAGE_YUV_UV,
-+      /* VCIII T-format RGBA8888 */
-+      VC_IMAGE_TF_RGBA32,
-+      /* VCIII T-format RGBx8888 */
-+      VC_IMAGE_TF_RGBX32,
-+      /* VCIII T-format float */
-+      VC_IMAGE_TF_FLOAT,
-+      /* VCIII T-format RGBA4444 */
-+      VC_IMAGE_TF_RGBA16,
-+      /* VCIII T-format RGB5551 */
-+      VC_IMAGE_TF_RGBA5551,
-+      /* VCIII T-format RGB565 */
-+      VC_IMAGE_TF_RGB565,
-+      /* VCIII T-format 8-bit luma and 8-bit alpha */
-+      VC_IMAGE_TF_YA88,
-+      /* VCIII T-format 8 bit generic sample */
-+      VC_IMAGE_TF_BYTE,
-+      /* VCIII T-format 8-bit palette */
-+      VC_IMAGE_TF_PAL8,
-+      /* VCIII T-format 4-bit palette */
-+      VC_IMAGE_TF_PAL4,
-+      /* VCIII T-format Ericsson Texture Compressed */
-+      VC_IMAGE_TF_ETC1,
-+      /* RGB888 with R & B swapped */
-+      VC_IMAGE_BGR888,
-+      /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after
-+       * each row of pixels
-+       */
-+      VC_IMAGE_BGR888_NP,
-+      /* Bayer image, extra defines which variant is being used */
-+      VC_IMAGE_BAYER,
-+      /* General wrapper for codec images e.g. JPEG from camera */
-+      VC_IMAGE_CODEC,
-+      /* VCIII codec format */
-+      VC_IMAGE_YUV_UV32,
-+      /* VCIII T-format 8-bit luma */
-+      VC_IMAGE_TF_Y8,
-+      /* VCIII T-format 8-bit alpha */
-+      VC_IMAGE_TF_A8,
-+      /* VCIII T-format 16-bit generic sample */
-+      VC_IMAGE_TF_SHORT,
-+      /* VCIII T-format 1bpp black/white */
-+      VC_IMAGE_TF_1BPP,
-+      VC_IMAGE_OPENGL,
-+      /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
-+      VC_IMAGE_YUV444I,
-+      /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on
-+       * a per line basis)
-+       */
-+      VC_IMAGE_YUV422PLANAR,
-+      /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
-+      VC_IMAGE_ARGB8888,
-+      /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
-+      VC_IMAGE_XRGB8888,
-+
-+      /* interleaved 8 bit samples of Y, U, Y, V (4 flavours) */
-+      VC_IMAGE_YUV422YUYV,
-+      VC_IMAGE_YUV422YVYU,
-+      VC_IMAGE_YUV422UYVY,
-+      VC_IMAGE_YUV422VYUY,
-+
-+      /* 32bpp like RGBA32 but with unused alpha */
-+      VC_IMAGE_RGBX32,
-+      /* 32bpp, corresponding to RGBA with unused alpha */
-+      VC_IMAGE_RGBX8888,
-+      /* 32bpp, corresponding to BGRA with unused alpha */
-+      VC_IMAGE_BGRX8888,
-+
-+      /* Y as a plane, then UV byte interleaved in plane with with same pitch,
-+       * half height
-+       */
-+      VC_IMAGE_YUV420SP,
-+
-+      /* Y, U, & V planes separately 4:4:4 */
-+      VC_IMAGE_YUV444PLANAR,
-+
-+      /* T-format 8-bit U - same as TF_Y8 buf from U plane */
-+      VC_IMAGE_TF_U8,
-+      /* T-format 8-bit U - same as TF_Y8 buf from V plane */
-+      VC_IMAGE_TF_V8,
-+
-+      /* YUV4:2:0 planar, 16bit values */
-+      VC_IMAGE_YUV420_16,
-+      /* YUV4:2:0 codec format, 16bit values */
-+      VC_IMAGE_YUV_UV_16,
-+      /* YUV4:2:0 with U,V in side-by-side format */
-+      VC_IMAGE_YUV420_S,
-+
-+      VC_IMAGE_MAX,     /* bounds for error checking */
-+      VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
-+};
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -148,6 +148,8 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
-+      RPI_FIRMWARE_SET_PLANE =                              0x00048015,
-+
-       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
-       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0520-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch b/target/linux/brcm2708/patches-4.19/950-0520-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch
new file mode 100644 (file)
index 0000000..06f8cf4
--- /dev/null
@@ -0,0 +1,280 @@
+From 4817db177a74ac58671e1fe84d98d584375d9697 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 3 Apr 2019 17:15:45 +0100
+Subject: [PATCH] drm: vc4: Add support for multiple displays to fkms
+
+There is a slightly nasty hack in that all crtcs share the
+same SMI interrupt from the firmware. This seems to currently
+work well enough, but ought to be fixed at a later date.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 160 +++++++++++++++++--------
+ 1 file changed, 113 insertions(+), 47 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -29,6 +29,8 @@
+ #include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
++#define PLANES_PER_CRTC               3
++
+ struct set_plane {
+       u8 display;
+       u8 plane_id;
+@@ -175,6 +177,7 @@ struct vc4_crtc {
+       struct drm_pending_vblank_event *event;
+       u32 overscan[4];
+       bool vblank_enabled;
++      u32 display_number;
+ };
+ static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
+@@ -480,6 +483,7 @@ static const struct drm_plane_helper_fun
+ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
+                                            enum drm_plane_type type,
++                                           u8 display_num,
+                                            u8 plane_id)
+ {
+       struct drm_plane *plane = NULL;
+@@ -543,7 +547,7 @@ static struct drm_plane *vc4_fkms_plane_
+       vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
+       vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
+       vc4_plane->mb.tag.req_resp_size = 0;
+-      vc4_plane->mb.plane.display = 0;
++      vc4_plane->mb.plane.display = display_num;
+       vc4_plane->mb.plane.plane_id = plane_id;
+       vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
+@@ -630,16 +634,20 @@ static void vc4_crtc_handle_page_flip(st
+ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
+ {
+-      struct vc4_crtc *vc4_crtc = data;
+-      u32 stat = readl(vc4_crtc->regs + SMICS);
++      struct vc4_crtc **crtc_list = data;
++      int i;
++      u32 stat = readl(crtc_list[0]->regs + SMICS);
+       irqreturn_t ret = IRQ_NONE;
+       if (stat & SMICS_INTERRUPTS) {
+-              writel(0, vc4_crtc->regs + SMICS);
+-              if (vc4_crtc->vblank_enabled)
+-                      drm_crtc_handle_vblank(&vc4_crtc->base);
+-              vc4_crtc_handle_page_flip(vc4_crtc);
+-              ret = IRQ_HANDLED;
++              writel(0, crtc_list[0]->regs + SMICS);
++
++              for (i = 0; crtc_list[i]; i++) {
++                      if (crtc_list[i]->vblank_enabled)
++                              drm_crtc_handle_vblank(&crtc_list[i]->base);
++                      vc4_crtc_handle_page_flip(crtc_list[i]);
++                      ret = IRQ_HANDLED;
++              }
+       }
+       return ret;
+@@ -836,66 +844,55 @@ static const struct drm_encoder_helper_f
+       .disable = vc4_fkms_encoder_disable,
+ };
+-static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
++static int vc4_fkms_create_screen(struct device *dev, struct drm_device *drm,
++                                int display_idx, int display_ref,
++                                struct vc4_crtc **ret_crtc)
+ {
+-      struct platform_device *pdev = to_platform_device(dev);
+-      struct drm_device *drm = dev_get_drvdata(master);
+       struct vc4_dev *vc4 = to_vc4_dev(drm);
+       struct vc4_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 device_node *firmware_node;
+       u32 blank = 1;
+       int ret;
+-      vc4->firmware_kms = true;
+-
+-      /* firmware kms doesn't have precise a scanoutpos implementation, so
+-       * we can't do the precise vblank timestamp mode.
+-       */
+-      drm->driver->get_scanout_position = NULL;
+-      drm->driver->get_vblank_timestamp = NULL;
+-
+       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+       if (!vc4_crtc)
+               return -ENOMEM;
+       crtc = &vc4_crtc->base;
+-      firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
+-      vc4->firmware = rpi_firmware_get(firmware_node);
+-      if (!vc4->firmware) {
+-              DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n");
+-              return -EPROBE_DEFER;
+-      }
+-      of_node_put(firmware_node);
+-
+-      /* Map the SMI interrupt reg */
+-      vc4_crtc->regs = vc4_ioremap_regs(pdev, 0);
+-      if (IS_ERR(vc4_crtc->regs))
+-              return PTR_ERR(vc4_crtc->regs);
++      vc4_crtc->display_number = display_ref;
+       /* Blank the firmware provided framebuffer */
+       rpi_firmware_property(vc4->firmware,
+                             RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+                             &blank, sizeof(blank));
+-      primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
++      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, 1);
++      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, 2);
++      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);
+@@ -922,13 +919,6 @@ static int vc4_fkms_bind(struct device *
+               goto err_destroy_encoder;
+       }
+-      writel(0, vc4_crtc->regs + SMICS);
+-      ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
+-                             vc4_crtc_irq_handler, 0, "vc4 firmware kms",
+-                             vc4_crtc);
+-      if (ret)
+-              goto err_destroy_connector;
+-
+       ret = rpi_firmware_property(vc4->firmware,
+                                   RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
+                                   &vc4_crtc->overscan,
+@@ -938,7 +928,7 @@ static int vc4_fkms_bind(struct device *
+               memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
+       }
+-      platform_set_drvdata(pdev, vc4_crtc);
++      *ret_crtc = vc4_crtc;
+       return 0;
+@@ -955,15 +945,91 @@ err:
+       return ret;
+ }
++static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
++{
++      struct platform_device *pdev = to_platform_device(dev);
++      struct drm_device *drm = dev_get_drvdata(master);
++      struct vc4_dev *vc4 = to_vc4_dev(drm);
++      struct device_node *firmware_node;
++      struct vc4_crtc **crtc_list;
++      u32 num_displays, display_num;
++      int ret;
++      const u32 display_num_lookup[] = {2, 7, 1};
++
++      vc4->firmware_kms = true;
++
++      /* firmware kms doesn't have precise a scanoutpos implementation, so
++       * we can't do the precise vblank timestamp mode.
++       */
++      drm->driver->get_scanout_position = NULL;
++      drm->driver->get_vblank_timestamp = NULL;
++
++      firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
++      vc4->firmware = rpi_firmware_get(firmware_node);
++      if (!vc4->firmware) {
++              DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n");
++              return -EPROBE_DEFER;
++      }
++      of_node_put(firmware_node);
++
++      ret = rpi_firmware_property(vc4->firmware,
++                                  RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
++                                  &num_displays, sizeof(u32));
++
++      /* If we fail to get the number of displays, or it returns 0, then
++       * assume old firmware that doesn't have the mailbox call, so just
++       * set one display
++       */
++      if (ret || num_displays == 0) {
++              num_displays = 1;
++              DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
++              ret = 0;
++      }
++
++      /* Allocate a list, with space for a NULL on the end */
++      crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
++                               GFP_KERNEL);
++      if (!crtc_list)
++              return -ENOMEM;
++
++      for (display_num = 0; display_num < num_displays; display_num++) {
++              ret = vc4_fkms_create_screen(dev, drm, display_num,
++                                           display_num_lookup[display_num],
++                                           &crtc_list[display_num]);
++              if (ret)
++                      DRM_ERROR("Oh dear, failed to create display %u\n",
++                                display_num);
++      }
++
++      /* Map the SMI interrupt reg */
++      crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
++      if (IS_ERR(crtc_list[0]->regs))
++              DRM_ERROR("Oh dear, failed to map registers\n");
++
++      writel(0, crtc_list[0]->regs + SMICS);
++      ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
++                             vc4_crtc_irq_handler, 0, "vc4 firmware kms",
++                             crtc_list);
++      if (ret)
++              DRM_ERROR("Oh dear, failed to register IRQ\n");
++
++      platform_set_drvdata(pdev, crtc_list);
++
++      return 0;
++}
++
+ static void vc4_fkms_unbind(struct device *dev, struct device *master,
+                           void *data)
+ {
+       struct platform_device *pdev = to_platform_device(dev);
+-      struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev);
++      struct vc4_crtc **crtc_list = dev_get_drvdata(dev);
++      int i;
+-      vc4_fkms_connector_destroy(vc4_crtc->connector);
+-      vc4_fkms_encoder_destroy(vc4_crtc->encoder);
+-      drm_crtc_cleanup(&vc4_crtc->base);
++      for (i = 0; crtc_list[i]; i++) {
++              vc4_fkms_connector_destroy(crtc_list[i]->connector);
++              vc4_fkms_encoder_destroy(crtc_list[i]->encoder);
++              drm_crtc_cleanup(&crtc_list[i]->base);
++      }
+       platform_set_drvdata(pdev, NULL);
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0521-drm-vc4-Fix-build-warning.patch b/target/linux/brcm2708/patches-4.19/950-0521-drm-vc4-Fix-build-warning.patch
new file mode 100644 (file)
index 0000000..3e6273a
--- /dev/null
@@ -0,0 +1,21 @@
+From 52d2903959ff9a1d68701a04884e18b31d051f30 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 5 Apr 2019 17:21:56 +0100
+Subject: [PATCH] drm: vc4: Fix build warning
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -932,8 +932,6 @@ static int vc4_fkms_create_screen(struct
+       return 0;
+-err_destroy_connector:
+-      vc4_fkms_connector_destroy(vc4_crtc->connector);
+ err_destroy_encoder:
+       vc4_fkms_encoder_destroy(vc4_crtc->encoder);
+       list_for_each_entry_safe(destroy_plane, temp,
diff --git a/target/linux/brcm2708/patches-4.19/950-0521-drm-vc4-Increase-max-screen-size-to-4096x4096.patch b/target/linux/brcm2708/patches-4.19/950-0521-drm-vc4-Increase-max-screen-size-to-4096x4096.patch
deleted file mode 100644 (file)
index c81e7fc..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 7c4a99448be56e288a5845f3de77b7eef006a450 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 3 Apr 2019 15:20:05 +0100
-Subject: [PATCH] drm: vc4: Increase max screen size to 4096x4096.
-
-We now should support 4k screens, therefore this limit needs to
-be increased.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
-               return ret;
-       }
--      dev->mode_config.max_width = 2048;
--      dev->mode_config.max_height = 2048;
-+      dev->mode_config.max_width = 4096;
-+      dev->mode_config.max_height = 4096;
-       dev->mode_config.funcs = &vc4_mode_funcs;
-       dev->mode_config.preferred_depth = 24;
-       dev->mode_config.async_page_flip = true;
diff --git a/target/linux/brcm2708/patches-4.19/950-0522-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch b/target/linux/brcm2708/patches-4.19/950-0522-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch
deleted file mode 100644 (file)
index 06f8cf4..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-From 4817db177a74ac58671e1fe84d98d584375d9697 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 3 Apr 2019 17:15:45 +0100
-Subject: [PATCH] drm: vc4: Add support for multiple displays to fkms
-
-There is a slightly nasty hack in that all crtcs share the
-same SMI interrupt from the firmware. This seems to currently
-work well enough, but ought to be fixed at a later date.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 160 +++++++++++++++++--------
- 1 file changed, 113 insertions(+), 47 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -29,6 +29,8 @@
- #include "vc_image_types.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-+#define PLANES_PER_CRTC               3
-+
- struct set_plane {
-       u8 display;
-       u8 plane_id;
-@@ -175,6 +177,7 @@ struct vc4_crtc {
-       struct drm_pending_vblank_event *event;
-       u32 overscan[4];
-       bool vblank_enabled;
-+      u32 display_number;
- };
- static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
-@@ -480,6 +483,7 @@ static const struct drm_plane_helper_fun
- static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
-                                            enum drm_plane_type type,
-+                                           u8 display_num,
-                                            u8 plane_id)
- {
-       struct drm_plane *plane = NULL;
-@@ -543,7 +547,7 @@ static struct drm_plane *vc4_fkms_plane_
-       vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
-       vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
-       vc4_plane->mb.tag.req_resp_size = 0;
--      vc4_plane->mb.plane.display = 0;
-+      vc4_plane->mb.plane.display = display_num;
-       vc4_plane->mb.plane.plane_id = plane_id;
-       vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
-@@ -630,16 +634,20 @@ static void vc4_crtc_handle_page_flip(st
- static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
- {
--      struct vc4_crtc *vc4_crtc = data;
--      u32 stat = readl(vc4_crtc->regs + SMICS);
-+      struct vc4_crtc **crtc_list = data;
-+      int i;
-+      u32 stat = readl(crtc_list[0]->regs + SMICS);
-       irqreturn_t ret = IRQ_NONE;
-       if (stat & SMICS_INTERRUPTS) {
--              writel(0, vc4_crtc->regs + SMICS);
--              if (vc4_crtc->vblank_enabled)
--                      drm_crtc_handle_vblank(&vc4_crtc->base);
--              vc4_crtc_handle_page_flip(vc4_crtc);
--              ret = IRQ_HANDLED;
-+              writel(0, crtc_list[0]->regs + SMICS);
-+
-+              for (i = 0; crtc_list[i]; i++) {
-+                      if (crtc_list[i]->vblank_enabled)
-+                              drm_crtc_handle_vblank(&crtc_list[i]->base);
-+                      vc4_crtc_handle_page_flip(crtc_list[i]);
-+                      ret = IRQ_HANDLED;
-+              }
-       }
-       return ret;
-@@ -836,66 +844,55 @@ static const struct drm_encoder_helper_f
-       .disable = vc4_fkms_encoder_disable,
- };
--static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
-+static int vc4_fkms_create_screen(struct device *dev, struct drm_device *drm,
-+                                int display_idx, int display_ref,
-+                                struct vc4_crtc **ret_crtc)
- {
--      struct platform_device *pdev = to_platform_device(dev);
--      struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
-       struct vc4_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 device_node *firmware_node;
-       u32 blank = 1;
-       int ret;
--      vc4->firmware_kms = true;
--
--      /* firmware kms doesn't have precise a scanoutpos implementation, so
--       * we can't do the precise vblank timestamp mode.
--       */
--      drm->driver->get_scanout_position = NULL;
--      drm->driver->get_vblank_timestamp = NULL;
--
-       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
-       if (!vc4_crtc)
-               return -ENOMEM;
-       crtc = &vc4_crtc->base;
--      firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
--      vc4->firmware = rpi_firmware_get(firmware_node);
--      if (!vc4->firmware) {
--              DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n");
--              return -EPROBE_DEFER;
--      }
--      of_node_put(firmware_node);
--
--      /* Map the SMI interrupt reg */
--      vc4_crtc->regs = vc4_ioremap_regs(pdev, 0);
--      if (IS_ERR(vc4_crtc->regs))
--              return PTR_ERR(vc4_crtc->regs);
-+      vc4_crtc->display_number = display_ref;
-       /* Blank the firmware provided framebuffer */
-       rpi_firmware_property(vc4->firmware,
-                             RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-                             &blank, sizeof(blank));
--      primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
-+      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, 1);
-+      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, 2);
-+      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);
-@@ -922,13 +919,6 @@ static int vc4_fkms_bind(struct device *
-               goto err_destroy_encoder;
-       }
--      writel(0, vc4_crtc->regs + SMICS);
--      ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
--                             vc4_crtc_irq_handler, 0, "vc4 firmware kms",
--                             vc4_crtc);
--      if (ret)
--              goto err_destroy_connector;
--
-       ret = rpi_firmware_property(vc4->firmware,
-                                   RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
-                                   &vc4_crtc->overscan,
-@@ -938,7 +928,7 @@ static int vc4_fkms_bind(struct device *
-               memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
-       }
--      platform_set_drvdata(pdev, vc4_crtc);
-+      *ret_crtc = vc4_crtc;
-       return 0;
-@@ -955,15 +945,91 @@ err:
-       return ret;
- }
-+static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
-+{
-+      struct platform_device *pdev = to_platform_device(dev);
-+      struct drm_device *drm = dev_get_drvdata(master);
-+      struct vc4_dev *vc4 = to_vc4_dev(drm);
-+      struct device_node *firmware_node;
-+      struct vc4_crtc **crtc_list;
-+      u32 num_displays, display_num;
-+      int ret;
-+      const u32 display_num_lookup[] = {2, 7, 1};
-+
-+      vc4->firmware_kms = true;
-+
-+      /* firmware kms doesn't have precise a scanoutpos implementation, so
-+       * we can't do the precise vblank timestamp mode.
-+       */
-+      drm->driver->get_scanout_position = NULL;
-+      drm->driver->get_vblank_timestamp = NULL;
-+
-+      firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
-+      vc4->firmware = rpi_firmware_get(firmware_node);
-+      if (!vc4->firmware) {
-+              DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n");
-+              return -EPROBE_DEFER;
-+      }
-+      of_node_put(firmware_node);
-+
-+      ret = rpi_firmware_property(vc4->firmware,
-+                                  RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
-+                                  &num_displays, sizeof(u32));
-+
-+      /* If we fail to get the number of displays, or it returns 0, then
-+       * assume old firmware that doesn't have the mailbox call, so just
-+       * set one display
-+       */
-+      if (ret || num_displays == 0) {
-+              num_displays = 1;
-+              DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
-+              ret = 0;
-+      }
-+
-+      /* Allocate a list, with space for a NULL on the end */
-+      crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
-+                               GFP_KERNEL);
-+      if (!crtc_list)
-+              return -ENOMEM;
-+
-+      for (display_num = 0; display_num < num_displays; display_num++) {
-+              ret = vc4_fkms_create_screen(dev, drm, display_num,
-+                                           display_num_lookup[display_num],
-+                                           &crtc_list[display_num]);
-+              if (ret)
-+                      DRM_ERROR("Oh dear, failed to create display %u\n",
-+                                display_num);
-+      }
-+
-+      /* Map the SMI interrupt reg */
-+      crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
-+      if (IS_ERR(crtc_list[0]->regs))
-+              DRM_ERROR("Oh dear, failed to map registers\n");
-+
-+      writel(0, crtc_list[0]->regs + SMICS);
-+      ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-+                             vc4_crtc_irq_handler, 0, "vc4 firmware kms",
-+                             crtc_list);
-+      if (ret)
-+              DRM_ERROR("Oh dear, failed to register IRQ\n");
-+
-+      platform_set_drvdata(pdev, crtc_list);
-+
-+      return 0;
-+}
-+
- static void vc4_fkms_unbind(struct device *dev, struct device *master,
-                           void *data)
- {
-       struct platform_device *pdev = to_platform_device(dev);
--      struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev);
-+      struct vc4_crtc **crtc_list = dev_get_drvdata(dev);
-+      int i;
--      vc4_fkms_connector_destroy(vc4_crtc->connector);
--      vc4_fkms_encoder_destroy(vc4_crtc->encoder);
--      drm_crtc_cleanup(&vc4_crtc->base);
-+      for (i = 0; crtc_list[i]; i++) {
-+              vc4_fkms_connector_destroy(crtc_list[i]->connector);
-+              vc4_fkms_encoder_destroy(crtc_list[i]->encoder);
-+              drm_crtc_cleanup(&crtc_list[i]->base);
-+      }
-       platform_set_drvdata(pdev, NULL);
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0522-drm-vc4-Select-display-to-blank-during-initialisatio.patch b/target/linux/brcm2708/patches-4.19/950-0522-drm-vc4-Select-display-to-blank-during-initialisatio.patch
new file mode 100644 (file)
index 0000000..0391767
--- /dev/null
@@ -0,0 +1,54 @@
+From a267031f384a4433fdcd662a97bce7c4949d3fd6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 5 Apr 2019 17:23:15 +0100
+Subject: [PATCH] drm: vc4: Select display to blank during
+ initialisation
+
+Otherwise the rainbow splash screen remained in the display list
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -87,6 +87,13 @@ struct fb_alloc_tags {
+       u32 layer;
+ };
++struct mailbox_blank_display {
++      struct rpi_firmware_property_tag_header tag1;
++      u32 display;
++      struct rpi_firmware_property_tag_header tag2;
++      u32 blank;
++};
++
+ static const struct vc_image_format {
+       u32 drm;        /* DRM_FORMAT_* */
+       u32 vc_image;   /* VC_IMAGE_* */
+@@ -854,7 +861,12 @@ static int vc4_fkms_create_screen(struct
+       struct drm_crtc *crtc;
+       struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
+       struct drm_plane *destroy_plane, *temp;
+-      u32 blank = 1;
++      struct mailbox_blank_display blank = {
++              .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
++              .display = display_idx,
++              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_BLANK, 4, 0, },
++              .blank = 1,
++      };
+       int ret;
+       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+@@ -865,9 +877,7 @@ static int vc4_fkms_create_screen(struct
+       vc4_crtc->display_number = display_ref;
+       /* Blank the firmware provided framebuffer */
+-      rpi_firmware_property(vc4->firmware,
+-                            RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+-                            &blank, sizeof(blank));
++      rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
+       primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
+                                           display_ref,
diff --git a/target/linux/brcm2708/patches-4.19/950-0523-drm-vc4-Fix-build-warning.patch b/target/linux/brcm2708/patches-4.19/950-0523-drm-vc4-Fix-build-warning.patch
deleted file mode 100644 (file)
index 3e6273a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-From 52d2903959ff9a1d68701a04884e18b31d051f30 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 5 Apr 2019 17:21:56 +0100
-Subject: [PATCH] drm: vc4: Fix build warning
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -932,8 +932,6 @@ static int vc4_fkms_create_screen(struct
-       return 0;
--err_destroy_connector:
--      vc4_fkms_connector_destroy(vc4_crtc->connector);
- err_destroy_encoder:
-       vc4_fkms_encoder_destroy(vc4_crtc->encoder);
-       list_for_each_entry_safe(destroy_plane, temp,
diff --git a/target/linux/brcm2708/patches-4.19/950-0523-drm-vc4-Remove-now-unused-structure.patch b/target/linux/brcm2708/patches-4.19/950-0523-drm-vc4-Remove-now-unused-structure.patch
new file mode 100644 (file)
index 0000000..08c0995
--- /dev/null
@@ -0,0 +1,41 @@
+From 0bbbf4f4a618072e6987f439784f2d24a81b8f2d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 5 Apr 2019 17:24:20 +0100
+Subject: [PATCH] drm: vc4: Remove now unused structure.
+
+Cleaning up structure that was unused after
+fbb59a2 drm: vc4: Add an overlay plane to vc4-firmware-kms
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 19 -------------------
+ 1 file changed, 19 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -68,25 +68,6 @@ struct mailbox_set_plane {
+       struct set_plane plane;
+ };
+-struct fb_alloc_tags {
+-      struct rpi_firmware_property_tag_header tag1;
+-      u32 xres, yres;
+-      struct rpi_firmware_property_tag_header tag2;
+-      u32 xres_virtual, yres_virtual;
+-      struct rpi_firmware_property_tag_header tag3;
+-      u32 bpp;
+-      struct rpi_firmware_property_tag_header tag4;
+-      u32 xoffset, yoffset;
+-      struct rpi_firmware_property_tag_header tag5;
+-      u32 base, screen_size;
+-      struct rpi_firmware_property_tag_header tag6;
+-      u32 pitch;
+-      struct rpi_firmware_property_tag_header tag7;
+-      u32 alpha_mode;
+-      struct rpi_firmware_property_tag_header tag8;
+-      u32 layer;
+-};
+-
+ struct mailbox_blank_display {
+       struct rpi_firmware_property_tag_header tag1;
+       u32 display;
diff --git a/target/linux/brcm2708/patches-4.19/950-0524-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch b/target/linux/brcm2708/patches-4.19/950-0524-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch
new file mode 100644 (file)
index 0000000..1c34944
--- /dev/null
@@ -0,0 +1,58 @@
+From 13723c680a129d79a7872ee131c0201374ba62ce Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 12:37:28 +0100
+Subject: [PATCH] drm: vc4: Query the display ID for each display in
+ FKMS
+
+Replace the hard coded list of display IDs for a mailbox call
+that returns the display ID for each display that has been
+detected.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 16 +++++++++++++---
+ include/soc/bcm2835/raspberrypi-firmware.h |  1 +
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -943,7 +943,7 @@ static int vc4_fkms_bind(struct device *
+       struct vc4_crtc **crtc_list;
+       u32 num_displays, display_num;
+       int ret;
+-      const u32 display_num_lookup[] = {2, 7, 1};
++      u32 display_id;
+       vc4->firmware_kms = true;
+@@ -982,8 +982,18 @@ static int vc4_fkms_bind(struct device *
+               return -ENOMEM;
+       for (display_num = 0; display_num < num_displays; display_num++) {
+-              ret = vc4_fkms_create_screen(dev, drm, display_num,
+-                                           display_num_lookup[display_num],
++              display_id = display_num;
++              ret = rpi_firmware_property(vc4->firmware,
++                                          RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
++                                          &display_id, sizeof(display_id));
++              /* FIXME: Determine the correct error handling here.
++               * Should we fail to create the one "screen" but keep the
++               * others, or fail the whole thing?
++               */
++              if (ret)
++                      DRM_ERROR("Failed to get display id %u\n", display_num);
++
++              ret = vc4_fkms_create_screen(dev, drm, display_num, display_id,
+                                            &crtc_list[display_num]);
+               if (ret)
+                       DRM_ERROR("Oh dear, failed to create display %u\n",
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -117,6 +117,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF =               0x0004000f,
+       RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF =            0x00040010,
+       RPI_FIRMWARE_FRAMEBUFFER_RELEASE =                    0x00048001,
++      RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID =             0x00040016,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM =            0x00048013,
+       RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS =           0x00040013,
+       RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS =       0x00040014,
diff --git a/target/linux/brcm2708/patches-4.19/950-0524-drm-vc4-Select-display-to-blank-during-initialisatio.patch b/target/linux/brcm2708/patches-4.19/950-0524-drm-vc4-Select-display-to-blank-during-initialisatio.patch
deleted file mode 100644 (file)
index 0391767..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From a267031f384a4433fdcd662a97bce7c4949d3fd6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 5 Apr 2019 17:23:15 +0100
-Subject: [PATCH] drm: vc4: Select display to blank during
- initialisation
-
-Otherwise the rainbow splash screen remained in the display list
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 18 ++++++++++++++----
- 1 file changed, 14 insertions(+), 4 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -87,6 +87,13 @@ struct fb_alloc_tags {
-       u32 layer;
- };
-+struct mailbox_blank_display {
-+      struct rpi_firmware_property_tag_header tag1;
-+      u32 display;
-+      struct rpi_firmware_property_tag_header tag2;
-+      u32 blank;
-+};
-+
- static const struct vc_image_format {
-       u32 drm;        /* DRM_FORMAT_* */
-       u32 vc_image;   /* VC_IMAGE_* */
-@@ -854,7 +861,12 @@ static int vc4_fkms_create_screen(struct
-       struct drm_crtc *crtc;
-       struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
-       struct drm_plane *destroy_plane, *temp;
--      u32 blank = 1;
-+      struct mailbox_blank_display blank = {
-+              .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
-+              .display = display_idx,
-+              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_BLANK, 4, 0, },
-+              .blank = 1,
-+      };
-       int ret;
-       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
-@@ -865,9 +877,7 @@ static int vc4_fkms_create_screen(struct
-       vc4_crtc->display_number = display_ref;
-       /* Blank the firmware provided framebuffer */
--      rpi_firmware_property(vc4->firmware,
--                            RPI_FIRMWARE_FRAMEBUFFER_BLANK,
--                            &blank, sizeof(blank));
-+      rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
-       primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
-                                           display_ref,
diff --git a/target/linux/brcm2708/patches-4.19/950-0525-drm-vc4-Remove-now-unused-structure.patch b/target/linux/brcm2708/patches-4.19/950-0525-drm-vc4-Remove-now-unused-structure.patch
deleted file mode 100644 (file)
index 08c0995..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From 0bbbf4f4a618072e6987f439784f2d24a81b8f2d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 5 Apr 2019 17:24:20 +0100
-Subject: [PATCH] drm: vc4: Remove now unused structure.
-
-Cleaning up structure that was unused after
-fbb59a2 drm: vc4: Add an overlay plane to vc4-firmware-kms
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 19 -------------------
- 1 file changed, 19 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -68,25 +68,6 @@ struct mailbox_set_plane {
-       struct set_plane plane;
- };
--struct fb_alloc_tags {
--      struct rpi_firmware_property_tag_header tag1;
--      u32 xres, yres;
--      struct rpi_firmware_property_tag_header tag2;
--      u32 xres_virtual, yres_virtual;
--      struct rpi_firmware_property_tag_header tag3;
--      u32 bpp;
--      struct rpi_firmware_property_tag_header tag4;
--      u32 xoffset, yoffset;
--      struct rpi_firmware_property_tag_header tag5;
--      u32 base, screen_size;
--      struct rpi_firmware_property_tag_header tag6;
--      u32 pitch;
--      struct rpi_firmware_property_tag_header tag7;
--      u32 alpha_mode;
--      struct rpi_firmware_property_tag_header tag8;
--      u32 layer;
--};
--
- struct mailbox_blank_display {
-       struct rpi_firmware_property_tag_header tag1;
-       u32 display;
diff --git a/target/linux/brcm2708/patches-4.19/950-0525-drm-vc4-Set-the-display-number-when-querying-the-dis.patch b/target/linux/brcm2708/patches-4.19/950-0525-drm-vc4-Set-the-display-number-when-querying-the-dis.patch
new file mode 100644 (file)
index 0000000..236caaf
--- /dev/null
@@ -0,0 +1,103 @@
+From 1b9eb8d557c692e5f1dd831b5e7134e6d07a4dd4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 14:00:07 +0100
+Subject: [PATCH] drm/vc4: Set the display number when querying the
+ display resolution
+
+Without this the two displays got set to the same resolution.
+(Requires a firmware bug fix to work).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 37 +++++++++++++++++++-------
+ 1 file changed, 27 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -75,6 +75,13 @@ struct mailbox_blank_display {
+       u32 blank;
+ };
++struct mailbox_get_width_height {
++      struct rpi_firmware_property_tag_header tag1;
++      u32 display;
++      struct rpi_firmware_property_tag_header tag2;
++      u32 wh[2];
++};
++
+ static const struct vc_image_format {
+       u32 drm;        /* DRM_FORMAT_* */
+       u32 vc_image;   /* VC_IMAGE_* */
+@@ -192,6 +199,7 @@ struct vc4_fkms_connector {
+        * hook.
+        */
+       struct drm_encoder *encoder;
++      u32 display_idx;
+ };
+ static inline struct vc4_fkms_connector *
+@@ -723,21 +731,27 @@ vc4_fkms_connector_detect(struct drm_con
+ static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
+ {
+       struct drm_device *dev = connector->dev;
++      struct vc4_fkms_connector *fkms_connector =
++              to_vc4_fkms_connector(connector);
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
+-      u32 wh[2] = {0, 0};
+-      int ret;
+       struct drm_display_mode *mode;
++      struct mailbox_get_width_height wh = {
++              .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
++              .display = fkms_connector->display_idx,
++              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
++                        8, 0, },
++      };
++      int ret;
++
++      ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
+-      ret = rpi_firmware_property(vc4->firmware,
+-                                  RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
+-                                  &wh, sizeof(wh));
+       if (ret) {
+               DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n",
+-                        ret, wh[0], wh[1]);
++                        ret, wh.wh[0], wh.wh[1]);
+               return 0;
+       }
+-      mode = drm_cvt_mode(dev, wh[0], wh[1], 60 /* vrefresh */,
++      mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
+                           0, 0, false);
+       drm_mode_probed_add(connector, mode);
+@@ -772,8 +786,9 @@ static const struct drm_connector_helper
+       .best_encoder = vc4_fkms_connector_best_encoder,
+ };
+-static struct drm_connector *vc4_fkms_connector_init(struct drm_device *dev,
+-                                                   struct drm_encoder *encoder)
++static struct drm_connector *
++vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
++                      u32 display_idx)
+ {
+       struct drm_connector *connector = NULL;
+       struct vc4_fkms_connector *fkms_connector;
+@@ -788,6 +803,7 @@ static struct drm_connector *vc4_fkms_co
+       connector = &fkms_connector->base;
+       fkms_connector->encoder = encoder;
++      fkms_connector->display_idx = display_idx;
+       drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+                          DRM_MODE_CONNECTOR_HDMIA);
+@@ -904,7 +920,8 @@ static int vc4_fkms_create_screen(struct
+       drm_encoder_helper_add(&vc4_encoder->base,
+                              &vc4_fkms_encoder_helper_funcs);
+-      vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base);
++      vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
++                                                    display_idx);
+       if (IS_ERR(vc4_crtc->connector)) {
+               ret = PTR_ERR(vc4_crtc->connector);
+               goto err_destroy_encoder;
diff --git a/target/linux/brcm2708/patches-4.19/950-0526-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch b/target/linux/brcm2708/patches-4.19/950-0526-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch
new file mode 100644 (file)
index 0000000..c9ce67f
--- /dev/null
@@ -0,0 +1,46 @@
+From fe2432615ecc3500cc265d6b84334950b9cbd4bf Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 18:14:44 +0100
+Subject: [PATCH] from
+ vc4_crtc_[en|dis]able
+
+vblank needs to be enabled and disabled by the driver to avoid the
+DRM framework complaining in the kernel log.
+
+vc4_fkms_disable_vblank needs to signal that we don't want vblank
+callbacks too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -562,6 +562,8 @@ static void vc4_crtc_mode_set_nofb(struc
+ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++      drm_crtc_vblank_off(crtc);
++
+       /* Always turn the planes off on CRTC disable. In DRM, planes
+        * are enabled/disabled through the update/disable hooks
+        * above, and the CRTC enable/disable independently controls
+@@ -577,6 +579,7 @@ static void vc4_crtc_disable(struct drm_
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++      drm_crtc_vblank_on(crtc);
+       /* Unblank the planes (if they're supposed to be displayed). */
+       if (crtc->primary->state->fb)
+@@ -673,6 +676,9 @@ static int vc4_fkms_enable_vblank(struct
+ static void vc4_fkms_disable_vblank(struct drm_crtc *crtc)
+ {
++      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++
++      vc4_crtc->vblank_enabled = false;
+ }
+ static const struct drm_crtc_funcs vc4_crtc_funcs = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0526-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch b/target/linux/brcm2708/patches-4.19/950-0526-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch
deleted file mode 100644 (file)
index 1c34944..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 13723c680a129d79a7872ee131c0201374ba62ce Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 12:37:28 +0100
-Subject: [PATCH] drm: vc4: Query the display ID for each display in
- FKMS
-
-Replace the hard coded list of display IDs for a mailbox call
-that returns the display ID for each display that has been
-detected.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 16 +++++++++++++---
- include/soc/bcm2835/raspberrypi-firmware.h |  1 +
- 2 files changed, 14 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -943,7 +943,7 @@ static int vc4_fkms_bind(struct device *
-       struct vc4_crtc **crtc_list;
-       u32 num_displays, display_num;
-       int ret;
--      const u32 display_num_lookup[] = {2, 7, 1};
-+      u32 display_id;
-       vc4->firmware_kms = true;
-@@ -982,8 +982,18 @@ static int vc4_fkms_bind(struct device *
-               return -ENOMEM;
-       for (display_num = 0; display_num < num_displays; display_num++) {
--              ret = vc4_fkms_create_screen(dev, drm, display_num,
--                                           display_num_lookup[display_num],
-+              display_id = display_num;
-+              ret = rpi_firmware_property(vc4->firmware,
-+                                          RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
-+                                          &display_id, sizeof(display_id));
-+              /* FIXME: Determine the correct error handling here.
-+               * Should we fail to create the one "screen" but keep the
-+               * others, or fail the whole thing?
-+               */
-+              if (ret)
-+                      DRM_ERROR("Failed to get display id %u\n", display_num);
-+
-+              ret = vc4_fkms_create_screen(dev, drm, display_num, display_id,
-                                            &crtc_list[display_num]);
-               if (ret)
-                       DRM_ERROR("Oh dear, failed to create display %u\n",
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -117,6 +117,7 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF =               0x0004000f,
-       RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF =            0x00040010,
-       RPI_FIRMWARE_FRAMEBUFFER_RELEASE =                    0x00048001,
-+      RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID =             0x00040016,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM =            0x00048013,
-       RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS =           0x00040013,
-       RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS =       0x00040014,
diff --git a/target/linux/brcm2708/patches-4.19/950-0527-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch b/target/linux/brcm2708/patches-4.19/950-0527-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch
new file mode 100644 (file)
index 0000000..c3f48ec
--- /dev/null
@@ -0,0 +1,86 @@
+From 129100bd38125bef5fe237ab867349dbe8b210ba Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 17:19:51 +0100
+Subject: [PATCH] drm: vc4: Add support for H & V flips on each plane
+ for FKMS
+
+They are near zero cost options for the HVS, therefore they
+may as well be implemented, and it allows us to invert the
+DSI display.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 36 ++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -61,8 +61,21 @@ struct set_plane {
+       u8 padding;
+       u32 planes[4];  /* DMA address of each plane */
++
++      u32 transform;
+ };
++/* Values for the transform field */
++#define TRANSFORM_NO_ROTATE   0
++#define TRANSFORM_ROTATE_180  BIT(1)
++#define TRANSFORM_FLIP_HRIZ   BIT(16)
++#define TRANSFORM_FLIP_VERT   BIT(17)
++
++#define SUPPORTED_ROTATIONS   (DRM_MODE_ROTATE_0 | \
++                               DRM_MODE_ROTATE_180 | \
++                               DRM_MODE_REFLECT_X | \
++                               DRM_MODE_REFLECT_Y)
++
+ struct mailbox_set_plane {
+       struct rpi_firmware_property_tag_header tag;
+       struct set_plane plane;
+@@ -274,6 +287,7 @@ static void vc4_plane_atomic_update(stru
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+       int num_planes = fb->format->num_planes;
+       struct drm_display_mode *mode = &state->crtc->mode;
++      unsigned int rotation = SUPPORTED_ROTATIONS;
+       mb->plane.vc_image_type = vc_fmt->vc_image;
+       mb->plane.width = fb->width;
+@@ -294,6 +308,24 @@ static void vc4_plane_atomic_update(stru
+       mb->plane.is_vu = vc_fmt->is_vu;
+       mb->plane.planes[0] = bo->paddr + fb->offsets[0];
++      rotation = drm_rotation_simplify(state->rotation, rotation);
++
++      switch (rotation) {
++      default:
++      case DRM_MODE_ROTATE_0:
++              mb->plane.transform = TRANSFORM_NO_ROTATE;
++              break;
++      case DRM_MODE_ROTATE_180:
++              mb->plane.transform = TRANSFORM_ROTATE_180;
++              break;
++      case DRM_MODE_REFLECT_X:
++              mb->plane.transform = TRANSFORM_FLIP_HRIZ;
++              break;
++      case DRM_MODE_REFLECT_Y:
++              mb->plane.transform = TRANSFORM_FLIP_VERT;
++              break;
++      }
++
+       /* FIXME: If the dest rect goes off screen then clip the src rect so we
+        * don't have off-screen pixels.
+        */
+@@ -514,9 +546,13 @@ static struct drm_plane *vc4_fkms_plane_
+                                      formats, num_formats, modifiers,
+                                      type, NULL);
++      /* FIXME: Do we need to be checking return values from all these calls?
++       */
+       drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
+       drm_plane_create_alpha_property(plane);
++      drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
++                                         SUPPORTED_ROTATIONS);
+       /*
+        * Default frame buffer setup is with FB on -127, and raspistill etc
diff --git a/target/linux/brcm2708/patches-4.19/950-0527-drm-vc4-Set-the-display-number-when-querying-the-dis.patch b/target/linux/brcm2708/patches-4.19/950-0527-drm-vc4-Set-the-display-number-when-querying-the-dis.patch
deleted file mode 100644 (file)
index 236caaf..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-From 1b9eb8d557c692e5f1dd831b5e7134e6d07a4dd4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 14:00:07 +0100
-Subject: [PATCH] drm/vc4: Set the display number when querying the
- display resolution
-
-Without this the two displays got set to the same resolution.
-(Requires a firmware bug fix to work).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 37 +++++++++++++++++++-------
- 1 file changed, 27 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -75,6 +75,13 @@ struct mailbox_blank_display {
-       u32 blank;
- };
-+struct mailbox_get_width_height {
-+      struct rpi_firmware_property_tag_header tag1;
-+      u32 display;
-+      struct rpi_firmware_property_tag_header tag2;
-+      u32 wh[2];
-+};
-+
- static const struct vc_image_format {
-       u32 drm;        /* DRM_FORMAT_* */
-       u32 vc_image;   /* VC_IMAGE_* */
-@@ -192,6 +199,7 @@ struct vc4_fkms_connector {
-        * hook.
-        */
-       struct drm_encoder *encoder;
-+      u32 display_idx;
- };
- static inline struct vc4_fkms_connector *
-@@ -723,21 +731,27 @@ vc4_fkms_connector_detect(struct drm_con
- static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
- {
-       struct drm_device *dev = connector->dev;
-+      struct vc4_fkms_connector *fkms_connector =
-+              to_vc4_fkms_connector(connector);
-       struct vc4_dev *vc4 = to_vc4_dev(dev);
--      u32 wh[2] = {0, 0};
--      int ret;
-       struct drm_display_mode *mode;
-+      struct mailbox_get_width_height wh = {
-+              .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
-+              .display = fkms_connector->display_idx,
-+              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
-+                        8, 0, },
-+      };
-+      int ret;
-+
-+      ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
--      ret = rpi_firmware_property(vc4->firmware,
--                                  RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
--                                  &wh, sizeof(wh));
-       if (ret) {
-               DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n",
--                        ret, wh[0], wh[1]);
-+                        ret, wh.wh[0], wh.wh[1]);
-               return 0;
-       }
--      mode = drm_cvt_mode(dev, wh[0], wh[1], 60 /* vrefresh */,
-+      mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
-                           0, 0, false);
-       drm_mode_probed_add(connector, mode);
-@@ -772,8 +786,9 @@ static const struct drm_connector_helper
-       .best_encoder = vc4_fkms_connector_best_encoder,
- };
--static struct drm_connector *vc4_fkms_connector_init(struct drm_device *dev,
--                                                   struct drm_encoder *encoder)
-+static struct drm_connector *
-+vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
-+                      u32 display_idx)
- {
-       struct drm_connector *connector = NULL;
-       struct vc4_fkms_connector *fkms_connector;
-@@ -788,6 +803,7 @@ static struct drm_connector *vc4_fkms_co
-       connector = &fkms_connector->base;
-       fkms_connector->encoder = encoder;
-+      fkms_connector->display_idx = display_idx;
-       drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-                          DRM_MODE_CONNECTOR_HDMIA);
-@@ -904,7 +920,8 @@ static int vc4_fkms_create_screen(struct
-       drm_encoder_helper_add(&vc4_encoder->base,
-                              &vc4_fkms_encoder_helper_funcs);
--      vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base);
-+      vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
-+                                                    display_idx);
-       if (IS_ERR(vc4_crtc->connector)) {
-               ret = PTR_ERR(vc4_crtc->connector);
-               goto err_destroy_encoder;
diff --git a/target/linux/brcm2708/patches-4.19/950-0528-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch b/target/linux/brcm2708/patches-4.19/950-0528-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch
deleted file mode 100644 (file)
index c9ce67f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From fe2432615ecc3500cc265d6b84334950b9cbd4bf Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 18:14:44 +0100
-Subject: [PATCH] from
- vc4_crtc_[en|dis]able
-
-vblank needs to be enabled and disabled by the driver to avoid the
-DRM framework complaining in the kernel log.
-
-vc4_fkms_disable_vblank needs to signal that we don't want vblank
-callbacks too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -562,6 +562,8 @@ static void vc4_crtc_mode_set_nofb(struc
- static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+      drm_crtc_vblank_off(crtc);
-+
-       /* Always turn the planes off on CRTC disable. In DRM, planes
-        * are enabled/disabled through the update/disable hooks
-        * above, and the CRTC enable/disable independently controls
-@@ -577,6 +579,7 @@ static void vc4_crtc_disable(struct drm_
- static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+      drm_crtc_vblank_on(crtc);
-       /* Unblank the planes (if they're supposed to be displayed). */
-       if (crtc->primary->state->fb)
-@@ -673,6 +676,9 @@ static int vc4_fkms_enable_vblank(struct
- static void vc4_fkms_disable_vblank(struct drm_crtc *crtc)
- {
-+      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+
-+      vc4_crtc->vblank_enabled = false;
- }
- static const struct drm_crtc_funcs vc4_crtc_funcs = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0528-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch b/target/linux/brcm2708/patches-4.19/950-0528-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch
new file mode 100644 (file)
index 0000000..4b6cb39
--- /dev/null
@@ -0,0 +1,56 @@
+From 6885af169f6eeb386f410e556029c6518c6b67b2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 10 Apr 2019 17:35:05 +0100
+Subject: [PATCH] drm: vc4: Remove unused vc4_fkms_cancel_page_flip
+ function
+
+"32a3dbe drm/vc4: Nuke preclose hook" removed vc4_cancel_page_flip,
+but vc4_fkms_cancel_page_flip was still be added to with the
+fkms driver, even though it was never called.
+Nuke it too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_drv.h          |  1 -
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 --------------------
+ 2 files changed, 21 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -724,7 +724,6 @@ extern const struct dma_fence_ops vc4_fe
+ /* vc4_firmware_kms.c */
+ extern struct platform_driver vc4_firmware_kms_driver;
+-void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
+ /* vc4_gem.c */
+ void vc4_gem_init(struct drm_device *dev);
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -739,26 +739,6 @@ static const struct drm_crtc_helper_func
+       .atomic_flush = vc4_crtc_atomic_flush,
+ };
+-/* Frees the page flip event when the DRM device is closed with the
+- * event still outstanding.
+- */
+-void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
+-{
+-      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+-      struct drm_device *dev = crtc->dev;
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&dev->event_lock, flags);
+-
+-      if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) {
+-              kfree(&vc4_crtc->event->base);
+-              drm_crtc_vblank_put(crtc);
+-              vc4_crtc->event = NULL;
+-      }
+-
+-      spin_unlock_irqrestore(&dev->event_lock, flags);
+-}
+-
+ static const struct of_device_id vc4_firmware_kms_dt_match[] = {
+       { .compatible = "raspberrypi,rpi-firmware-kms" },
+       {}
diff --git a/target/linux/brcm2708/patches-4.19/950-0529-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch b/target/linux/brcm2708/patches-4.19/950-0529-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch
deleted file mode 100644 (file)
index c3f48ec..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-From 129100bd38125bef5fe237ab867349dbe8b210ba Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 17:19:51 +0100
-Subject: [PATCH] drm: vc4: Add support for H & V flips on each plane
- for FKMS
-
-They are near zero cost options for the HVS, therefore they
-may as well be implemented, and it allows us to invert the
-DSI display.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 36 ++++++++++++++++++++++++++
- 1 file changed, 36 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -61,8 +61,21 @@ struct set_plane {
-       u8 padding;
-       u32 planes[4];  /* DMA address of each plane */
-+
-+      u32 transform;
- };
-+/* Values for the transform field */
-+#define TRANSFORM_NO_ROTATE   0
-+#define TRANSFORM_ROTATE_180  BIT(1)
-+#define TRANSFORM_FLIP_HRIZ   BIT(16)
-+#define TRANSFORM_FLIP_VERT   BIT(17)
-+
-+#define SUPPORTED_ROTATIONS   (DRM_MODE_ROTATE_0 | \
-+                               DRM_MODE_ROTATE_180 | \
-+                               DRM_MODE_REFLECT_X | \
-+                               DRM_MODE_REFLECT_Y)
-+
- struct mailbox_set_plane {
-       struct rpi_firmware_property_tag_header tag;
-       struct set_plane plane;
-@@ -274,6 +287,7 @@ static void vc4_plane_atomic_update(stru
-       struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
-       int num_planes = fb->format->num_planes;
-       struct drm_display_mode *mode = &state->crtc->mode;
-+      unsigned int rotation = SUPPORTED_ROTATIONS;
-       mb->plane.vc_image_type = vc_fmt->vc_image;
-       mb->plane.width = fb->width;
-@@ -294,6 +308,24 @@ static void vc4_plane_atomic_update(stru
-       mb->plane.is_vu = vc_fmt->is_vu;
-       mb->plane.planes[0] = bo->paddr + fb->offsets[0];
-+      rotation = drm_rotation_simplify(state->rotation, rotation);
-+
-+      switch (rotation) {
-+      default:
-+      case DRM_MODE_ROTATE_0:
-+              mb->plane.transform = TRANSFORM_NO_ROTATE;
-+              break;
-+      case DRM_MODE_ROTATE_180:
-+              mb->plane.transform = TRANSFORM_ROTATE_180;
-+              break;
-+      case DRM_MODE_REFLECT_X:
-+              mb->plane.transform = TRANSFORM_FLIP_HRIZ;
-+              break;
-+      case DRM_MODE_REFLECT_Y:
-+              mb->plane.transform = TRANSFORM_FLIP_VERT;
-+              break;
-+      }
-+
-       /* FIXME: If the dest rect goes off screen then clip the src rect so we
-        * don't have off-screen pixels.
-        */
-@@ -514,9 +546,13 @@ static struct drm_plane *vc4_fkms_plane_
-                                      formats, num_formats, modifiers,
-                                      type, NULL);
-+      /* FIXME: Do we need to be checking return values from all these calls?
-+       */
-       drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
-       drm_plane_create_alpha_property(plane);
-+      drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
-+                                         SUPPORTED_ROTATIONS);
-       /*
-        * Default frame buffer setup is with FB on -127, and raspistill etc
diff --git a/target/linux/brcm2708/patches-4.19/950-0529-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch b/target/linux/brcm2708/patches-4.19/950-0529-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch
new file mode 100644 (file)
index 0000000..ca1b777
--- /dev/null
@@ -0,0 +1,57 @@
+From 501dabdd480e2da1b3b1395b5ebf9d5306fec689 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 10 Apr 2019 17:42:37 +0100
+Subject: [PATCH] drm: vc4: Iterate over all planes in
+ vc4_crtc_[dis|en]able
+
+Fixes a FIXME where the overlay plane wouldn't be restored.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -598,6 +598,8 @@ static void vc4_crtc_mode_set_nofb(struc
+ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++      struct drm_plane *plane;
++
+       drm_crtc_vblank_off(crtc);
+       /* Always turn the planes off on CRTC disable. In DRM, planes
+@@ -607,23 +609,23 @@ static void vc4_crtc_disable(struct drm_
+        * give us a CRTC-level control for that.
+        */
+-      vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
+-      vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
+-
+-      /* FIXME: Disable overlay planes */
++      drm_atomic_crtc_for_each_plane(plane, crtc)
++              vc4_plane_atomic_disable(plane, plane->state);
+ }
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++      struct drm_plane *plane;
++
+       drm_crtc_vblank_on(crtc);
++
+       /* Unblank the planes (if they're supposed to be displayed). */
++      drm_atomic_crtc_for_each_plane(plane, crtc)
++              if (plane->state->fb)
++                      vc4_plane_set_blank(plane, plane->state->visible);
++}
+-      if (crtc->primary->state->fb)
+-              vc4_plane_set_blank(crtc->primary, false);
+-      if (crtc->cursor->state->fb)
+-              vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
+-      /* FIXME: Enable overlay planes */
+ }
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
diff --git a/target/linux/brcm2708/patches-4.19/950-0530-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch b/target/linux/brcm2708/patches-4.19/950-0530-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch
new file mode 100644 (file)
index 0000000..af29bda
--- /dev/null
@@ -0,0 +1,47 @@
+From d4df2766945e0410d1975434f34e647e7e13b992 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 10 Apr 2019 17:43:57 +0100
+Subject: [PATCH] drm: vc4: Bring fkms into line with kms in blocking
+ doublescan modes
+
+Implement vc4_crtc_mode_valid so that it blocks doublescan modes
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -625,7 +625,17 @@ static void vc4_crtc_enable(struct drm_c
+                       vc4_plane_set_blank(plane, plane->state->visible);
+ }
++static enum drm_mode_status
++vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
++{
++      /* Do not allow doublescan modes from user space */
++      if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
++              DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
++                            crtc->base.id);
++              return MODE_NO_DBLESCAN;
++      }
++      return MODE_OK;
+ }
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+@@ -735,10 +745,11 @@ static const struct drm_crtc_funcs vc4_c
+ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
+       .mode_set_nofb = vc4_crtc_mode_set_nofb,
+-      .atomic_disable = vc4_crtc_disable,
+-      .atomic_enable = vc4_crtc_enable,
++      .mode_valid = vc4_crtc_mode_valid,
+       .atomic_check = vc4_crtc_atomic_check,
+       .atomic_flush = vc4_crtc_atomic_flush,
++      .atomic_enable = vc4_crtc_enable,
++      .atomic_disable = vc4_crtc_disable,
+ };
+ static const struct of_device_id vc4_firmware_kms_dt_match[] = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0530-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch b/target/linux/brcm2708/patches-4.19/950-0530-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch
deleted file mode 100644 (file)
index 4b6cb39..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 6885af169f6eeb386f410e556029c6518c6b67b2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 10 Apr 2019 17:35:05 +0100
-Subject: [PATCH] drm: vc4: Remove unused vc4_fkms_cancel_page_flip
- function
-
-"32a3dbe drm/vc4: Nuke preclose hook" removed vc4_cancel_page_flip,
-but vc4_fkms_cancel_page_flip was still be added to with the
-fkms driver, even though it was never called.
-Nuke it too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_drv.h          |  1 -
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 --------------------
- 2 files changed, 21 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_drv.h
-+++ b/drivers/gpu/drm/vc4/vc4_drv.h
-@@ -724,7 +724,6 @@ extern const struct dma_fence_ops vc4_fe
- /* vc4_firmware_kms.c */
- extern struct platform_driver vc4_firmware_kms_driver;
--void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
- /* vc4_gem.c */
- void vc4_gem_init(struct drm_device *dev);
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -739,26 +739,6 @@ static const struct drm_crtc_helper_func
-       .atomic_flush = vc4_crtc_atomic_flush,
- };
--/* Frees the page flip event when the DRM device is closed with the
-- * event still outstanding.
-- */
--void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
--{
--      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
--      struct drm_device *dev = crtc->dev;
--      unsigned long flags;
--
--      spin_lock_irqsave(&dev->event_lock, flags);
--
--      if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) {
--              kfree(&vc4_crtc->event->base);
--              drm_crtc_vblank_put(crtc);
--              vc4_crtc->event = NULL;
--      }
--
--      spin_unlock_irqrestore(&dev->event_lock, flags);
--}
--
- static const struct of_device_id vc4_firmware_kms_dt_match[] = {
-       { .compatible = "raspberrypi,rpi-firmware-kms" },
-       {}
diff --git a/target/linux/brcm2708/patches-4.19/950-0531-drm-vc4-Increase-max_width-height-to-7680.patch b/target/linux/brcm2708/patches-4.19/950-0531-drm-vc4-Increase-max_width-height-to-7680.patch
new file mode 100644 (file)
index 0000000..f2c9747
--- /dev/null
@@ -0,0 +1,27 @@
+From b4ed0c4f55542b642f16ee6376b69968d6bafc3b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Apr 2019 18:45:00 +0100
+Subject: [PATCH] drm: vc4: Increase max_width/height to 7680.
+
+There are some limits still being investigated that stop
+us going up to 8192, but 7680 is sufficient for dual 4k
+displays.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
+               return ret;
+       }
+-      dev->mode_config.max_width = 4096;
+-      dev->mode_config.max_height = 4096;
++      dev->mode_config.max_width = 7680;
++      dev->mode_config.max_height = 7680;
+       dev->mode_config.funcs = &vc4_mode_funcs;
+       dev->mode_config.preferred_depth = 24;
+       dev->mode_config.async_page_flip = true;
diff --git a/target/linux/brcm2708/patches-4.19/950-0531-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch b/target/linux/brcm2708/patches-4.19/950-0531-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch
deleted file mode 100644 (file)
index ca1b777..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From 501dabdd480e2da1b3b1395b5ebf9d5306fec689 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 10 Apr 2019 17:42:37 +0100
-Subject: [PATCH] drm: vc4: Iterate over all planes in
- vc4_crtc_[dis|en]able
-
-Fixes a FIXME where the overlay plane wouldn't be restored.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 +++++++++++---------
- 1 file changed, 11 insertions(+), 9 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -598,6 +598,8 @@ static void vc4_crtc_mode_set_nofb(struc
- static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+      struct drm_plane *plane;
-+
-       drm_crtc_vblank_off(crtc);
-       /* Always turn the planes off on CRTC disable. In DRM, planes
-@@ -607,23 +609,23 @@ static void vc4_crtc_disable(struct drm_
-        * give us a CRTC-level control for that.
-        */
--      vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
--      vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
--
--      /* FIXME: Disable overlay planes */
-+      drm_atomic_crtc_for_each_plane(plane, crtc)
-+              vc4_plane_atomic_disable(plane, plane->state);
- }
- static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+      struct drm_plane *plane;
-+
-       drm_crtc_vblank_on(crtc);
-+
-       /* Unblank the planes (if they're supposed to be displayed). */
-+      drm_atomic_crtc_for_each_plane(plane, crtc)
-+              if (plane->state->fb)
-+                      vc4_plane_set_blank(plane, plane->state->visible);
-+}
--      if (crtc->primary->state->fb)
--              vc4_plane_set_blank(crtc->primary, false);
--      if (crtc->cursor->state->fb)
--              vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
--      /* FIXME: Enable overlay planes */
- }
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
diff --git a/target/linux/brcm2708/patches-4.19/950-0532-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch b/target/linux/brcm2708/patches-4.19/950-0532-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch
deleted file mode 100644 (file)
index af29bda..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From d4df2766945e0410d1975434f34e647e7e13b992 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 10 Apr 2019 17:43:57 +0100
-Subject: [PATCH] drm: vc4: Bring fkms into line with kms in blocking
- doublescan modes
-
-Implement vc4_crtc_mode_valid so that it blocks doublescan modes
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 +++++++++++++--
- 1 file changed, 13 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -625,7 +625,17 @@ static void vc4_crtc_enable(struct drm_c
-                       vc4_plane_set_blank(plane, plane->state->visible);
- }
-+static enum drm_mode_status
-+vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
-+{
-+      /* Do not allow doublescan modes from user space */
-+      if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
-+              DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
-+                            crtc->base.id);
-+              return MODE_NO_DBLESCAN;
-+      }
-+      return MODE_OK;
- }
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
-@@ -735,10 +745,11 @@ static const struct drm_crtc_funcs vc4_c
- static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
-       .mode_set_nofb = vc4_crtc_mode_set_nofb,
--      .atomic_disable = vc4_crtc_disable,
--      .atomic_enable = vc4_crtc_enable,
-+      .mode_valid = vc4_crtc_mode_valid,
-       .atomic_check = vc4_crtc_atomic_check,
-       .atomic_flush = vc4_crtc_atomic_flush,
-+      .atomic_enable = vc4_crtc_enable,
-+      .atomic_disable = vc4_crtc_disable,
- };
- static const struct of_device_id vc4_firmware_kms_dt_match[] = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0532-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch b/target/linux/brcm2708/patches-4.19/950-0532-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch
new file mode 100644 (file)
index 0000000..db83c12
--- /dev/null
@@ -0,0 +1,557 @@
+From 9536044338d9c341e805e288a58090c49a793638 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 18:23:41 +0100
+Subject: [PATCH] drm: vc4: FKMS reads the EDID from fw, and supports
+ mode setting
+
+This extends FKMS to read the EDID from the display, and support
+requesting a particular mode via KMS.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 334 ++++++++++++++++++---
+ include/soc/bcm2835/raspberrypi-firmware.h |   2 +
+ 2 files changed, 302 insertions(+), 34 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -88,11 +88,60 @@ struct mailbox_blank_display {
+       u32 blank;
+ };
+-struct mailbox_get_width_height {
++struct mailbox_get_edid {
+       struct rpi_firmware_property_tag_header tag1;
+-      u32 display;
+-      struct rpi_firmware_property_tag_header tag2;
+-      u32 wh[2];
++      u32 block;
++      u32 display_number;
++      u8 edid[128];
++};
++
++struct set_timings {
++      u8 display;
++      u8 padding;
++      u16 video_id_code;
++
++      u32 clock;              /* in kHz */
++
++      u16 hdisplay;
++      u16 hsync_start;
++
++      u16 hsync_end;
++      u16 htotal;
++
++      u16 hskew;
++      u16 vdisplay;
++
++      u16 vsync_start;
++      u16 vsync_end;
++
++      u16 vtotal;
++      u16 vscan;
++
++      u16 vrefresh;
++      u16 padding2;
++
++      u32 flags;
++#define  TIMINGS_FLAGS_H_SYNC_POS     BIT(0)
++#define  TIMINGS_FLAGS_H_SYNC_NEG     0
++#define  TIMINGS_FLAGS_V_SYNC_POS     BIT(1)
++#define  TIMINGS_FLAGS_V_SYNC_NEG     0
++
++#define TIMINGS_FLAGS_ASPECT_MASK     GENMASK(7, 4)
++#define TIMINGS_FLAGS_ASPECT_NONE     (0 << 4)
++#define TIMINGS_FLAGS_ASPECT_4_3      (1 << 4)
++#define TIMINGS_FLAGS_ASPECT_16_9     (2 << 4)
++#define TIMINGS_FLAGS_ASPECT_64_27    (3 << 4)
++#define TIMINGS_FLAGS_ASPECT_256_135  (4 << 4)
++
++/* Limited range RGB flag. Not set corresponds to full range. */
++#define TIMINGS_FLAGS_RGB_LIMITED     BIT(8)
++/* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */
++#define TIMINGS_FLAGS_DVI             BIT(9)
++};
++
++struct mailbox_set_mode {
++      struct rpi_firmware_property_tag_header tag1;
++      struct set_timings timings;
+ };
+ static const struct vc_image_format {
+@@ -186,6 +235,7 @@ struct vc4_crtc {
+       u32 overscan[4];
+       bool vblank_enabled;
+       u32 display_number;
++      u32 display_type;
+ };
+ static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
+@@ -195,6 +245,8 @@ static inline struct vc4_crtc *to_vc4_cr
+ struct vc4_fkms_encoder {
+       struct drm_encoder base;
++      bool hdmi_monitor;
++      bool rgb_range_selectable;
+ };
+ static inline struct vc4_fkms_encoder *
+@@ -212,7 +264,9 @@ struct vc4_fkms_connector {
+        * hook.
+        */
+       struct drm_encoder *encoder;
+-      u32 display_idx;
++      struct vc4_dev *vc4_dev;
++      u32 display_number;
++      u32 display_type;
+ };
+ static inline struct vc4_fkms_connector *
+@@ -221,6 +275,26 @@ to_vc4_fkms_connector(struct drm_connect
+       return container_of(connector, struct vc4_fkms_connector, base);
+ }
++static u32 vc4_get_display_type(u32 display_number)
++{
++      const u32 display_types[] = {
++              /* The firmware display (DispmanX) IDs map to specific types in
++               * a fixed manner.
++               */
++              DRM_MODE_ENCODER_DSI,   /* MAIN_LCD */
++              DRM_MODE_ENCODER_DSI,   /* AUX_LCD */
++              DRM_MODE_ENCODER_TMDS,  /* HDMI0 */
++              DRM_MODE_ENCODER_TVDAC, /* VEC */
++              DRM_MODE_ENCODER_NONE,  /* FORCE_LCD */
++              DRM_MODE_ENCODER_NONE,  /* FORCE_TV */
++              DRM_MODE_ENCODER_NONE,  /* FORCE_OTHER */
++              DRM_MODE_ENCODER_TMDS,  /* HDMI1 */
++              DRM_MODE_ENCODER_NONE,  /* FORCE_TV2 */
++      };
++      return display_number > ARRAY_SIZE(display_types) - 1 ?
++                      DRM_MODE_ENCODER_NONE : display_types[display_number];
++}
++
+ /* Firmware's structure for making an FB mbox call. */
+ struct fbinfo_s {
+       u32 xres, yres, xres_virtual, yres_virtual;
+@@ -255,10 +329,15 @@ static int vc4_plane_set_blank(struct dr
+                       .plane_id = vc4_plane->mb.plane.plane_id,
+               }
+       };
++      static const char * const plane_types[] = {
++                                                      "overlay",
++                                                      "primary",
++                                                      "cursor"
++                                                };
+       int ret;
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
+-                       plane->base.id, plane->name,
++      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s",
++                       plane->base.id, plane->name, plane_types[plane->type],
+                        blank ? "blank" : "unblank");
+       if (blank)
+@@ -593,13 +672,102 @@ fail:
+ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
+ {
+-      /* Everyting is handled in the planes. */
++      struct drm_device *dev = crtc->dev;
++      struct vc4_dev *vc4 = to_vc4_dev(dev);
++      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++      struct drm_display_mode *mode = &crtc->state->adjusted_mode;
++      struct vc4_fkms_encoder *vc4_encoder =
++                                      to_vc4_fkms_encoder(vc4_crtc->encoder);
++      struct mailbox_set_mode mb = {
++              .tag1 = { RPI_FIRMWARE_SET_TIMING,
++                        sizeof(struct set_timings), 0},
++      };
++      union hdmi_infoframe frame;
++      int ret;
++
++      ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
++      if (ret < 0) {
++              DRM_ERROR("couldn't fill AVI infoframe\n");
++              return;
++      }
++
++      DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
++                    vc4_crtc->display_number, mode->name, mode->clock,
++                    mode->hdisplay, mode->hsync_start, mode->hsync_end,
++                    mode->htotal, mode->hskew, mode->vdisplay,
++                    mode->vsync_start, mode->vsync_end, mode->vtotal,
++                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
++      mb.timings.display = vc4_crtc->display_number;
++
++      mb.timings.video_id_code = frame.avi.video_code;
++
++      mb.timings.clock = mode->clock;
++      mb.timings.hdisplay = mode->hdisplay;
++      mb.timings.hsync_start = mode->hsync_start;
++      mb.timings.hsync_end = mode->hsync_end;
++      mb.timings.htotal = mode->htotal;
++      mb.timings.hskew = mode->hskew;
++      mb.timings.vdisplay = mode->vdisplay;
++      mb.timings.vsync_start = mode->vsync_start;
++      mb.timings.vsync_end = mode->vsync_end;
++      mb.timings.vtotal = mode->vtotal;
++      mb.timings.vscan = mode->vscan;
++      mb.timings.vrefresh = 0;
++      mb.timings.flags = 0;
++      if (mode->flags & DRM_MODE_FLAG_PHSYNC)
++              mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
++      if (mode->flags & DRM_MODE_FLAG_PVSYNC)
++              mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS;
++
++      switch (frame.avi.picture_aspect) {
++      default:
++      case HDMI_PICTURE_ASPECT_NONE:
++              mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
++              break;
++      case HDMI_PICTURE_ASPECT_4_3:
++              mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
++              break;
++      case HDMI_PICTURE_ASPECT_16_9:
++              mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
++              break;
++      case HDMI_PICTURE_ASPECT_64_27:
++              mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
++              break;
++      case HDMI_PICTURE_ASPECT_256_135:
++              mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
++              break;
++      }
++
++      if (!vc4_encoder->hdmi_monitor)
++              mb.timings.flags |= TIMINGS_FLAGS_DVI;
++      else if (drm_default_rgb_quant_range(mode) ==
++                                      HDMI_QUANTIZATION_RANGE_LIMITED)
++              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++
++      /*
++      FIXME: To implement
++      switch(mode->flag & DRM_MODE_FLAG_3D_MASK) {
++      case DRM_MODE_FLAG_3D_NONE:
++      case DRM_MODE_FLAG_3D_FRAME_PACKING:
++      case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
++      case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
++      case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
++      case DRM_MODE_FLAG_3D_L_DEPTH:
++      case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
++      case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
++      case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
++      }
++      */
++
++      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
+ }
+ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
+       struct drm_plane *plane;
++      DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
++                    crtc->base.id);
+       drm_crtc_vblank_off(crtc);
+       /* Always turn the planes off on CRTC disable. In DRM, planes
+@@ -617,6 +785,8 @@ static void vc4_crtc_enable(struct drm_c
+ {
+       struct drm_plane *plane;
++      DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
++                    crtc->base.id);
+       drm_crtc_vblank_on(crtc);
+       /* Unblank the planes (if they're supposed to be displayed). */
+@@ -635,12 +805,20 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+               return MODE_NO_DBLESCAN;
+       }
++      /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
++       * working.
++       */
++      if (mode->clock > 340000)
++              return MODE_CLOCK_HIGH;
++
+       return MODE_OK;
+ }
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+                                struct drm_crtc_state *state)
+ {
++      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
++                    crtc->base.id);
+       return 0;
+ }
+@@ -650,6 +828,8 @@ static void vc4_crtc_atomic_flush(struct
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
++      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
++                    crtc->base.id);
+       if (crtc->state->event) {
+               unsigned long flags;
+@@ -717,6 +897,8 @@ static int vc4_fkms_enable_vblank(struct
+ {
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++      DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n",
++                    crtc->base.id);
+       vc4_crtc->vblank_enabled = true;
+       return 0;
+@@ -726,6 +908,8 @@ static void vc4_fkms_disable_vblank(stru
+ {
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++      DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n",
++                    crtc->base.id);
+       vc4_crtc->vblank_enabled = false;
+ }
+@@ -760,36 +944,92 @@ static const struct of_device_id vc4_fir
+ static enum drm_connector_status
+ vc4_fkms_connector_detect(struct drm_connector *connector, bool force)
+ {
++      DRM_DEBUG_KMS("connector detect.\n");
+       return connector_status_connected;
+ }
+-static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
++static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
++                                 size_t len)
+ {
+-      struct drm_device *dev = connector->dev;
+       struct vc4_fkms_connector *fkms_connector =
+-              to_vc4_fkms_connector(connector);
+-      struct vc4_dev *vc4 = to_vc4_dev(dev);
+-      struct drm_display_mode *mode;
+-      struct mailbox_get_width_height wh = {
+-              .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
+-              .display = fkms_connector->display_idx,
+-              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
+-                        8, 0, },
++                                      (struct vc4_fkms_connector *)data;
++      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
++      struct mailbox_get_edid mb = {
++              .tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY,
++                        128 + 8, 0 },
++              .block = block,
++              .display_number = fkms_connector->display_number,
+       };
+-      int ret;
++      int ret = 0;
++
++      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
++
++      if (!ret)
++              memcpy(buf, mb.edid, len);
++
++      return ret;
++}
++
++static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
++{
++      struct vc4_fkms_connector *fkms_connector =
++                                      to_vc4_fkms_connector(connector);
++      struct drm_encoder *encoder = fkms_connector->encoder;
++      struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
++      int ret = 0;
++      struct edid *edid;
++
++      edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
++                             fkms_connector);
++
++      /* FIXME: Can we do CEC?
++       * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
++       * if (!edid)
++       *      return -ENODEV;
++       */
++
++      vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
+-      ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
++      if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
++              vc4_encoder->rgb_range_selectable =
++                      drm_rgb_quant_range_selectable(edid);
++      }
++
++      drm_connector_update_edid_property(connector, edid);
++      ret = drm_add_edid_modes(connector, edid);
++      kfree(edid);
++
++      return ret;
++}
++
++/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
++static const struct drm_display_mode lcd_mode = {
++      DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
++               25979400 / 1000,
++               800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
++               480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
++               DRM_MODE_FLAG_INTERLACE)
++};
++
++static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
++{
++      //struct vc4_fkms_connector *fkms_connector =
++      //                              to_vc4_fkms_connector(connector);
++      //struct drm_encoder *encoder = fkms_connector->encoder;
++      //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
++      struct drm_display_mode *mode;
++      //int ret = 0;
+-      if (ret) {
+-              DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n",
+-                        ret, wh.wh[0], wh.wh[1]);
+-              return 0;
++      mode = drm_mode_duplicate(connector->dev,
++                                &lcd_mode);
++      if (!mode) {
++              DRM_ERROR("Failed to create a new display mode\n");
++              return -ENOMEM;
+       }
+-      mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
+-                          0, 0, false);
+       drm_mode_probed_add(connector, mode);
++      /* We have one mode */
+       return 1;
+ }
+@@ -798,11 +1038,14 @@ vc4_fkms_connector_best_encoder(struct d
+ {
+       struct vc4_fkms_connector *fkms_connector =
+               to_vc4_fkms_connector(connector);
++      DRM_DEBUG_KMS("best_connector.\n");
+       return fkms_connector->encoder;
+ }
+ static void vc4_fkms_connector_destroy(struct drm_connector *connector)
+ {
++      DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n",
++                    connector->base.id);
+       drm_connector_unregister(connector);
+       drm_connector_cleanup(connector);
+ }
+@@ -821,14 +1064,22 @@ static const struct drm_connector_helper
+       .best_encoder = vc4_fkms_connector_best_encoder,
+ };
++static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = {
++      .get_modes = vc4_fkms_lcd_connector_get_modes,
++      .best_encoder = vc4_fkms_connector_best_encoder,
++};
++
+ static struct drm_connector *
+ vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
+-                      u32 display_idx)
++                      u32 display_num)
+ {
+       struct drm_connector *connector = NULL;
+       struct vc4_fkms_connector *fkms_connector;
++      struct vc4_dev *vc4_dev = to_vc4_dev(dev);
+       int ret = 0;
++      DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num);
++
+       fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
+                                     GFP_KERNEL);
+       if (!fkms_connector) {
+@@ -838,11 +1089,21 @@ vc4_fkms_connector_init(struct drm_devic
+       connector = &fkms_connector->base;
+       fkms_connector->encoder = encoder;
+-      fkms_connector->display_idx = display_idx;
+-
+-      drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+-                         DRM_MODE_CONNECTOR_HDMIA);
+-      drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs);
++      fkms_connector->display_number = display_num;
++      fkms_connector->display_type = vc4_get_display_type(display_num);
++      fkms_connector->vc4_dev = vc4_dev;
++
++      if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
++              drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
++                                 DRM_MODE_CONNECTOR_DSI);
++              drm_connector_helper_add(connector,
++                                       &vc4_fkms_lcd_conn_helper_funcs);
++      } else {
++              drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
++                                 DRM_MODE_CONNECTOR_HDMIA);
++              drm_connector_helper_add(connector,
++                                       &vc4_fkms_connector_helper_funcs);
++      }
+       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+                            DRM_CONNECTOR_POLL_DISCONNECT);
+@@ -863,6 +1124,7 @@ vc4_fkms_connector_init(struct drm_devic
+ static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder)
+ {
++      DRM_DEBUG_KMS("Encoder_destroy\n");
+       drm_encoder_cleanup(encoder);
+ }
+@@ -872,10 +1134,12 @@ static const struct drm_encoder_funcs vc
+ static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
+ {
++      DRM_DEBUG_KMS("Encoder_enable\n");
+ }
+ static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
+ {
++      DRM_DEBUG_KMS("Encoder_disable\n");
+ }
+ static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = {
+@@ -907,6 +1171,7 @@ static int vc4_fkms_create_screen(struct
+       crtc = &vc4_crtc->base;
+       vc4_crtc->display_number = display_ref;
++      vc4_crtc->display_type = vc4_get_display_type(display_ref);
+       /* Blank the firmware provided framebuffer */
+       rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
+@@ -950,13 +1215,14 @@ static int vc4_fkms_create_screen(struct
+               return -ENOMEM;
+       vc4_crtc->encoder = &vc4_encoder->base;
+       vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ;
++
+       drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs,
+-                       DRM_MODE_ENCODER_TMDS, NULL);
++                       vc4_crtc->display_type, NULL);
+       drm_encoder_helper_add(&vc4_encoder->base,
+                              &vc4_fkms_encoder_helper_funcs);
+       vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
+-                                                    display_idx);
++                                                    display_ref);
+       if (IS_ERR(vc4_crtc->connector)) {
+               ret = PTR_ERR(vc4_crtc->connector);
+               goto err_destroy_encoder;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -78,6 +78,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE =       0x00030014,
+       RPI_FIRMWARE_GET_EDID_BLOCK =                         0x00030020,
+       RPI_FIRMWARE_GET_CUSTOMER_OTP =                       0x00030021,
++      RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY =                 0x00030023,
+       RPI_FIRMWARE_GET_DOMAIN_STATE =                       0x00030030,
+       RPI_FIRMWARE_GET_THROTTLED =                          0x00030046,
+       RPI_FIRMWARE_GET_CLOCK_MEASURED =                     0x00030047,
+@@ -150,6 +151,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
+       RPI_FIRMWARE_SET_PLANE =                              0x00048015,
++      RPI_FIRMWARE_SET_TIMING =                             0x00048017,
+       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
+       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
diff --git a/target/linux/brcm2708/patches-4.19/950-0533-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch b/target/linux/brcm2708/patches-4.19/950-0533-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch
new file mode 100644 (file)
index 0000000..ca70b9d
--- /dev/null
@@ -0,0 +1,53 @@
+From bf85b92a97a95161d98874571c520fb1395c5aa2 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 15:11:05 -0700
+Subject: [PATCH] clk: bcm2835: Add support for setting leaf clock
+ rates while running.
+
+As long as you wait for !BUSY, you can do glitch-free updates of clock
+rate while the clock is running.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1097,15 +1097,19 @@ static int bcm2835_clock_set_rate(struct
+       spin_lock(&cprman->regs_lock);
+-      /*
+-       * Setting up frac support
+-       *
+-       * In principle it is recommended to stop/start the clock first,
+-       * but as we set CLK_SET_RATE_GATE during registration of the
+-       * clock this requirement should be take care of by the
+-       * clk-framework.
++      ctl = cprman_read(cprman, data->ctl_reg);
++
++      /* If the clock is running, we have to pause clock generation while
++       * updating the control and div regs.  This is glitchless (no clock
++       * signals generated faster than the rate) but each reg access is two
++       * OSC cycles so the clock will slow down for a moment.
+        */
+-      ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
++      if (ctl & CM_ENABLE) {
++              cprman_write(cprman, data->ctl_reg, ctl & ~CM_ENABLE);
++              bcm2835_clock_wait_busy(clock);
++      }
++
++      ctl &= ~CM_FRAC;
+       ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
+       cprman_write(cprman, data->ctl_reg, ctl);
+@@ -1475,7 +1479,7 @@ static struct clk_hw *bcm2835_register_c
+               init.ops = &bcm2835_vpu_clock_clk_ops;
+       } else {
+               init.ops = &bcm2835_clock_clk_ops;
+-              init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
++              init.flags |= CLK_SET_PARENT_GATE;
+               /* If the clock wasn't actually enabled at boot, it's not
+                * critical.
diff --git a/target/linux/brcm2708/patches-4.19/950-0533-drm-vc4-Increase-max_width-height-to-7680.patch b/target/linux/brcm2708/patches-4.19/950-0533-drm-vc4-Increase-max_width-height-to-7680.patch
deleted file mode 100644 (file)
index f2c9747..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From b4ed0c4f55542b642f16ee6376b69968d6bafc3b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Apr 2019 18:45:00 +0100
-Subject: [PATCH] drm: vc4: Increase max_width/height to 7680.
-
-There are some limits still being investigated that stop
-us going up to 8192, but 7680 is sufficient for dual 4k
-displays.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
-               return ret;
-       }
--      dev->mode_config.max_width = 4096;
--      dev->mode_config.max_height = 4096;
-+      dev->mode_config.max_width = 7680;
-+      dev->mode_config.max_height = 7680;
-       dev->mode_config.funcs = &vc4_mode_funcs;
-       dev->mode_config.preferred_depth = 24;
-       dev->mode_config.async_page_flip = true;
diff --git a/target/linux/brcm2708/patches-4.19/950-0534-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch b/target/linux/brcm2708/patches-4.19/950-0534-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch
new file mode 100644 (file)
index 0000000..490466d
--- /dev/null
@@ -0,0 +1,71 @@
+From d46285327ba5961c992643d468b2862c70f4c7e5 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 15:24:04 -0700
+Subject: [PATCH] clk: bcm2835: Allow reparenting leaf clocks while
+ they're running.
+
+This falls under the same "we can reprogram glitch-free as long as we
+pause generation" rule as updating the div/frac fields.  This can be
+used for runtime reclocking of V3D to manage power leakage.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1086,8 +1086,10 @@ static int bcm2835_clock_on(struct clk_h
+       return 0;
+ }
+-static int bcm2835_clock_set_rate(struct clk_hw *hw,
+-                                unsigned long rate, unsigned long parent_rate)
++static int bcm2835_clock_set_rate_and_parent(struct clk_hw *hw,
++                                           unsigned long rate,
++                                           unsigned long parent_rate,
++                                           u8 parent)
+ {
+       struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+       struct bcm2835_cprman *cprman = clock->cprman;
+@@ -1109,6 +1111,11 @@ static int bcm2835_clock_set_rate(struct
+               bcm2835_clock_wait_busy(clock);
+       }
++      if (parent != 0xff) {
++              ctl &= ~(CM_SRC_MASK << CM_SRC_SHIFT);
++              ctl |= parent << CM_SRC_SHIFT;
++      }
++
+       ctl &= ~CM_FRAC;
+       ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
+       cprman_write(cprman, data->ctl_reg, ctl);
+@@ -1120,6 +1127,12 @@ static int bcm2835_clock_set_rate(struct
+       return 0;
+ }
++static int bcm2835_clock_set_rate(struct clk_hw *hw,
++                                unsigned long rate, unsigned long parent_rate)
++{
++      return bcm2835_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff);
++}
++
+ static bool
+ bcm2835_clk_is_pllc(struct clk_hw *hw)
+ {
+@@ -1303,6 +1316,7 @@ static const struct clk_ops bcm2835_cloc
+       .unprepare = bcm2835_clock_off,
+       .recalc_rate = bcm2835_clock_get_rate,
+       .set_rate = bcm2835_clock_set_rate,
++      .set_rate_and_parent = bcm2835_clock_set_rate_and_parent,
+       .determine_rate = bcm2835_clock_determine_rate,
+       .set_parent = bcm2835_clock_set_parent,
+       .get_parent = bcm2835_clock_get_parent,
+@@ -1479,7 +1493,6 @@ static struct clk_hw *bcm2835_register_c
+               init.ops = &bcm2835_vpu_clock_clk_ops;
+       } else {
+               init.ops = &bcm2835_clock_clk_ops;
+-              init.flags |= CLK_SET_PARENT_GATE;
+               /* If the clock wasn't actually enabled at boot, it's not
+                * critical.
diff --git a/target/linux/brcm2708/patches-4.19/950-0534-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch b/target/linux/brcm2708/patches-4.19/950-0534-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch
deleted file mode 100644 (file)
index db83c12..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-From 9536044338d9c341e805e288a58090c49a793638 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 18:23:41 +0100
-Subject: [PATCH] drm: vc4: FKMS reads the EDID from fw, and supports
- mode setting
-
-This extends FKMS to read the EDID from the display, and support
-requesting a particular mode via KMS.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 334 ++++++++++++++++++---
- include/soc/bcm2835/raspberrypi-firmware.h |   2 +
- 2 files changed, 302 insertions(+), 34 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -88,11 +88,60 @@ struct mailbox_blank_display {
-       u32 blank;
- };
--struct mailbox_get_width_height {
-+struct mailbox_get_edid {
-       struct rpi_firmware_property_tag_header tag1;
--      u32 display;
--      struct rpi_firmware_property_tag_header tag2;
--      u32 wh[2];
-+      u32 block;
-+      u32 display_number;
-+      u8 edid[128];
-+};
-+
-+struct set_timings {
-+      u8 display;
-+      u8 padding;
-+      u16 video_id_code;
-+
-+      u32 clock;              /* in kHz */
-+
-+      u16 hdisplay;
-+      u16 hsync_start;
-+
-+      u16 hsync_end;
-+      u16 htotal;
-+
-+      u16 hskew;
-+      u16 vdisplay;
-+
-+      u16 vsync_start;
-+      u16 vsync_end;
-+
-+      u16 vtotal;
-+      u16 vscan;
-+
-+      u16 vrefresh;
-+      u16 padding2;
-+
-+      u32 flags;
-+#define  TIMINGS_FLAGS_H_SYNC_POS     BIT(0)
-+#define  TIMINGS_FLAGS_H_SYNC_NEG     0
-+#define  TIMINGS_FLAGS_V_SYNC_POS     BIT(1)
-+#define  TIMINGS_FLAGS_V_SYNC_NEG     0
-+
-+#define TIMINGS_FLAGS_ASPECT_MASK     GENMASK(7, 4)
-+#define TIMINGS_FLAGS_ASPECT_NONE     (0 << 4)
-+#define TIMINGS_FLAGS_ASPECT_4_3      (1 << 4)
-+#define TIMINGS_FLAGS_ASPECT_16_9     (2 << 4)
-+#define TIMINGS_FLAGS_ASPECT_64_27    (3 << 4)
-+#define TIMINGS_FLAGS_ASPECT_256_135  (4 << 4)
-+
-+/* Limited range RGB flag. Not set corresponds to full range. */
-+#define TIMINGS_FLAGS_RGB_LIMITED     BIT(8)
-+/* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */
-+#define TIMINGS_FLAGS_DVI             BIT(9)
-+};
-+
-+struct mailbox_set_mode {
-+      struct rpi_firmware_property_tag_header tag1;
-+      struct set_timings timings;
- };
- static const struct vc_image_format {
-@@ -186,6 +235,7 @@ struct vc4_crtc {
-       u32 overscan[4];
-       bool vblank_enabled;
-       u32 display_number;
-+      u32 display_type;
- };
- static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
-@@ -195,6 +245,8 @@ static inline struct vc4_crtc *to_vc4_cr
- struct vc4_fkms_encoder {
-       struct drm_encoder base;
-+      bool hdmi_monitor;
-+      bool rgb_range_selectable;
- };
- static inline struct vc4_fkms_encoder *
-@@ -212,7 +264,9 @@ struct vc4_fkms_connector {
-        * hook.
-        */
-       struct drm_encoder *encoder;
--      u32 display_idx;
-+      struct vc4_dev *vc4_dev;
-+      u32 display_number;
-+      u32 display_type;
- };
- static inline struct vc4_fkms_connector *
-@@ -221,6 +275,26 @@ to_vc4_fkms_connector(struct drm_connect
-       return container_of(connector, struct vc4_fkms_connector, base);
- }
-+static u32 vc4_get_display_type(u32 display_number)
-+{
-+      const u32 display_types[] = {
-+              /* The firmware display (DispmanX) IDs map to specific types in
-+               * a fixed manner.
-+               */
-+              DRM_MODE_ENCODER_DSI,   /* MAIN_LCD */
-+              DRM_MODE_ENCODER_DSI,   /* AUX_LCD */
-+              DRM_MODE_ENCODER_TMDS,  /* HDMI0 */
-+              DRM_MODE_ENCODER_TVDAC, /* VEC */
-+              DRM_MODE_ENCODER_NONE,  /* FORCE_LCD */
-+              DRM_MODE_ENCODER_NONE,  /* FORCE_TV */
-+              DRM_MODE_ENCODER_NONE,  /* FORCE_OTHER */
-+              DRM_MODE_ENCODER_TMDS,  /* HDMI1 */
-+              DRM_MODE_ENCODER_NONE,  /* FORCE_TV2 */
-+      };
-+      return display_number > ARRAY_SIZE(display_types) - 1 ?
-+                      DRM_MODE_ENCODER_NONE : display_types[display_number];
-+}
-+
- /* Firmware's structure for making an FB mbox call. */
- struct fbinfo_s {
-       u32 xres, yres, xres_virtual, yres_virtual;
-@@ -255,10 +329,15 @@ static int vc4_plane_set_blank(struct dr
-                       .plane_id = vc4_plane->mb.plane.plane_id,
-               }
-       };
-+      static const char * const plane_types[] = {
-+                                                      "overlay",
-+                                                      "primary",
-+                                                      "cursor"
-+                                                };
-       int ret;
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
--                       plane->base.id, plane->name,
-+      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s",
-+                       plane->base.id, plane->name, plane_types[plane->type],
-                        blank ? "blank" : "unblank");
-       if (blank)
-@@ -593,13 +672,102 @@ fail:
- static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
- {
--      /* Everyting is handled in the planes. */
-+      struct drm_device *dev = crtc->dev;
-+      struct vc4_dev *vc4 = to_vc4_dev(dev);
-+      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+      struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-+      struct vc4_fkms_encoder *vc4_encoder =
-+                                      to_vc4_fkms_encoder(vc4_crtc->encoder);
-+      struct mailbox_set_mode mb = {
-+              .tag1 = { RPI_FIRMWARE_SET_TIMING,
-+                        sizeof(struct set_timings), 0},
-+      };
-+      union hdmi_infoframe frame;
-+      int ret;
-+
-+      ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
-+      if (ret < 0) {
-+              DRM_ERROR("couldn't fill AVI infoframe\n");
-+              return;
-+      }
-+
-+      DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
-+                    vc4_crtc->display_number, mode->name, mode->clock,
-+                    mode->hdisplay, mode->hsync_start, mode->hsync_end,
-+                    mode->htotal, mode->hskew, mode->vdisplay,
-+                    mode->vsync_start, mode->vsync_end, mode->vtotal,
-+                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
-+      mb.timings.display = vc4_crtc->display_number;
-+
-+      mb.timings.video_id_code = frame.avi.video_code;
-+
-+      mb.timings.clock = mode->clock;
-+      mb.timings.hdisplay = mode->hdisplay;
-+      mb.timings.hsync_start = mode->hsync_start;
-+      mb.timings.hsync_end = mode->hsync_end;
-+      mb.timings.htotal = mode->htotal;
-+      mb.timings.hskew = mode->hskew;
-+      mb.timings.vdisplay = mode->vdisplay;
-+      mb.timings.vsync_start = mode->vsync_start;
-+      mb.timings.vsync_end = mode->vsync_end;
-+      mb.timings.vtotal = mode->vtotal;
-+      mb.timings.vscan = mode->vscan;
-+      mb.timings.vrefresh = 0;
-+      mb.timings.flags = 0;
-+      if (mode->flags & DRM_MODE_FLAG_PHSYNC)
-+              mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
-+      if (mode->flags & DRM_MODE_FLAG_PVSYNC)
-+              mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS;
-+
-+      switch (frame.avi.picture_aspect) {
-+      default:
-+      case HDMI_PICTURE_ASPECT_NONE:
-+              mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
-+              break;
-+      case HDMI_PICTURE_ASPECT_4_3:
-+              mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
-+              break;
-+      case HDMI_PICTURE_ASPECT_16_9:
-+              mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
-+              break;
-+      case HDMI_PICTURE_ASPECT_64_27:
-+              mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
-+              break;
-+      case HDMI_PICTURE_ASPECT_256_135:
-+              mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
-+              break;
-+      }
-+
-+      if (!vc4_encoder->hdmi_monitor)
-+              mb.timings.flags |= TIMINGS_FLAGS_DVI;
-+      else if (drm_default_rgb_quant_range(mode) ==
-+                                      HDMI_QUANTIZATION_RANGE_LIMITED)
-+              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
-+
-+      /*
-+      FIXME: To implement
-+      switch(mode->flag & DRM_MODE_FLAG_3D_MASK) {
-+      case DRM_MODE_FLAG_3D_NONE:
-+      case DRM_MODE_FLAG_3D_FRAME_PACKING:
-+      case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
-+      case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
-+      case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
-+      case DRM_MODE_FLAG_3D_L_DEPTH:
-+      case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
-+      case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
-+      case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
-+      }
-+      */
-+
-+      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
- }
- static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-       struct drm_plane *plane;
-+      DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
-+                    crtc->base.id);
-       drm_crtc_vblank_off(crtc);
-       /* Always turn the planes off on CRTC disable. In DRM, planes
-@@ -617,6 +785,8 @@ static void vc4_crtc_enable(struct drm_c
- {
-       struct drm_plane *plane;
-+      DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
-+                    crtc->base.id);
-       drm_crtc_vblank_on(crtc);
-       /* Unblank the planes (if they're supposed to be displayed). */
-@@ -635,12 +805,20 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
-               return MODE_NO_DBLESCAN;
-       }
-+      /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
-+       * working.
-+       */
-+      if (mode->clock > 340000)
-+              return MODE_CLOCK_HIGH;
-+
-       return MODE_OK;
- }
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
-                                struct drm_crtc_state *state)
- {
-+      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
-+                    crtc->base.id);
-       return 0;
- }
-@@ -650,6 +828,8 @@ static void vc4_crtc_atomic_flush(struct
-       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-+      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
-+                    crtc->base.id);
-       if (crtc->state->event) {
-               unsigned long flags;
-@@ -717,6 +897,8 @@ static int vc4_fkms_enable_vblank(struct
- {
-       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+      DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n",
-+                    crtc->base.id);
-       vc4_crtc->vblank_enabled = true;
-       return 0;
-@@ -726,6 +908,8 @@ static void vc4_fkms_disable_vblank(stru
- {
-       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+      DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n",
-+                    crtc->base.id);
-       vc4_crtc->vblank_enabled = false;
- }
-@@ -760,36 +944,92 @@ static const struct of_device_id vc4_fir
- static enum drm_connector_status
- vc4_fkms_connector_detect(struct drm_connector *connector, bool force)
- {
-+      DRM_DEBUG_KMS("connector detect.\n");
-       return connector_status_connected;
- }
--static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
-+static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
-+                                 size_t len)
- {
--      struct drm_device *dev = connector->dev;
-       struct vc4_fkms_connector *fkms_connector =
--              to_vc4_fkms_connector(connector);
--      struct vc4_dev *vc4 = to_vc4_dev(dev);
--      struct drm_display_mode *mode;
--      struct mailbox_get_width_height wh = {
--              .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
--              .display = fkms_connector->display_idx,
--              .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
--                        8, 0, },
-+                                      (struct vc4_fkms_connector *)data;
-+      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
-+      struct mailbox_get_edid mb = {
-+              .tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY,
-+                        128 + 8, 0 },
-+              .block = block,
-+              .display_number = fkms_connector->display_number,
-       };
--      int ret;
-+      int ret = 0;
-+
-+      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
-+
-+      if (!ret)
-+              memcpy(buf, mb.edid, len);
-+
-+      return ret;
-+}
-+
-+static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
-+{
-+      struct vc4_fkms_connector *fkms_connector =
-+                                      to_vc4_fkms_connector(connector);
-+      struct drm_encoder *encoder = fkms_connector->encoder;
-+      struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
-+      int ret = 0;
-+      struct edid *edid;
-+
-+      edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
-+                             fkms_connector);
-+
-+      /* FIXME: Can we do CEC?
-+       * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
-+       * if (!edid)
-+       *      return -ENODEV;
-+       */
-+
-+      vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
--      ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
-+      if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
-+              vc4_encoder->rgb_range_selectable =
-+                      drm_rgb_quant_range_selectable(edid);
-+      }
-+
-+      drm_connector_update_edid_property(connector, edid);
-+      ret = drm_add_edid_modes(connector, edid);
-+      kfree(edid);
-+
-+      return ret;
-+}
-+
-+/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
-+static const struct drm_display_mode lcd_mode = {
-+      DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-+               25979400 / 1000,
-+               800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
-+               480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
-+               DRM_MODE_FLAG_INTERLACE)
-+};
-+
-+static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
-+{
-+      //struct vc4_fkms_connector *fkms_connector =
-+      //                              to_vc4_fkms_connector(connector);
-+      //struct drm_encoder *encoder = fkms_connector->encoder;
-+      //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
-+      struct drm_display_mode *mode;
-+      //int ret = 0;
--      if (ret) {
--              DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n",
--                        ret, wh.wh[0], wh.wh[1]);
--              return 0;
-+      mode = drm_mode_duplicate(connector->dev,
-+                                &lcd_mode);
-+      if (!mode) {
-+              DRM_ERROR("Failed to create a new display mode\n");
-+              return -ENOMEM;
-       }
--      mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
--                          0, 0, false);
-       drm_mode_probed_add(connector, mode);
-+      /* We have one mode */
-       return 1;
- }
-@@ -798,11 +1038,14 @@ vc4_fkms_connector_best_encoder(struct d
- {
-       struct vc4_fkms_connector *fkms_connector =
-               to_vc4_fkms_connector(connector);
-+      DRM_DEBUG_KMS("best_connector.\n");
-       return fkms_connector->encoder;
- }
- static void vc4_fkms_connector_destroy(struct drm_connector *connector)
- {
-+      DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n",
-+                    connector->base.id);
-       drm_connector_unregister(connector);
-       drm_connector_cleanup(connector);
- }
-@@ -821,14 +1064,22 @@ static const struct drm_connector_helper
-       .best_encoder = vc4_fkms_connector_best_encoder,
- };
-+static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = {
-+      .get_modes = vc4_fkms_lcd_connector_get_modes,
-+      .best_encoder = vc4_fkms_connector_best_encoder,
-+};
-+
- static struct drm_connector *
- vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
--                      u32 display_idx)
-+                      u32 display_num)
- {
-       struct drm_connector *connector = NULL;
-       struct vc4_fkms_connector *fkms_connector;
-+      struct vc4_dev *vc4_dev = to_vc4_dev(dev);
-       int ret = 0;
-+      DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num);
-+
-       fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
-                                     GFP_KERNEL);
-       if (!fkms_connector) {
-@@ -838,11 +1089,21 @@ vc4_fkms_connector_init(struct drm_devic
-       connector = &fkms_connector->base;
-       fkms_connector->encoder = encoder;
--      fkms_connector->display_idx = display_idx;
--
--      drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
--                         DRM_MODE_CONNECTOR_HDMIA);
--      drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs);
-+      fkms_connector->display_number = display_num;
-+      fkms_connector->display_type = vc4_get_display_type(display_num);
-+      fkms_connector->vc4_dev = vc4_dev;
-+
-+      if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
-+              drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-+                                 DRM_MODE_CONNECTOR_DSI);
-+              drm_connector_helper_add(connector,
-+                                       &vc4_fkms_lcd_conn_helper_funcs);
-+      } else {
-+              drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-+                                 DRM_MODE_CONNECTOR_HDMIA);
-+              drm_connector_helper_add(connector,
-+                                       &vc4_fkms_connector_helper_funcs);
-+      }
-       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
-                            DRM_CONNECTOR_POLL_DISCONNECT);
-@@ -863,6 +1124,7 @@ vc4_fkms_connector_init(struct drm_devic
- static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder)
- {
-+      DRM_DEBUG_KMS("Encoder_destroy\n");
-       drm_encoder_cleanup(encoder);
- }
-@@ -872,10 +1134,12 @@ static const struct drm_encoder_funcs vc
- static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
- {
-+      DRM_DEBUG_KMS("Encoder_enable\n");
- }
- static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
- {
-+      DRM_DEBUG_KMS("Encoder_disable\n");
- }
- static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = {
-@@ -907,6 +1171,7 @@ static int vc4_fkms_create_screen(struct
-       crtc = &vc4_crtc->base;
-       vc4_crtc->display_number = display_ref;
-+      vc4_crtc->display_type = vc4_get_display_type(display_ref);
-       /* Blank the firmware provided framebuffer */
-       rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
-@@ -950,13 +1215,14 @@ static int vc4_fkms_create_screen(struct
-               return -ENOMEM;
-       vc4_crtc->encoder = &vc4_encoder->base;
-       vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ;
-+
-       drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs,
--                       DRM_MODE_ENCODER_TMDS, NULL);
-+                       vc4_crtc->display_type, NULL);
-       drm_encoder_helper_add(&vc4_encoder->base,
-                              &vc4_fkms_encoder_helper_funcs);
-       vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
--                                                    display_idx);
-+                                                    display_ref);
-       if (IS_ERR(vc4_crtc->connector)) {
-               ret = PTR_ERR(vc4_crtc->connector);
-               goto err_destroy_encoder;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -78,6 +78,7 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE =       0x00030014,
-       RPI_FIRMWARE_GET_EDID_BLOCK =                         0x00030020,
-       RPI_FIRMWARE_GET_CUSTOMER_OTP =                       0x00030021,
-+      RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY =                 0x00030023,
-       RPI_FIRMWARE_GET_DOMAIN_STATE =                       0x00030030,
-       RPI_FIRMWARE_GET_THROTTLED =                          0x00030046,
-       RPI_FIRMWARE_GET_CLOCK_MEASURED =                     0x00030047,
-@@ -150,6 +151,7 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
-       RPI_FIRMWARE_SET_PLANE =                              0x00048015,
-+      RPI_FIRMWARE_SET_TIMING =                             0x00048017,
-       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
-       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
diff --git a/target/linux/brcm2708/patches-4.19/950-0535-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch b/target/linux/brcm2708/patches-4.19/950-0535-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch
deleted file mode 100644 (file)
index ca70b9d..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From bf85b92a97a95161d98874571c520fb1395c5aa2 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 2 May 2019 15:11:05 -0700
-Subject: [PATCH] clk: bcm2835: Add support for setting leaf clock
- rates while running.
-
-As long as you wait for !BUSY, you can do glitch-free updates of clock
-rate while the clock is running.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/clk/bcm/clk-bcm2835.c | 22 +++++++++++++---------
- 1 file changed, 13 insertions(+), 9 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1097,15 +1097,19 @@ static int bcm2835_clock_set_rate(struct
-       spin_lock(&cprman->regs_lock);
--      /*
--       * Setting up frac support
--       *
--       * In principle it is recommended to stop/start the clock first,
--       * but as we set CLK_SET_RATE_GATE during registration of the
--       * clock this requirement should be take care of by the
--       * clk-framework.
-+      ctl = cprman_read(cprman, data->ctl_reg);
-+
-+      /* If the clock is running, we have to pause clock generation while
-+       * updating the control and div regs.  This is glitchless (no clock
-+       * signals generated faster than the rate) but each reg access is two
-+       * OSC cycles so the clock will slow down for a moment.
-        */
--      ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
-+      if (ctl & CM_ENABLE) {
-+              cprman_write(cprman, data->ctl_reg, ctl & ~CM_ENABLE);
-+              bcm2835_clock_wait_busy(clock);
-+      }
-+
-+      ctl &= ~CM_FRAC;
-       ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
-       cprman_write(cprman, data->ctl_reg, ctl);
-@@ -1475,7 +1479,7 @@ static struct clk_hw *bcm2835_register_c
-               init.ops = &bcm2835_vpu_clock_clk_ops;
-       } else {
-               init.ops = &bcm2835_clock_clk_ops;
--              init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
-+              init.flags |= CLK_SET_PARENT_GATE;
-               /* If the clock wasn't actually enabled at boot, it's not
-                * critical.
diff --git a/target/linux/brcm2708/patches-4.19/950-0535-drm-v3d-Add-support-for-compute-shader-dispatch.patch b/target/linux/brcm2708/patches-4.19/950-0535-drm-v3d-Add-support-for-compute-shader-dispatch.patch
new file mode 100644 (file)
index 0000000..6db0729
--- /dev/null
@@ -0,0 +1,897 @@
+From 22dbf1420a552d1952d22b92d8c30f8162b026b5 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 16 Apr 2019 15:58:54 -0700
+Subject: [PATCH] drm/v3d: Add support for compute shader dispatch.
+
+The compute shader dispatch interface is pretty simple -- just pass in
+the regs that userspace has passed us, with no CLs to run.  However,
+with no CL to run it means that we need to do manual cache flushing of
+the L2 after the HW execution completes (for SSBO, atomic, and
+image_load_store writes that are the output of compute shaders).
+
+This doesn't yet expose the L2 cache's ability to have a region of the
+address space not write back to memory (which could be used for
+shared_var storage).
+
+So far, the Mesa side has been tested on V3D v4.2 simpenrose (passing
+the ES31 tests), and on the kernel side on 7278 (failing atomic
+compswap tests in a way that doesn't reproduce on simpenrose).
+
+v2: Fix excessive allocation for the clean_job (reported by Dan
+    Carpenter).  Keep refs on jobs until clean_job is finished, to
+    avoid spurious MMU errors if the output BOs are freed by userspace
+    before L2 cleaning is finished.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190416225856.20264-4-eric@anholt.net
+Acked-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c |  22 +++++
+ drivers/gpu/drm/v3d/v3d_drv.c     |  10 +-
+ drivers/gpu/drm/v3d/v3d_drv.h     |  28 +++++-
+ drivers/gpu/drm/v3d/v3d_fence.c   |   2 +
+ drivers/gpu/drm/v3d/v3d_gem.c     | 156 +++++++++++++++++++++++++++++-
+ drivers/gpu/drm/v3d/v3d_irq.c     |  16 ++-
+ drivers/gpu/drm/v3d/v3d_regs.h    |  73 ++++++++++++++
+ drivers/gpu/drm/v3d/v3d_sched.c   | 121 +++++++++++++++++++++--
+ drivers/gpu/drm/v3d/v3d_trace.h   |  94 ++++++++++++++++++
+ include/uapi/drm/v3d_drm.h        |  28 ++++++
+ 10 files changed, 531 insertions(+), 19 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -57,6 +57,17 @@ static const struct v3d_reg_def v3d_core
+       REGDEF(V3D_GMP_VIO_ADDR),
+ };
++static const struct v3d_reg_def v3d_csd_reg_defs[] = {
++      REGDEF(V3D_CSD_STATUS),
++      REGDEF(V3D_CSD_CURRENT_CFG0),
++      REGDEF(V3D_CSD_CURRENT_CFG1),
++      REGDEF(V3D_CSD_CURRENT_CFG2),
++      REGDEF(V3D_CSD_CURRENT_CFG3),
++      REGDEF(V3D_CSD_CURRENT_CFG4),
++      REGDEF(V3D_CSD_CURRENT_CFG5),
++      REGDEF(V3D_CSD_CURRENT_CFG6),
++};
++
+ static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
+ {
+       struct drm_info_node *node = (struct drm_info_node *)m->private;
+@@ -88,6 +99,17 @@ static int v3d_v3d_debugfs_regs(struct s
+                                  V3D_CORE_READ(core,
+                                                v3d_core_reg_defs[i].reg));
+               }
++
++              if (v3d_has_csd(v3d)) {
++                      for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
++                              seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
++                                         core,
++                                         v3d_csd_reg_defs[i].name,
++                                         v3d_csd_reg_defs[i].reg,
++                                         V3D_CORE_READ(core,
++                                                       v3d_csd_reg_defs[i].reg));
++                      }
++              }
+       }
+       return 0;
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -7,9 +7,9 @@
+  * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
+  * For V3D 2.x support, see the VC4 driver.
+  *
+- * Currently only single-core rendering using the binner and renderer,
+- * along with TFU (texture formatting unit) rendering is supported.
+- * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
++ * The V3D GPU includes a tiled render (composed of a bin and render
++ * pipelines), the TFU (texture formatting unit), and the CSD (compute
++ * shader dispatch).
+  */
+ #include <linux/clk.h>
+@@ -114,6 +114,9 @@ static int v3d_get_param_ioctl(struct dr
+       case DRM_V3D_PARAM_SUPPORTS_TFU:
+               args->value = 1;
+               return 0;
++      case DRM_V3D_PARAM_SUPPORTS_CSD:
++              args->value = v3d_has_csd(v3d);
++              return 0;
+       default:
+               DRM_DEBUG("Unknown parameter %d\n", args->param);
+               return -EINVAL;
+@@ -183,6 +186,7 @@ static const struct drm_ioctl_desc v3d_d
+       DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
++      DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CSD, v3d_submit_csd_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+ };
+ static const struct vm_operations_struct v3d_vm_ops = {
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -16,9 +16,11 @@ enum v3d_queue {
+       V3D_BIN,
+       V3D_RENDER,
+       V3D_TFU,
++      V3D_CSD,
++      V3D_CACHE_CLEAN,
+ };
+-#define V3D_MAX_QUEUES (V3D_TFU + 1)
++#define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1)
+ struct v3d_queue_state {
+       struct drm_gpu_scheduler sched;
+@@ -70,6 +72,7 @@ struct v3d_dev {
+       struct v3d_bin_job *bin_job;
+       struct v3d_render_job *render_job;
+       struct v3d_tfu_job *tfu_job;
++      struct v3d_csd_job *csd_job;
+       struct v3d_queue_state queue[V3D_MAX_QUEUES];
+@@ -92,6 +95,12 @@ struct v3d_dev {
+        */
+       struct mutex sched_lock;
++      /* Lock taken during a cache clean and when initiating an L2
++       * flush, to keep L2 flushes from interfering with the
++       * synchronous L2 cleans.
++       */
++      struct mutex cache_clean_lock;
++
+       struct {
+               u32 num_allocated;
+               u32 pages_allocated;
+@@ -104,6 +113,12 @@ to_v3d_dev(struct drm_device *dev)
+       return (struct v3d_dev *)dev->dev_private;
+ }
++static inline bool
++v3d_has_csd(struct v3d_dev *v3d)
++{
++      return v3d->ver >= 41;
++}
++
+ /* The per-fd struct, which tracks the MMU mappings. */
+ struct v3d_file_priv {
+       struct v3d_dev *v3d;
+@@ -237,6 +252,14 @@ struct v3d_tfu_job {
+       struct drm_v3d_submit_tfu args;
+ };
++struct v3d_csd_job {
++      struct v3d_job base;
++
++      u32 timedout_batches;
++
++      struct drm_v3d_submit_csd args;
++};
++
+ /**
+  * _wait_for - magic (register) wait macro
+  *
+@@ -302,11 +325,14 @@ int v3d_submit_cl_ioctl(struct drm_devic
+                       struct drm_file *file_priv);
+ int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
++int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
++                       struct drm_file *file_priv);
+ int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+ void v3d_job_put(struct v3d_job *job);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
++void v3d_clean_caches(struct v3d_dev *v3d);
+ /* v3d_irq.c */
+ int v3d_irq_init(struct v3d_dev *v3d);
+--- a/drivers/gpu/drm/v3d/v3d_fence.c
++++ b/drivers/gpu/drm/v3d/v3d_fence.c
+@@ -36,6 +36,8 @@ static const char *v3d_fence_get_timelin
+               return "v3d-render";
+       case V3D_TFU:
+               return "v3d-tfu";
++      case V3D_CSD:
++              return "v3d-csd";
+       default:
+               return NULL;
+       }
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -162,10 +162,52 @@ v3d_flush_l2t(struct v3d_dev *v3d, int c
+       /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
+        * need to wait for completion before dispatching the job --
+        * L2T accesses will be stalled until the flush has completed.
++       * However, we do need to make sure we don't try to trigger a
++       * new flush while the L2_CLEAN queue is trying to
++       * synchronously clean after a job.
+        */
++      mutex_lock(&v3d->cache_clean_lock);
+       V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
+                      V3D_L2TCACTL_L2TFLS |
+                      V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
++      mutex_unlock(&v3d->cache_clean_lock);
++}
++
++/* Cleans texture L1 and L2 cachelines (writing back dirty data).
++ *
++ * For cleaning, which happens from the CACHE_CLEAN queue after CSD has
++ * executed, we need to make sure that the clean is done before
++ * signaling job completion.  So, we synchronously wait before
++ * returning, and we make sure that L2 invalidates don't happen in the
++ * meantime to confuse our are-we-done checks.
++ */
++void
++v3d_clean_caches(struct v3d_dev *v3d)
++{
++      struct drm_device *dev = &v3d->drm;
++      int core = 0;
++
++      trace_v3d_cache_clean_begin(dev);
++
++      V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
++      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
++                     V3D_L2TCACTL_L2TFLS), 100)) {
++              DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
++      }
++
++      mutex_lock(&v3d->cache_clean_lock);
++      V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
++                     V3D_L2TCACTL_L2TFLS |
++                     V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAN, V3D_L2TCACTL_FLM));
++
++      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
++                     V3D_L2TCACTL_L2TFLS), 100)) {
++              DRM_ERROR("Timeout waiting for L2T clean\n");
++      }
++
++      mutex_unlock(&v3d->cache_clean_lock);
++
++      trace_v3d_cache_clean_end(dev);
+ }
+ /* Invalidates the slice caches.  These are read-only caches. */
+@@ -584,7 +626,8 @@ static void
+ v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
+                                        struct v3d_job *job,
+                                        struct ww_acquire_ctx *acquire_ctx,
+-                                       u32 out_sync)
++                                       u32 out_sync,
++                                       struct dma_fence *done_fence)
+ {
+       struct drm_syncobj *sync_out;
+@@ -594,7 +637,7 @@ v3d_attach_fences_and_unlock_reservation
+       /* Update the return sync object for the job */
+       sync_out = drm_syncobj_find(file_priv, out_sync);
+       if (sync_out) {
+-              drm_syncobj_replace_fence(sync_out, job->done_fence);
++              drm_syncobj_replace_fence(sync_out, done_fence);
+               drm_syncobj_put(sync_out);
+       }
+ }
+@@ -691,8 +734,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       mutex_unlock(&v3d->sched_lock);
+       v3d_attach_fences_and_unlock_reservation(file_priv,
+-                                               &render->base, &acquire_ctx,
+-                                               args->out_sync);
++                                               &render->base,
++                                               &acquire_ctx,
++                                               args->out_sync,
++                                               render->base.done_fence);
+       if (bin)
+               v3d_job_put(&bin->base);
+@@ -785,7 +830,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
+       v3d_attach_fences_and_unlock_reservation(file_priv,
+                                                &job->base, &acquire_ctx,
+-                                               args->out_sync);
++                                               args->out_sync,
++                                               job->base.done_fence);
+       v3d_job_put(&job->base);
+@@ -801,6 +847,105 @@ fail:
+       return ret;
+ }
++/**
++ * v3d_submit_csd_ioctl() - Submits a CSD (texture formatting) job to the V3D.
++ * @dev: DRM device
++ * @data: ioctl argument
++ * @file_priv: DRM file for this fd
++ *
++ * Userspace provides the register setup for the CSD, which we don't
++ * need to validate since the CSD is behind the MMU.
++ */
++int
++v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
++                   struct drm_file *file_priv)
++{
++      struct v3d_dev *v3d = to_v3d_dev(dev);
++      struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
++      struct drm_v3d_submit_csd *args = data;
++      struct v3d_csd_job *job;
++      struct v3d_job *clean_job;
++      struct ww_acquire_ctx acquire_ctx;
++      int ret;
++
++      trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]);
++
++      if (!v3d_has_csd(v3d)) {
++              DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n");
++              return -EINVAL;
++      }
++
++      job = kcalloc(1, sizeof(*job), GFP_KERNEL);
++      if (!job)
++              return -ENOMEM;
++
++      ret = v3d_job_init(v3d, file_priv, &job->base,
++                         v3d_job_free, args->in_sync);
++      if (ret) {
++              kfree(job);
++              return ret;
++      }
++
++      clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
++      if (!clean_job) {
++              v3d_job_put(&job->base);
++              kfree(job);
++              return -ENOMEM;
++      }
++
++      ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
++      if (ret) {
++              v3d_job_put(&job->base);
++              kfree(clean_job);
++              return ret;
++      }
++
++      job->args = *args;
++
++      ret = v3d_lookup_bos(dev, file_priv, clean_job,
++                           args->bo_handles, args->bo_handle_count);
++      if (ret)
++              goto fail;
++
++      ret = v3d_lock_bo_reservations(clean_job, &acquire_ctx);
++      if (ret)
++              goto fail;
++
++      mutex_lock(&v3d->sched_lock);
++      ret = v3d_push_job(v3d_priv, &job->base, V3D_CSD);
++      if (ret)
++              goto fail_unreserve;
++
++      ret = v3d_add_dep(clean_job, dma_fence_get(job->base.done_fence));
++      if (ret)
++              goto fail_unreserve;
++      ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
++      if (ret)
++              goto fail_unreserve;
++      mutex_unlock(&v3d->sched_lock);
++
++      v3d_attach_fences_and_unlock_reservation(file_priv,
++                                               clean_job,
++                                               &acquire_ctx,
++                                               args->out_sync,
++                                               clean_job->done_fence);
++
++      v3d_job_put(&job->base);
++      v3d_job_put(clean_job);
++
++      return 0;
++
++fail_unreserve:
++      mutex_unlock(&v3d->sched_lock);
++      v3d_unlock_bo_reservations(clean_job->bo, clean_job->bo_count,
++                                 &acquire_ctx);
++fail:
++      v3d_job_put(&job->base);
++      v3d_job_put(clean_job);
++
++      return ret;
++}
++
+ int
+ v3d_gem_init(struct drm_device *dev)
+ {
+@@ -816,6 +961,7 @@ v3d_gem_init(struct drm_device *dev)
+       mutex_init(&v3d->bo_lock);
+       mutex_init(&v3d->reset_lock);
+       mutex_init(&v3d->sched_lock);
++      mutex_init(&v3d->cache_clean_lock);
+       /* Note: We don't allocate address 0.  Various bits of HW
+        * treat 0 as special, such as the occlusion query counters
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -4,9 +4,9 @@
+ /**
+  * DOC: Interrupt management for the V3D engine
+  *
+- * When we take a bin, render, or TFU done interrupt, we need to
+- * signal the fence for that job so that the scheduler can queue up
+- * the next one and unblock any waiters.
++ * When we take a bin, render, TFU done, or CSD done interrupt, we
++ * need to signal the fence for that job so that the scheduler can
++ * queue up the next one and unblock any waiters.
+  *
+  * When we take the binner out of memory interrupt, we need to
+  * allocate some new memory and pass it to the binner so that the
+@@ -20,6 +20,7 @@
+ #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM |        \
+                            V3D_INT_FLDONE |   \
+                            V3D_INT_FRDONE |   \
++                           V3D_INT_CSDDONE |  \
+                            V3D_INT_GMPV))
+ #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV |     \
+@@ -108,6 +109,15 @@ v3d_irq(int irq, void *arg)
+               dma_fence_signal(&fence->base);
+               status = IRQ_HANDLED;
+       }
++
++      if (intsts & V3D_INT_CSDDONE) {
++              struct v3d_fence *fence =
++                      to_v3d_fence(v3d->csd_job->base.irq_fence);
++
++              trace_v3d_csd_irq(&v3d->drm, fence->seqno);
++              dma_fence_signal(&fence->base);
++              status = IRQ_HANDLED;
++      }
+       /* We shouldn't be triggering these if we have GMP in
+        * always-allowed mode.
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -238,8 +238,11 @@
+ #define V3D_CTL_L2TCACTL                               0x00030
+ # define V3D_L2TCACTL_TMUWCF                           BIT(8)
+ # define V3D_L2TCACTL_L2T_NO_WM                        BIT(4)
++/* Invalidates cache lines. */
+ # define V3D_L2TCACTL_FLM_FLUSH                        0
++/* Removes cachelines without writing dirty lines back. */
+ # define V3D_L2TCACTL_FLM_CLEAR                        1
++/* Writes out dirty cachelines and marks them clean, but doesn't invalidate. */
+ # define V3D_L2TCACTL_FLM_CLEAN                        2
+ # define V3D_L2TCACTL_FLM_MASK                         V3D_MASK(2, 1)
+ # define V3D_L2TCACTL_FLM_SHIFT                        1
+@@ -255,6 +258,8 @@
+ #define V3D_CTL_INT_MSK_CLR                            0x00064
+ # define V3D_INT_QPU_MASK                              V3D_MASK(27, 16)
+ # define V3D_INT_QPU_SHIFT                             16
++# define V3D_INT_CSDDONE                               BIT(7)
++# define V3D_INT_PCTR                                  BIT(6)
+ # define V3D_INT_GMPV                                  BIT(5)
+ # define V3D_INT_TRFB                                  BIT(4)
+ # define V3D_INT_SPILLUSE                              BIT(3)
+@@ -374,4 +379,72 @@
+ #define V3D_GMP_PRESERVE_LOAD                          0x00818
+ #define V3D_GMP_VALID_LINES                            0x00820
++#define V3D_CSD_STATUS                                 0x00900
++# define V3D_CSD_STATUS_NUM_COMPLETED_MASK             V3D_MASK(11, 4)
++# define V3D_CSD_STATUS_NUM_COMPLETED_SHIFT            4
++# define V3D_CSD_STATUS_NUM_ACTIVE_MASK                V3D_MASK(3, 2)
++# define V3D_CSD_STATUS_NUM_ACTIVE_SHIFT               2
++# define V3D_CSD_STATUS_HAVE_CURRENT_DISPATCH          BIT(1)
++# define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH           BIT(0)
++
++#define V3D_CSD_QUEUED_CFG0                            0x00904
++# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK            V3D_MASK(31, 16)
++# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT           16
++# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_MASK          V3D_MASK(15, 0)
++# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_SHIFT         0
++
++#define V3D_CSD_QUEUED_CFG1                            0x00908
++# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_MASK            V3D_MASK(31, 16)
++# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_SHIFT           16
++# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_MASK          V3D_MASK(15, 0)
++# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_SHIFT         0
++
++#define V3D_CSD_QUEUED_CFG2                            0x0090c
++# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_MASK            V3D_MASK(31, 16)
++# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_SHIFT           16
++# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_MASK          V3D_MASK(15, 0)
++# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_SHIFT         0
++
++#define V3D_CSD_QUEUED_CFG3                            0x00910
++# define V3D_CSD_QUEUED_CFG3_OVERLAP_WITH_PREV         BIT(26)
++# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_MASK            V3D_MASK(25, 20)
++# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_SHIFT           20
++# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_MASK    V3D_MASK(19, 12)
++# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_SHIFT   12
++# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_MASK           V3D_MASK(11, 8)
++# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_SHIFT          8
++# define V3D_CSD_QUEUED_CFG3_WG_SIZE_MASK              V3D_MASK(7, 0)
++# define V3D_CSD_QUEUED_CFG3_WG_SIZE_SHIFT             0
++
++/* Number of batches, minus 1 */
++#define V3D_CSD_QUEUED_CFG4                            0x00914
++
++/* Shader address, pnan, singleseg, threading, like a shader record. */
++#define V3D_CSD_QUEUED_CFG5                            0x00918
++
++/* Uniforms address (4 byte aligned) */
++#define V3D_CSD_QUEUED_CFG6                            0x0091c
++
++#define V3D_CSD_CURRENT_CFG0                          0x00920
++#define V3D_CSD_CURRENT_CFG1                          0x00924
++#define V3D_CSD_CURRENT_CFG2                          0x00928
++#define V3D_CSD_CURRENT_CFG3                          0x0092c
++#define V3D_CSD_CURRENT_CFG4                          0x00930
++#define V3D_CSD_CURRENT_CFG5                          0x00934
++#define V3D_CSD_CURRENT_CFG6                          0x00938
++
++#define V3D_CSD_CURRENT_ID0                            0x0093c
++# define V3D_CSD_CURRENT_ID0_WG_X_MASK                 V3D_MASK(31, 16)
++# define V3D_CSD_CURRENT_ID0_WG_X_SHIFT                16
++# define V3D_CSD_CURRENT_ID0_WG_IN_SG_MASK             V3D_MASK(11, 8)
++# define V3D_CSD_CURRENT_ID0_WG_IN_SG_SHIFT            8
++# define V3D_CSD_CURRENT_ID0_L_IDX_MASK                V3D_MASK(7, 0)
++# define V3D_CSD_CURRENT_ID0_L_IDX_SHIFT               0
++
++#define V3D_CSD_CURRENT_ID1                            0x00940
++# define V3D_CSD_CURRENT_ID0_WG_Z_MASK                 V3D_MASK(31, 16)
++# define V3D_CSD_CURRENT_ID0_WG_Z_SHIFT                16
++# define V3D_CSD_CURRENT_ID0_WG_Y_MASK                 V3D_MASK(15, 0)
++# define V3D_CSD_CURRENT_ID0_WG_Y_SHIFT                0
++
+ #endif /* V3D_REGS_H */
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -48,6 +48,12 @@ to_tfu_job(struct drm_sched_job *sched_j
+       return container_of(sched_job, struct v3d_tfu_job, base.base);
+ }
++static struct v3d_csd_job *
++to_csd_job(struct drm_sched_job *sched_job)
++{
++      return container_of(sched_job, struct v3d_csd_job, base.base);
++}
++
+ static void
+ v3d_job_free(struct drm_sched_job *sched_job)
+ {
+@@ -205,6 +211,48 @@ v3d_tfu_job_run(struct drm_sched_job *sc
+       return fence;
+ }
++static struct dma_fence *
++v3d_csd_job_run(struct drm_sched_job *sched_job)
++{
++      struct v3d_csd_job *job = to_csd_job(sched_job);
++      struct v3d_dev *v3d = job->base.v3d;
++      struct drm_device *dev = &v3d->drm;
++      struct dma_fence *fence;
++      int i;
++
++      v3d->csd_job = job;
++
++      v3d_invalidate_caches(v3d);
++
++      fence = v3d_fence_create(v3d, V3D_CSD);
++      if (IS_ERR(fence))
++              return NULL;
++
++      if (job->base.irq_fence)
++              dma_fence_put(job->base.irq_fence);
++      job->base.irq_fence = dma_fence_get(fence);
++
++      trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
++
++      for (i = 1; i <= 6; i++)
++              V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]);
++      /* CFG0 write kicks off the job. */
++      V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0, job->args.cfg[0]);
++
++      return fence;
++}
++
++static struct dma_fence *
++v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
++{
++      struct v3d_job *job = to_v3d_job(sched_job);
++      struct v3d_dev *v3d = job->v3d;
++
++      v3d_clean_caches(v3d);
++
++      return NULL;
++}
++
+ static void
+ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
+ {
+@@ -277,13 +325,31 @@ v3d_render_job_timedout(struct drm_sched
+ }
+ static void
+-v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
++v3d_generic_job_timedout(struct drm_sched_job *sched_job)
+ {
+       struct v3d_job *job = to_v3d_job(sched_job);
+       v3d_gpu_reset_for_timeout(job->v3d, sched_job);
+ }
++static void
++v3d_csd_job_timedout(struct drm_sched_job *sched_job)
++{
++      struct v3d_csd_job *job = to_csd_job(sched_job);
++      struct v3d_dev *v3d = job->base.v3d;
++      u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4);
++
++      /* If we've made progress, skip reset and let the timer get
++       * rearmed.
++       */
++      if (job->timedout_batches != batches) {
++              job->timedout_batches = batches;
++              return;
++      }
++
++      v3d_gpu_reset_for_timeout(v3d, sched_job);
++}
++
+ static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
+       .dependency = v3d_job_dependency,
+       .run_job = v3d_bin_job_run,
+@@ -301,10 +367,24 @@ static const struct drm_sched_backend_op
+ static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
+       .dependency = v3d_job_dependency,
+       .run_job = v3d_tfu_job_run,
+-      .timedout_job = v3d_tfu_job_timedout,
++      .timedout_job = v3d_generic_job_timedout,
+       .free_job = v3d_job_free,
+ };
++static const struct drm_sched_backend_ops v3d_csd_sched_ops = {
++      .dependency = v3d_job_dependency,
++      .run_job = v3d_csd_job_run,
++      .timedout_job = v3d_csd_job_timedout,
++      .free_job = v3d_job_free
++};
++
++static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
++      .dependency = v3d_job_dependency,
++      .run_job = v3d_cache_clean_job_run,
++      .timedout_job = v3d_generic_job_timedout,
++      .free_job = v3d_job_free
++};
++
+ int
+ v3d_sched_init(struct v3d_dev *v3d)
+ {
+@@ -331,7 +411,7 @@ v3d_sched_init(struct v3d_dev *v3d)
+       if (ret) {
+               dev_err(v3d->dev, "Failed to create render scheduler: %d.",
+                       ret);
+-              drm_sched_fini(&v3d->queue[V3D_BIN].sched);
++              v3d_sched_fini(v3d);
+               return ret;
+       }
+@@ -343,11 +423,36 @@ v3d_sched_init(struct v3d_dev *v3d)
+       if (ret) {
+               dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
+                       ret);
+-              drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
+-              drm_sched_fini(&v3d->queue[V3D_BIN].sched);
++              v3d_sched_fini(v3d);
+               return ret;
+       }
++      if (v3d_has_csd(v3d)) {
++              ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
++                                   &v3d_csd_sched_ops,
++                                   hw_jobs_limit, job_hang_limit,
++                                   msecs_to_jiffies(hang_limit_ms),
++                                   "v3d_csd");
++              if (ret) {
++                      dev_err(v3d->dev, "Failed to create CSD scheduler: %d.",
++                              ret);
++                      v3d_sched_fini(v3d);
++                      return ret;
++              }
++
++              ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
++                                   &v3d_cache_clean_sched_ops,
++                                   hw_jobs_limit, job_hang_limit,
++                                   msecs_to_jiffies(hang_limit_ms),
++                                   "v3d_cache_clean");
++              if (ret) {
++                      dev_err(v3d->dev, "Failed to create CACHE_CLEAN scheduler: %d.",
++                              ret);
++                      v3d_sched_fini(v3d);
++                      return ret;
++              }
++      }
++
+       return 0;
+ }
+@@ -356,6 +461,8 @@ v3d_sched_fini(struct v3d_dev *v3d)
+ {
+       enum v3d_queue q;
+-      for (q = 0; q < V3D_MAX_QUEUES; q++)
+-              drm_sched_fini(&v3d->queue[q].sched);
++      for (q = 0; q < V3D_MAX_QUEUES; q++) {
++              if (v3d->queue[q].sched.ops)
++                      drm_sched_fini(&v3d->queue[q].sched);
++      }
+ }
+--- a/drivers/gpu/drm/v3d/v3d_trace.h
++++ b/drivers/gpu/drm/v3d/v3d_trace.h
+@@ -124,6 +124,26 @@ TRACE_EVENT(v3d_tfu_irq,
+                     __entry->seqno)
+ );
++TRACE_EVENT(v3d_csd_irq,
++          TP_PROTO(struct drm_device *dev,
++                   uint64_t seqno),
++          TP_ARGS(dev, seqno),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u64, seqno)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->seqno = seqno;
++                         ),
++
++          TP_printk("dev=%u, seqno=%llu",
++                    __entry->dev,
++                    __entry->seqno)
++);
++
+ TRACE_EVENT(v3d_submit_tfu_ioctl,
+           TP_PROTO(struct drm_device *dev, u32 iia),
+           TP_ARGS(dev, iia),
+@@ -163,6 +183,80 @@ TRACE_EVENT(v3d_submit_tfu,
+                     __entry->seqno)
+ );
++TRACE_EVENT(v3d_submit_csd_ioctl,
++          TP_PROTO(struct drm_device *dev, u32 cfg5, u32 cfg6),
++          TP_ARGS(dev, cfg5, cfg6),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u32, cfg5)
++                           __field(u32, cfg6)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->cfg5 = cfg5;
++                         __entry->cfg6 = cfg6;
++                         ),
++
++          TP_printk("dev=%u, CFG5 0x%08x, CFG6 0x%08x",
++                    __entry->dev,
++                    __entry->cfg5,
++                    __entry->cfg6)
++);
++
++TRACE_EVENT(v3d_submit_csd,
++          TP_PROTO(struct drm_device *dev,
++                   uint64_t seqno),
++          TP_ARGS(dev, seqno),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           __field(u64, seqno)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         __entry->seqno = seqno;
++                         ),
++
++          TP_printk("dev=%u, seqno=%llu",
++                    __entry->dev,
++                    __entry->seqno)
++);
++
++TRACE_EVENT(v3d_cache_clean_begin,
++          TP_PROTO(struct drm_device *dev),
++          TP_ARGS(dev),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         ),
++
++          TP_printk("dev=%u",
++                    __entry->dev)
++);
++
++TRACE_EVENT(v3d_cache_clean_end,
++          TP_PROTO(struct drm_device *dev),
++          TP_ARGS(dev),
++
++          TP_STRUCT__entry(
++                           __field(u32, dev)
++                           ),
++
++          TP_fast_assign(
++                         __entry->dev = dev->primary->index;
++                         ),
++
++          TP_printk("dev=%u",
++                    __entry->dev)
++);
++
+ TRACE_EVENT(v3d_reset_begin,
+           TP_PROTO(struct drm_device *dev),
+           TP_ARGS(dev),
+--- a/include/uapi/drm/v3d_drm.h
++++ b/include/uapi/drm/v3d_drm.h
+@@ -37,6 +37,7 @@ extern "C" {
+ #define DRM_V3D_GET_PARAM                         0x04
+ #define DRM_V3D_GET_BO_OFFSET                     0x05
+ #define DRM_V3D_SUBMIT_TFU                        0x06
++#define DRM_V3D_SUBMIT_CSD                        0x07
+ #define DRM_IOCTL_V3D_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
+ #define DRM_IOCTL_V3D_WAIT_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
+@@ -45,6 +46,7 @@ extern "C" {
+ #define DRM_IOCTL_V3D_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
+ #define DRM_IOCTL_V3D_GET_BO_OFFSET       DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
+ #define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
++#define DRM_IOCTL_V3D_SUBMIT_CSD          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
+ /**
+  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
+@@ -172,6 +174,7 @@ enum drm_v3d_param {
+       DRM_V3D_PARAM_V3D_CORE0_IDENT1,
+       DRM_V3D_PARAM_V3D_CORE0_IDENT2,
+       DRM_V3D_PARAM_SUPPORTS_TFU,
++      DRM_V3D_PARAM_SUPPORTS_CSD,
+ };
+ struct drm_v3d_get_param {
+@@ -212,6 +215,31 @@ struct drm_v3d_submit_tfu {
+       __u32 out_sync;
+ };
++/* Submits a compute shader for dispatch.  This job will block on any
++ * previous compute shaders submitted on this fd, and any other
++ * synchronization must be performed with in_sync/out_sync.
++ */
++struct drm_v3d_submit_csd {
++      __u32 cfg[7];
++      __u32 coef[4];
++
++      /* Pointer to a u32 array of the BOs that are referenced by the job.
++       */
++      __u64 bo_handles;
++
++      /* Number of BO handles passed in (size is that times 4). */
++      __u32 bo_handle_count;
++
++      /* sync object to block on before running the CSD job.  Each
++       * CSD job will execute in the order submitted to its FD.
++       * Synchronization against rendering/TFU jobs or CSD from
++       * other fds requires using sync objects.
++       */
++      __u32 in_sync;
++      /* Sync object to signal when the CSD job is done. */
++      __u32 out_sync;
++};
++
+ #if defined(__cplusplus)
+ }
+ #endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0536-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch b/target/linux/brcm2708/patches-4.19/950-0536-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch
deleted file mode 100644 (file)
index 490466d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-From d46285327ba5961c992643d468b2862c70f4c7e5 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 2 May 2019 15:24:04 -0700
-Subject: [PATCH] clk: bcm2835: Allow reparenting leaf clocks while
- they're running.
-
-This falls under the same "we can reprogram glitch-free as long as we
-pause generation" rule as updating the div/frac fields.  This can be
-used for runtime reclocking of V3D to manage power leakage.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/clk/bcm/clk-bcm2835.c | 19 ++++++++++++++++---
- 1 file changed, 16 insertions(+), 3 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1086,8 +1086,10 @@ static int bcm2835_clock_on(struct clk_h
-       return 0;
- }
--static int bcm2835_clock_set_rate(struct clk_hw *hw,
--                                unsigned long rate, unsigned long parent_rate)
-+static int bcm2835_clock_set_rate_and_parent(struct clk_hw *hw,
-+                                           unsigned long rate,
-+                                           unsigned long parent_rate,
-+                                           u8 parent)
- {
-       struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
-       struct bcm2835_cprman *cprman = clock->cprman;
-@@ -1109,6 +1111,11 @@ static int bcm2835_clock_set_rate(struct
-               bcm2835_clock_wait_busy(clock);
-       }
-+      if (parent != 0xff) {
-+              ctl &= ~(CM_SRC_MASK << CM_SRC_SHIFT);
-+              ctl |= parent << CM_SRC_SHIFT;
-+      }
-+
-       ctl &= ~CM_FRAC;
-       ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
-       cprman_write(cprman, data->ctl_reg, ctl);
-@@ -1120,6 +1127,12 @@ static int bcm2835_clock_set_rate(struct
-       return 0;
- }
-+static int bcm2835_clock_set_rate(struct clk_hw *hw,
-+                                unsigned long rate, unsigned long parent_rate)
-+{
-+      return bcm2835_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff);
-+}
-+
- static bool
- bcm2835_clk_is_pllc(struct clk_hw *hw)
- {
-@@ -1303,6 +1316,7 @@ static const struct clk_ops bcm2835_cloc
-       .unprepare = bcm2835_clock_off,
-       .recalc_rate = bcm2835_clock_get_rate,
-       .set_rate = bcm2835_clock_set_rate,
-+      .set_rate_and_parent = bcm2835_clock_set_rate_and_parent,
-       .determine_rate = bcm2835_clock_determine_rate,
-       .set_parent = bcm2835_clock_set_parent,
-       .get_parent = bcm2835_clock_get_parent,
-@@ -1479,7 +1493,6 @@ static struct clk_hw *bcm2835_register_c
-               init.ops = &bcm2835_vpu_clock_clk_ops;
-       } else {
-               init.ops = &bcm2835_clock_clk_ops;
--              init.flags |= CLK_SET_PARENT_GATE;
-               /* If the clock wasn't actually enabled at boot, it's not
-                * critical.
diff --git a/target/linux/brcm2708/patches-4.19/950-0536-drm-v3d-Clock-V3D-down-when-not-in-use.patch b/target/linux/brcm2708/patches-4.19/950-0536-drm-v3d-Clock-V3D-down-when-not-in-use.patch
new file mode 100644 (file)
index 0000000..b4c2c3b
--- /dev/null
@@ -0,0 +1,157 @@
+From 3e6b687bae81bdf5a430ffaa04aa04ee195a866c Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 13:22:53 -0700
+Subject: [PATCH] drm/v3d: Clock V3D down when not in use.
+
+My various attempts at re-enabling runtime PM have failed, so just
+crank the clock down when V3D is idle to reduce power consumption.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 18 +++++++++++++
+ drivers/gpu/drm/v3d/v3d_drv.h |  6 +++++
+ drivers/gpu/drm/v3d/v3d_gem.c | 49 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 73 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -297,6 +297,21 @@ static int v3d_platform_drm_probe(struct
+               }
+       }
++      v3d->clk = devm_clk_get(dev, NULL);
++      if (IS_ERR(v3d->clk)) {
++              if (ret != -EPROBE_DEFER)
++                      dev_err(dev, "Failed to get clock\n");
++              goto dev_free;
++      }
++      v3d->clk_up_rate = clk_get_rate(v3d->clk);
++      /* For downclocking, drop it to the minimum frequency we can get from
++       * the CPRMAN clock generator dividing off our parent.  The divider is
++       * 4 bits, but ask for just higher than that so that rounding doesn't
++       * make cprman reject our rate.
++       */
++      v3d->clk_down_rate =
++              (clk_get_rate(clk_get_parent(v3d->clk)) / (1 << 4)) + 10000;
++
+       if (v3d->ver < 41) {
+               ret = map_regs(v3d, &v3d->gca_regs, "gca");
+               if (ret)
+@@ -331,6 +346,9 @@ static int v3d_platform_drm_probe(struct
+       if (ret)
+               goto irq_disable;
++      ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
++      WARN_ON_ONCE(ret != 0);
++
+       return 0;
+ irq_disable:
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -45,6 +45,12 @@ struct v3d_dev {
+       void __iomem *bridge_regs;
+       void __iomem *gca_regs;
+       struct clk *clk;
++      struct delayed_work clk_down_work;
++      unsigned long clk_up_rate, clk_down_rate;
++      struct mutex clk_lock;
++      u32 clk_refcount;
++      bool clk_up;
++
+       struct reset_control *reset;
+       /* Virtual and DMA addresses of the single shared page table. */
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -3,6 +3,7 @@
+ #include <drm/drmP.h>
+ #include <drm/drm_syncobj.h>
++#include <linux/clk.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
+@@ -17,6 +18,47 @@
+ #include "v3d_trace.h"
+ static void
++v3d_clock_down_work(struct work_struct *work)
++{
++      struct v3d_dev *v3d =
++              container_of(work, struct v3d_dev, clk_down_work.work);
++      int ret;
++
++      ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
++      v3d->clk_up = false;
++      WARN_ON_ONCE(ret != 0);
++}
++
++static void
++v3d_clock_up_get(struct v3d_dev *v3d)
++{
++      mutex_lock(&v3d->clk_lock);
++      if (v3d->clk_refcount++ == 0) {
++              cancel_delayed_work_sync(&v3d->clk_down_work);
++              if (!v3d->clk_up)  {
++                      int ret;
++
++                      ret = clk_set_rate(v3d->clk, v3d->clk_up_rate);
++                      WARN_ON_ONCE(ret != 0);
++                      v3d->clk_up = true;
++              }
++      }
++      mutex_unlock(&v3d->clk_lock);
++}
++
++static void
++v3d_clock_up_put(struct v3d_dev *v3d)
++{
++      mutex_lock(&v3d->clk_lock);
++      if (--v3d->clk_refcount == 0) {
++              schedule_delayed_work(&v3d->clk_down_work,
++                                    msecs_to_jiffies(100));
++      }
++      mutex_unlock(&v3d->clk_lock);
++}
++
++
++static void
+ v3d_init_core(struct v3d_dev *v3d, int core)
+ {
+       /* Set OVRTMUOUT, which means that the texture sampler uniform
+@@ -490,6 +532,7 @@ static void
+ v3d_job_free(struct kref *ref)
+ {
+       struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
++      struct v3d_dev *v3d = job->v3d;
+       int i;
+       for (i = 0; i < job->bo_count; i++) {
+@@ -505,6 +548,8 @@ v3d_job_free(struct kref *ref)
+       dma_fence_put(job->irq_fence);
+       dma_fence_put(job->done_fence);
++      v3d_clock_up_put(v3d);
++
+       kfree(job);
+ }
+@@ -596,6 +641,7 @@ v3d_job_init(struct v3d_dev *v3d, struct
+       if (ret)
+               return ret;
++      v3d_clock_up_get(v3d);
+       kref_init(&job->refcount);
+       return 0;
+@@ -963,6 +1009,9 @@ v3d_gem_init(struct drm_device *dev)
+       mutex_init(&v3d->sched_lock);
+       mutex_init(&v3d->cache_clean_lock);
++      mutex_init(&v3d->clk_lock);
++      INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
++
+       /* Note: We don't allocate address 0.  Various bits of HW
+        * treat 0 as special, such as the occlusion query counters
+        * where 0 means "disabled".
diff --git a/target/linux/brcm2708/patches-4.19/950-0537-drm-v3d-Add-support-for-compute-shader-dispatch.patch b/target/linux/brcm2708/patches-4.19/950-0537-drm-v3d-Add-support-for-compute-shader-dispatch.patch
deleted file mode 100644 (file)
index 6db0729..0000000
+++ /dev/null
@@ -1,897 +0,0 @@
-From 22dbf1420a552d1952d22b92d8c30f8162b026b5 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 16 Apr 2019 15:58:54 -0700
-Subject: [PATCH] drm/v3d: Add support for compute shader dispatch.
-
-The compute shader dispatch interface is pretty simple -- just pass in
-the regs that userspace has passed us, with no CLs to run.  However,
-with no CL to run it means that we need to do manual cache flushing of
-the L2 after the HW execution completes (for SSBO, atomic, and
-image_load_store writes that are the output of compute shaders).
-
-This doesn't yet expose the L2 cache's ability to have a region of the
-address space not write back to memory (which could be used for
-shared_var storage).
-
-So far, the Mesa side has been tested on V3D v4.2 simpenrose (passing
-the ES31 tests), and on the kernel side on 7278 (failing atomic
-compswap tests in a way that doesn't reproduce on simpenrose).
-
-v2: Fix excessive allocation for the clean_job (reported by Dan
-    Carpenter).  Keep refs on jobs until clean_job is finished, to
-    avoid spurious MMU errors if the output BOs are freed by userspace
-    before L2 cleaning is finished.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20190416225856.20264-4-eric@anholt.net
-Acked-by: Rob Clark <robdclark@gmail.com>
----
- drivers/gpu/drm/v3d/v3d_debugfs.c |  22 +++++
- drivers/gpu/drm/v3d/v3d_drv.c     |  10 +-
- drivers/gpu/drm/v3d/v3d_drv.h     |  28 +++++-
- drivers/gpu/drm/v3d/v3d_fence.c   |   2 +
- drivers/gpu/drm/v3d/v3d_gem.c     | 156 +++++++++++++++++++++++++++++-
- drivers/gpu/drm/v3d/v3d_irq.c     |  16 ++-
- drivers/gpu/drm/v3d/v3d_regs.h    |  73 ++++++++++++++
- drivers/gpu/drm/v3d/v3d_sched.c   | 121 +++++++++++++++++++++--
- drivers/gpu/drm/v3d/v3d_trace.h   |  94 ++++++++++++++++++
- include/uapi/drm/v3d_drm.h        |  28 ++++++
- 10 files changed, 531 insertions(+), 19 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -57,6 +57,17 @@ static const struct v3d_reg_def v3d_core
-       REGDEF(V3D_GMP_VIO_ADDR),
- };
-+static const struct v3d_reg_def v3d_csd_reg_defs[] = {
-+      REGDEF(V3D_CSD_STATUS),
-+      REGDEF(V3D_CSD_CURRENT_CFG0),
-+      REGDEF(V3D_CSD_CURRENT_CFG1),
-+      REGDEF(V3D_CSD_CURRENT_CFG2),
-+      REGDEF(V3D_CSD_CURRENT_CFG3),
-+      REGDEF(V3D_CSD_CURRENT_CFG4),
-+      REGDEF(V3D_CSD_CURRENT_CFG5),
-+      REGDEF(V3D_CSD_CURRENT_CFG6),
-+};
-+
- static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
- {
-       struct drm_info_node *node = (struct drm_info_node *)m->private;
-@@ -88,6 +99,17 @@ static int v3d_v3d_debugfs_regs(struct s
-                                  V3D_CORE_READ(core,
-                                                v3d_core_reg_defs[i].reg));
-               }
-+
-+              if (v3d_has_csd(v3d)) {
-+                      for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
-+                              seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
-+                                         core,
-+                                         v3d_csd_reg_defs[i].name,
-+                                         v3d_csd_reg_defs[i].reg,
-+                                         V3D_CORE_READ(core,
-+                                                       v3d_csd_reg_defs[i].reg));
-+                      }
-+              }
-       }
-       return 0;
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -7,9 +7,9 @@
-  * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
-  * For V3D 2.x support, see the VC4 driver.
-  *
-- * Currently only single-core rendering using the binner and renderer,
-- * along with TFU (texture formatting unit) rendering is supported.
-- * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
-+ * The V3D GPU includes a tiled render (composed of a bin and render
-+ * pipelines), the TFU (texture formatting unit), and the CSD (compute
-+ * shader dispatch).
-  */
- #include <linux/clk.h>
-@@ -114,6 +114,9 @@ static int v3d_get_param_ioctl(struct dr
-       case DRM_V3D_PARAM_SUPPORTS_TFU:
-               args->value = 1;
-               return 0;
-+      case DRM_V3D_PARAM_SUPPORTS_CSD:
-+              args->value = v3d_has_csd(v3d);
-+              return 0;
-       default:
-               DRM_DEBUG("Unknown parameter %d\n", args->param);
-               return -EINVAL;
-@@ -183,6 +186,7 @@ static const struct drm_ioctl_desc v3d_d
-       DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
-+      DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CSD, v3d_submit_csd_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
- };
- static const struct vm_operations_struct v3d_vm_ops = {
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -16,9 +16,11 @@ enum v3d_queue {
-       V3D_BIN,
-       V3D_RENDER,
-       V3D_TFU,
-+      V3D_CSD,
-+      V3D_CACHE_CLEAN,
- };
--#define V3D_MAX_QUEUES (V3D_TFU + 1)
-+#define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1)
- struct v3d_queue_state {
-       struct drm_gpu_scheduler sched;
-@@ -70,6 +72,7 @@ struct v3d_dev {
-       struct v3d_bin_job *bin_job;
-       struct v3d_render_job *render_job;
-       struct v3d_tfu_job *tfu_job;
-+      struct v3d_csd_job *csd_job;
-       struct v3d_queue_state queue[V3D_MAX_QUEUES];
-@@ -92,6 +95,12 @@ struct v3d_dev {
-        */
-       struct mutex sched_lock;
-+      /* Lock taken during a cache clean and when initiating an L2
-+       * flush, to keep L2 flushes from interfering with the
-+       * synchronous L2 cleans.
-+       */
-+      struct mutex cache_clean_lock;
-+
-       struct {
-               u32 num_allocated;
-               u32 pages_allocated;
-@@ -104,6 +113,12 @@ to_v3d_dev(struct drm_device *dev)
-       return (struct v3d_dev *)dev->dev_private;
- }
-+static inline bool
-+v3d_has_csd(struct v3d_dev *v3d)
-+{
-+      return v3d->ver >= 41;
-+}
-+
- /* The per-fd struct, which tracks the MMU mappings. */
- struct v3d_file_priv {
-       struct v3d_dev *v3d;
-@@ -237,6 +252,14 @@ struct v3d_tfu_job {
-       struct drm_v3d_submit_tfu args;
- };
-+struct v3d_csd_job {
-+      struct v3d_job base;
-+
-+      u32 timedout_batches;
-+
-+      struct drm_v3d_submit_csd args;
-+};
-+
- /**
-  * _wait_for - magic (register) wait macro
-  *
-@@ -302,11 +325,14 @@ int v3d_submit_cl_ioctl(struct drm_devic
-                       struct drm_file *file_priv);
- int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-+int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
-+                       struct drm_file *file_priv);
- int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
- void v3d_job_put(struct v3d_job *job);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
-+void v3d_clean_caches(struct v3d_dev *v3d);
- /* v3d_irq.c */
- int v3d_irq_init(struct v3d_dev *v3d);
---- a/drivers/gpu/drm/v3d/v3d_fence.c
-+++ b/drivers/gpu/drm/v3d/v3d_fence.c
-@@ -36,6 +36,8 @@ static const char *v3d_fence_get_timelin
-               return "v3d-render";
-       case V3D_TFU:
-               return "v3d-tfu";
-+      case V3D_CSD:
-+              return "v3d-csd";
-       default:
-               return NULL;
-       }
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -162,10 +162,52 @@ v3d_flush_l2t(struct v3d_dev *v3d, int c
-       /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
-        * need to wait for completion before dispatching the job --
-        * L2T accesses will be stalled until the flush has completed.
-+       * However, we do need to make sure we don't try to trigger a
-+       * new flush while the L2_CLEAN queue is trying to
-+       * synchronously clean after a job.
-        */
-+      mutex_lock(&v3d->cache_clean_lock);
-       V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
-                      V3D_L2TCACTL_L2TFLS |
-                      V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
-+      mutex_unlock(&v3d->cache_clean_lock);
-+}
-+
-+/* Cleans texture L1 and L2 cachelines (writing back dirty data).
-+ *
-+ * For cleaning, which happens from the CACHE_CLEAN queue after CSD has
-+ * executed, we need to make sure that the clean is done before
-+ * signaling job completion.  So, we synchronously wait before
-+ * returning, and we make sure that L2 invalidates don't happen in the
-+ * meantime to confuse our are-we-done checks.
-+ */
-+void
-+v3d_clean_caches(struct v3d_dev *v3d)
-+{
-+      struct drm_device *dev = &v3d->drm;
-+      int core = 0;
-+
-+      trace_v3d_cache_clean_begin(dev);
-+
-+      V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
-+      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-+                     V3D_L2TCACTL_L2TFLS), 100)) {
-+              DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
-+      }
-+
-+      mutex_lock(&v3d->cache_clean_lock);
-+      V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
-+                     V3D_L2TCACTL_L2TFLS |
-+                     V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAN, V3D_L2TCACTL_FLM));
-+
-+      if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-+                     V3D_L2TCACTL_L2TFLS), 100)) {
-+              DRM_ERROR("Timeout waiting for L2T clean\n");
-+      }
-+
-+      mutex_unlock(&v3d->cache_clean_lock);
-+
-+      trace_v3d_cache_clean_end(dev);
- }
- /* Invalidates the slice caches.  These are read-only caches. */
-@@ -584,7 +626,8 @@ static void
- v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
-                                        struct v3d_job *job,
-                                        struct ww_acquire_ctx *acquire_ctx,
--                                       u32 out_sync)
-+                                       u32 out_sync,
-+                                       struct dma_fence *done_fence)
- {
-       struct drm_syncobj *sync_out;
-@@ -594,7 +637,7 @@ v3d_attach_fences_and_unlock_reservation
-       /* Update the return sync object for the job */
-       sync_out = drm_syncobj_find(file_priv, out_sync);
-       if (sync_out) {
--              drm_syncobj_replace_fence(sync_out, job->done_fence);
-+              drm_syncobj_replace_fence(sync_out, done_fence);
-               drm_syncobj_put(sync_out);
-       }
- }
-@@ -691,8 +734,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       mutex_unlock(&v3d->sched_lock);
-       v3d_attach_fences_and_unlock_reservation(file_priv,
--                                               &render->base, &acquire_ctx,
--                                               args->out_sync);
-+                                               &render->base,
-+                                               &acquire_ctx,
-+                                               args->out_sync,
-+                                               render->base.done_fence);
-       if (bin)
-               v3d_job_put(&bin->base);
-@@ -785,7 +830,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
-       v3d_attach_fences_and_unlock_reservation(file_priv,
-                                                &job->base, &acquire_ctx,
--                                               args->out_sync);
-+                                               args->out_sync,
-+                                               job->base.done_fence);
-       v3d_job_put(&job->base);
-@@ -801,6 +847,105 @@ fail:
-       return ret;
- }
-+/**
-+ * v3d_submit_csd_ioctl() - Submits a CSD (texture formatting) job to the V3D.
-+ * @dev: DRM device
-+ * @data: ioctl argument
-+ * @file_priv: DRM file for this fd
-+ *
-+ * Userspace provides the register setup for the CSD, which we don't
-+ * need to validate since the CSD is behind the MMU.
-+ */
-+int
-+v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
-+                   struct drm_file *file_priv)
-+{
-+      struct v3d_dev *v3d = to_v3d_dev(dev);
-+      struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
-+      struct drm_v3d_submit_csd *args = data;
-+      struct v3d_csd_job *job;
-+      struct v3d_job *clean_job;
-+      struct ww_acquire_ctx acquire_ctx;
-+      int ret;
-+
-+      trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]);
-+
-+      if (!v3d_has_csd(v3d)) {
-+              DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n");
-+              return -EINVAL;
-+      }
-+
-+      job = kcalloc(1, sizeof(*job), GFP_KERNEL);
-+      if (!job)
-+              return -ENOMEM;
-+
-+      ret = v3d_job_init(v3d, file_priv, &job->base,
-+                         v3d_job_free, args->in_sync);
-+      if (ret) {
-+              kfree(job);
-+              return ret;
-+      }
-+
-+      clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
-+      if (!clean_job) {
-+              v3d_job_put(&job->base);
-+              kfree(job);
-+              return -ENOMEM;
-+      }
-+
-+      ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
-+      if (ret) {
-+              v3d_job_put(&job->base);
-+              kfree(clean_job);
-+              return ret;
-+      }
-+
-+      job->args = *args;
-+
-+      ret = v3d_lookup_bos(dev, file_priv, clean_job,
-+                           args->bo_handles, args->bo_handle_count);
-+      if (ret)
-+              goto fail;
-+
-+      ret = v3d_lock_bo_reservations(clean_job, &acquire_ctx);
-+      if (ret)
-+              goto fail;
-+
-+      mutex_lock(&v3d->sched_lock);
-+      ret = v3d_push_job(v3d_priv, &job->base, V3D_CSD);
-+      if (ret)
-+              goto fail_unreserve;
-+
-+      ret = v3d_add_dep(clean_job, dma_fence_get(job->base.done_fence));
-+      if (ret)
-+              goto fail_unreserve;
-+      ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
-+      if (ret)
-+              goto fail_unreserve;
-+      mutex_unlock(&v3d->sched_lock);
-+
-+      v3d_attach_fences_and_unlock_reservation(file_priv,
-+                                               clean_job,
-+                                               &acquire_ctx,
-+                                               args->out_sync,
-+                                               clean_job->done_fence);
-+
-+      v3d_job_put(&job->base);
-+      v3d_job_put(clean_job);
-+
-+      return 0;
-+
-+fail_unreserve:
-+      mutex_unlock(&v3d->sched_lock);
-+      v3d_unlock_bo_reservations(clean_job->bo, clean_job->bo_count,
-+                                 &acquire_ctx);
-+fail:
-+      v3d_job_put(&job->base);
-+      v3d_job_put(clean_job);
-+
-+      return ret;
-+}
-+
- int
- v3d_gem_init(struct drm_device *dev)
- {
-@@ -816,6 +961,7 @@ v3d_gem_init(struct drm_device *dev)
-       mutex_init(&v3d->bo_lock);
-       mutex_init(&v3d->reset_lock);
-       mutex_init(&v3d->sched_lock);
-+      mutex_init(&v3d->cache_clean_lock);
-       /* Note: We don't allocate address 0.  Various bits of HW
-        * treat 0 as special, such as the occlusion query counters
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -4,9 +4,9 @@
- /**
-  * DOC: Interrupt management for the V3D engine
-  *
-- * When we take a bin, render, or TFU done interrupt, we need to
-- * signal the fence for that job so that the scheduler can queue up
-- * the next one and unblock any waiters.
-+ * When we take a bin, render, TFU done, or CSD done interrupt, we
-+ * need to signal the fence for that job so that the scheduler can
-+ * queue up the next one and unblock any waiters.
-  *
-  * When we take the binner out of memory interrupt, we need to
-  * allocate some new memory and pass it to the binner so that the
-@@ -20,6 +20,7 @@
- #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM |        \
-                            V3D_INT_FLDONE |   \
-                            V3D_INT_FRDONE |   \
-+                           V3D_INT_CSDDONE |  \
-                            V3D_INT_GMPV))
- #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV |     \
-@@ -108,6 +109,15 @@ v3d_irq(int irq, void *arg)
-               dma_fence_signal(&fence->base);
-               status = IRQ_HANDLED;
-       }
-+
-+      if (intsts & V3D_INT_CSDDONE) {
-+              struct v3d_fence *fence =
-+                      to_v3d_fence(v3d->csd_job->base.irq_fence);
-+
-+              trace_v3d_csd_irq(&v3d->drm, fence->seqno);
-+              dma_fence_signal(&fence->base);
-+              status = IRQ_HANDLED;
-+      }
-       /* We shouldn't be triggering these if we have GMP in
-        * always-allowed mode.
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -238,8 +238,11 @@
- #define V3D_CTL_L2TCACTL                               0x00030
- # define V3D_L2TCACTL_TMUWCF                           BIT(8)
- # define V3D_L2TCACTL_L2T_NO_WM                        BIT(4)
-+/* Invalidates cache lines. */
- # define V3D_L2TCACTL_FLM_FLUSH                        0
-+/* Removes cachelines without writing dirty lines back. */
- # define V3D_L2TCACTL_FLM_CLEAR                        1
-+/* Writes out dirty cachelines and marks them clean, but doesn't invalidate. */
- # define V3D_L2TCACTL_FLM_CLEAN                        2
- # define V3D_L2TCACTL_FLM_MASK                         V3D_MASK(2, 1)
- # define V3D_L2TCACTL_FLM_SHIFT                        1
-@@ -255,6 +258,8 @@
- #define V3D_CTL_INT_MSK_CLR                            0x00064
- # define V3D_INT_QPU_MASK                              V3D_MASK(27, 16)
- # define V3D_INT_QPU_SHIFT                             16
-+# define V3D_INT_CSDDONE                               BIT(7)
-+# define V3D_INT_PCTR                                  BIT(6)
- # define V3D_INT_GMPV                                  BIT(5)
- # define V3D_INT_TRFB                                  BIT(4)
- # define V3D_INT_SPILLUSE                              BIT(3)
-@@ -374,4 +379,72 @@
- #define V3D_GMP_PRESERVE_LOAD                          0x00818
- #define V3D_GMP_VALID_LINES                            0x00820
-+#define V3D_CSD_STATUS                                 0x00900
-+# define V3D_CSD_STATUS_NUM_COMPLETED_MASK             V3D_MASK(11, 4)
-+# define V3D_CSD_STATUS_NUM_COMPLETED_SHIFT            4
-+# define V3D_CSD_STATUS_NUM_ACTIVE_MASK                V3D_MASK(3, 2)
-+# define V3D_CSD_STATUS_NUM_ACTIVE_SHIFT               2
-+# define V3D_CSD_STATUS_HAVE_CURRENT_DISPATCH          BIT(1)
-+# define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH           BIT(0)
-+
-+#define V3D_CSD_QUEUED_CFG0                            0x00904
-+# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK            V3D_MASK(31, 16)
-+# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT           16
-+# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_MASK          V3D_MASK(15, 0)
-+# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_SHIFT         0
-+
-+#define V3D_CSD_QUEUED_CFG1                            0x00908
-+# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_MASK            V3D_MASK(31, 16)
-+# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_SHIFT           16
-+# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_MASK          V3D_MASK(15, 0)
-+# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_SHIFT         0
-+
-+#define V3D_CSD_QUEUED_CFG2                            0x0090c
-+# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_MASK            V3D_MASK(31, 16)
-+# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_SHIFT           16
-+# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_MASK          V3D_MASK(15, 0)
-+# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_SHIFT         0
-+
-+#define V3D_CSD_QUEUED_CFG3                            0x00910
-+# define V3D_CSD_QUEUED_CFG3_OVERLAP_WITH_PREV         BIT(26)
-+# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_MASK            V3D_MASK(25, 20)
-+# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_SHIFT           20
-+# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_MASK    V3D_MASK(19, 12)
-+# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_SHIFT   12
-+# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_MASK           V3D_MASK(11, 8)
-+# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_SHIFT          8
-+# define V3D_CSD_QUEUED_CFG3_WG_SIZE_MASK              V3D_MASK(7, 0)
-+# define V3D_CSD_QUEUED_CFG3_WG_SIZE_SHIFT             0
-+
-+/* Number of batches, minus 1 */
-+#define V3D_CSD_QUEUED_CFG4                            0x00914
-+
-+/* Shader address, pnan, singleseg, threading, like a shader record. */
-+#define V3D_CSD_QUEUED_CFG5                            0x00918
-+
-+/* Uniforms address (4 byte aligned) */
-+#define V3D_CSD_QUEUED_CFG6                            0x0091c
-+
-+#define V3D_CSD_CURRENT_CFG0                          0x00920
-+#define V3D_CSD_CURRENT_CFG1                          0x00924
-+#define V3D_CSD_CURRENT_CFG2                          0x00928
-+#define V3D_CSD_CURRENT_CFG3                          0x0092c
-+#define V3D_CSD_CURRENT_CFG4                          0x00930
-+#define V3D_CSD_CURRENT_CFG5                          0x00934
-+#define V3D_CSD_CURRENT_CFG6                          0x00938
-+
-+#define V3D_CSD_CURRENT_ID0                            0x0093c
-+# define V3D_CSD_CURRENT_ID0_WG_X_MASK                 V3D_MASK(31, 16)
-+# define V3D_CSD_CURRENT_ID0_WG_X_SHIFT                16
-+# define V3D_CSD_CURRENT_ID0_WG_IN_SG_MASK             V3D_MASK(11, 8)
-+# define V3D_CSD_CURRENT_ID0_WG_IN_SG_SHIFT            8
-+# define V3D_CSD_CURRENT_ID0_L_IDX_MASK                V3D_MASK(7, 0)
-+# define V3D_CSD_CURRENT_ID0_L_IDX_SHIFT               0
-+
-+#define V3D_CSD_CURRENT_ID1                            0x00940
-+# define V3D_CSD_CURRENT_ID0_WG_Z_MASK                 V3D_MASK(31, 16)
-+# define V3D_CSD_CURRENT_ID0_WG_Z_SHIFT                16
-+# define V3D_CSD_CURRENT_ID0_WG_Y_MASK                 V3D_MASK(15, 0)
-+# define V3D_CSD_CURRENT_ID0_WG_Y_SHIFT                0
-+
- #endif /* V3D_REGS_H */
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -48,6 +48,12 @@ to_tfu_job(struct drm_sched_job *sched_j
-       return container_of(sched_job, struct v3d_tfu_job, base.base);
- }
-+static struct v3d_csd_job *
-+to_csd_job(struct drm_sched_job *sched_job)
-+{
-+      return container_of(sched_job, struct v3d_csd_job, base.base);
-+}
-+
- static void
- v3d_job_free(struct drm_sched_job *sched_job)
- {
-@@ -205,6 +211,48 @@ v3d_tfu_job_run(struct drm_sched_job *sc
-       return fence;
- }
-+static struct dma_fence *
-+v3d_csd_job_run(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_csd_job *job = to_csd_job(sched_job);
-+      struct v3d_dev *v3d = job->base.v3d;
-+      struct drm_device *dev = &v3d->drm;
-+      struct dma_fence *fence;
-+      int i;
-+
-+      v3d->csd_job = job;
-+
-+      v3d_invalidate_caches(v3d);
-+
-+      fence = v3d_fence_create(v3d, V3D_CSD);
-+      if (IS_ERR(fence))
-+              return NULL;
-+
-+      if (job->base.irq_fence)
-+              dma_fence_put(job->base.irq_fence);
-+      job->base.irq_fence = dma_fence_get(fence);
-+
-+      trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
-+
-+      for (i = 1; i <= 6; i++)
-+              V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]);
-+      /* CFG0 write kicks off the job. */
-+      V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0, job->args.cfg[0]);
-+
-+      return fence;
-+}
-+
-+static struct dma_fence *
-+v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_job *job = to_v3d_job(sched_job);
-+      struct v3d_dev *v3d = job->v3d;
-+
-+      v3d_clean_caches(v3d);
-+
-+      return NULL;
-+}
-+
- static void
- v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
- {
-@@ -277,13 +325,31 @@ v3d_render_job_timedout(struct drm_sched
- }
- static void
--v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
-+v3d_generic_job_timedout(struct drm_sched_job *sched_job)
- {
-       struct v3d_job *job = to_v3d_job(sched_job);
-       v3d_gpu_reset_for_timeout(job->v3d, sched_job);
- }
-+static void
-+v3d_csd_job_timedout(struct drm_sched_job *sched_job)
-+{
-+      struct v3d_csd_job *job = to_csd_job(sched_job);
-+      struct v3d_dev *v3d = job->base.v3d;
-+      u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4);
-+
-+      /* If we've made progress, skip reset and let the timer get
-+       * rearmed.
-+       */
-+      if (job->timedout_batches != batches) {
-+              job->timedout_batches = batches;
-+              return;
-+      }
-+
-+      v3d_gpu_reset_for_timeout(v3d, sched_job);
-+}
-+
- static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
-       .dependency = v3d_job_dependency,
-       .run_job = v3d_bin_job_run,
-@@ -301,10 +367,24 @@ static const struct drm_sched_backend_op
- static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
-       .dependency = v3d_job_dependency,
-       .run_job = v3d_tfu_job_run,
--      .timedout_job = v3d_tfu_job_timedout,
-+      .timedout_job = v3d_generic_job_timedout,
-       .free_job = v3d_job_free,
- };
-+static const struct drm_sched_backend_ops v3d_csd_sched_ops = {
-+      .dependency = v3d_job_dependency,
-+      .run_job = v3d_csd_job_run,
-+      .timedout_job = v3d_csd_job_timedout,
-+      .free_job = v3d_job_free
-+};
-+
-+static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
-+      .dependency = v3d_job_dependency,
-+      .run_job = v3d_cache_clean_job_run,
-+      .timedout_job = v3d_generic_job_timedout,
-+      .free_job = v3d_job_free
-+};
-+
- int
- v3d_sched_init(struct v3d_dev *v3d)
- {
-@@ -331,7 +411,7 @@ v3d_sched_init(struct v3d_dev *v3d)
-       if (ret) {
-               dev_err(v3d->dev, "Failed to create render scheduler: %d.",
-                       ret);
--              drm_sched_fini(&v3d->queue[V3D_BIN].sched);
-+              v3d_sched_fini(v3d);
-               return ret;
-       }
-@@ -343,11 +423,36 @@ v3d_sched_init(struct v3d_dev *v3d)
-       if (ret) {
-               dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
-                       ret);
--              drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
--              drm_sched_fini(&v3d->queue[V3D_BIN].sched);
-+              v3d_sched_fini(v3d);
-               return ret;
-       }
-+      if (v3d_has_csd(v3d)) {
-+              ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
-+                                   &v3d_csd_sched_ops,
-+                                   hw_jobs_limit, job_hang_limit,
-+                                   msecs_to_jiffies(hang_limit_ms),
-+                                   "v3d_csd");
-+              if (ret) {
-+                      dev_err(v3d->dev, "Failed to create CSD scheduler: %d.",
-+                              ret);
-+                      v3d_sched_fini(v3d);
-+                      return ret;
-+              }
-+
-+              ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
-+                                   &v3d_cache_clean_sched_ops,
-+                                   hw_jobs_limit, job_hang_limit,
-+                                   msecs_to_jiffies(hang_limit_ms),
-+                                   "v3d_cache_clean");
-+              if (ret) {
-+                      dev_err(v3d->dev, "Failed to create CACHE_CLEAN scheduler: %d.",
-+                              ret);
-+                      v3d_sched_fini(v3d);
-+                      return ret;
-+              }
-+      }
-+
-       return 0;
- }
-@@ -356,6 +461,8 @@ v3d_sched_fini(struct v3d_dev *v3d)
- {
-       enum v3d_queue q;
--      for (q = 0; q < V3D_MAX_QUEUES; q++)
--              drm_sched_fini(&v3d->queue[q].sched);
-+      for (q = 0; q < V3D_MAX_QUEUES; q++) {
-+              if (v3d->queue[q].sched.ops)
-+                      drm_sched_fini(&v3d->queue[q].sched);
-+      }
- }
---- a/drivers/gpu/drm/v3d/v3d_trace.h
-+++ b/drivers/gpu/drm/v3d/v3d_trace.h
-@@ -124,6 +124,26 @@ TRACE_EVENT(v3d_tfu_irq,
-                     __entry->seqno)
- );
-+TRACE_EVENT(v3d_csd_irq,
-+          TP_PROTO(struct drm_device *dev,
-+                   uint64_t seqno),
-+          TP_ARGS(dev, seqno),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u64, seqno)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->seqno = seqno;
-+                         ),
-+
-+          TP_printk("dev=%u, seqno=%llu",
-+                    __entry->dev,
-+                    __entry->seqno)
-+);
-+
- TRACE_EVENT(v3d_submit_tfu_ioctl,
-           TP_PROTO(struct drm_device *dev, u32 iia),
-           TP_ARGS(dev, iia),
-@@ -163,6 +183,80 @@ TRACE_EVENT(v3d_submit_tfu,
-                     __entry->seqno)
- );
-+TRACE_EVENT(v3d_submit_csd_ioctl,
-+          TP_PROTO(struct drm_device *dev, u32 cfg5, u32 cfg6),
-+          TP_ARGS(dev, cfg5, cfg6),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u32, cfg5)
-+                           __field(u32, cfg6)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->cfg5 = cfg5;
-+                         __entry->cfg6 = cfg6;
-+                         ),
-+
-+          TP_printk("dev=%u, CFG5 0x%08x, CFG6 0x%08x",
-+                    __entry->dev,
-+                    __entry->cfg5,
-+                    __entry->cfg6)
-+);
-+
-+TRACE_EVENT(v3d_submit_csd,
-+          TP_PROTO(struct drm_device *dev,
-+                   uint64_t seqno),
-+          TP_ARGS(dev, seqno),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           __field(u64, seqno)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         __entry->seqno = seqno;
-+                         ),
-+
-+          TP_printk("dev=%u, seqno=%llu",
-+                    __entry->dev,
-+                    __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_cache_clean_begin,
-+          TP_PROTO(struct drm_device *dev),
-+          TP_ARGS(dev),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         ),
-+
-+          TP_printk("dev=%u",
-+                    __entry->dev)
-+);
-+
-+TRACE_EVENT(v3d_cache_clean_end,
-+          TP_PROTO(struct drm_device *dev),
-+          TP_ARGS(dev),
-+
-+          TP_STRUCT__entry(
-+                           __field(u32, dev)
-+                           ),
-+
-+          TP_fast_assign(
-+                         __entry->dev = dev->primary->index;
-+                         ),
-+
-+          TP_printk("dev=%u",
-+                    __entry->dev)
-+);
-+
- TRACE_EVENT(v3d_reset_begin,
-           TP_PROTO(struct drm_device *dev),
-           TP_ARGS(dev),
---- a/include/uapi/drm/v3d_drm.h
-+++ b/include/uapi/drm/v3d_drm.h
-@@ -37,6 +37,7 @@ extern "C" {
- #define DRM_V3D_GET_PARAM                         0x04
- #define DRM_V3D_GET_BO_OFFSET                     0x05
- #define DRM_V3D_SUBMIT_TFU                        0x06
-+#define DRM_V3D_SUBMIT_CSD                        0x07
- #define DRM_IOCTL_V3D_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
- #define DRM_IOCTL_V3D_WAIT_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
-@@ -45,6 +46,7 @@ extern "C" {
- #define DRM_IOCTL_V3D_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
- #define DRM_IOCTL_V3D_GET_BO_OFFSET       DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
- #define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
-+#define DRM_IOCTL_V3D_SUBMIT_CSD          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
- /**
-  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
-@@ -172,6 +174,7 @@ enum drm_v3d_param {
-       DRM_V3D_PARAM_V3D_CORE0_IDENT1,
-       DRM_V3D_PARAM_V3D_CORE0_IDENT2,
-       DRM_V3D_PARAM_SUPPORTS_TFU,
-+      DRM_V3D_PARAM_SUPPORTS_CSD,
- };
- struct drm_v3d_get_param {
-@@ -212,6 +215,31 @@ struct drm_v3d_submit_tfu {
-       __u32 out_sync;
- };
-+/* Submits a compute shader for dispatch.  This job will block on any
-+ * previous compute shaders submitted on this fd, and any other
-+ * synchronization must be performed with in_sync/out_sync.
-+ */
-+struct drm_v3d_submit_csd {
-+      __u32 cfg[7];
-+      __u32 coef[4];
-+
-+      /* Pointer to a u32 array of the BOs that are referenced by the job.
-+       */
-+      __u64 bo_handles;
-+
-+      /* Number of BO handles passed in (size is that times 4). */
-+      __u32 bo_handle_count;
-+
-+      /* sync object to block on before running the CSD job.  Each
-+       * CSD job will execute in the order submitted to its FD.
-+       * Synchronization against rendering/TFU jobs or CSD from
-+       * other fds requires using sync objects.
-+       */
-+      __u32 in_sync;
-+      /* Sync object to signal when the CSD job is done. */
-+      __u32 out_sync;
-+};
-+
- #if defined(__cplusplus)
- }
- #endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0537-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch b/target/linux/brcm2708/patches-4.19/950-0537-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch
new file mode 100644 (file)
index 0000000..db3f195
--- /dev/null
@@ -0,0 +1,55 @@
+From 3cd15f787b391db5224a27715fe9dc6fc8559bee Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 3 May 2019 13:58:03 +0100
+Subject: [PATCH] drm: vc4-firmware-kms: Remove incorrect overscan
+ support.
+
+The overscan support was required for the old mailbox API
+in order to match up the cursor and frame buffer planes.
+With the newer API directly talking to dispmanx there is no
+difference, therefore FKMS does not need to make any
+adjustments.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 ---------------
+ 1 file changed, 15 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -232,7 +232,6 @@ struct vc4_crtc {
+       void __iomem *regs;
+       struct drm_pending_vblank_event *event;
+-      u32 overscan[4];
+       bool vblank_enabled;
+       u32 display_number;
+       u32 display_type;
+@@ -468,11 +467,6 @@ static void vc4_plane_atomic_update(stru
+               break;
+       }
+-      if (vc4_crtc) {
+-              mb->plane.dst_x += vc4_crtc->overscan[0];
+-              mb->plane.dst_y += vc4_crtc->overscan[1];
+-      }
+-
+       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
+                        plane->base.id, plane->name,
+                        mb->plane.width,
+@@ -1228,15 +1222,6 @@ static int vc4_fkms_create_screen(struct
+               goto err_destroy_encoder;
+       }
+-      ret = rpi_firmware_property(vc4->firmware,
+-                                  RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
+-                                  &vc4_crtc->overscan,
+-                                  sizeof(vc4_crtc->overscan));
+-      if (ret) {
+-              DRM_ERROR("Failed to get overscan state: 0x%08x\n", vc4_crtc->overscan[0]);
+-              memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
+-      }
+-
+       *ret_crtc = vc4_crtc;
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0538-drm-v3d-Clock-V3D-down-when-not-in-use.patch b/target/linux/brcm2708/patches-4.19/950-0538-drm-v3d-Clock-V3D-down-when-not-in-use.patch
deleted file mode 100644 (file)
index b4c2c3b..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-From 3e6b687bae81bdf5a430ffaa04aa04ee195a866c Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 2 May 2019 13:22:53 -0700
-Subject: [PATCH] drm/v3d: Clock V3D down when not in use.
-
-My various attempts at re-enabling runtime PM have failed, so just
-crank the clock down when V3D is idle to reduce power consumption.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 18 +++++++++++++
- drivers/gpu/drm/v3d/v3d_drv.h |  6 +++++
- drivers/gpu/drm/v3d/v3d_gem.c | 49 +++++++++++++++++++++++++++++++++++
- 3 files changed, 73 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -297,6 +297,21 @@ static int v3d_platform_drm_probe(struct
-               }
-       }
-+      v3d->clk = devm_clk_get(dev, NULL);
-+      if (IS_ERR(v3d->clk)) {
-+              if (ret != -EPROBE_DEFER)
-+                      dev_err(dev, "Failed to get clock\n");
-+              goto dev_free;
-+      }
-+      v3d->clk_up_rate = clk_get_rate(v3d->clk);
-+      /* For downclocking, drop it to the minimum frequency we can get from
-+       * the CPRMAN clock generator dividing off our parent.  The divider is
-+       * 4 bits, but ask for just higher than that so that rounding doesn't
-+       * make cprman reject our rate.
-+       */
-+      v3d->clk_down_rate =
-+              (clk_get_rate(clk_get_parent(v3d->clk)) / (1 << 4)) + 10000;
-+
-       if (v3d->ver < 41) {
-               ret = map_regs(v3d, &v3d->gca_regs, "gca");
-               if (ret)
-@@ -331,6 +346,9 @@ static int v3d_platform_drm_probe(struct
-       if (ret)
-               goto irq_disable;
-+      ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
-+      WARN_ON_ONCE(ret != 0);
-+
-       return 0;
- irq_disable:
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -45,6 +45,12 @@ struct v3d_dev {
-       void __iomem *bridge_regs;
-       void __iomem *gca_regs;
-       struct clk *clk;
-+      struct delayed_work clk_down_work;
-+      unsigned long clk_up_rate, clk_down_rate;
-+      struct mutex clk_lock;
-+      u32 clk_refcount;
-+      bool clk_up;
-+
-       struct reset_control *reset;
-       /* Virtual and DMA addresses of the single shared page table. */
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -3,6 +3,7 @@
- #include <drm/drmP.h>
- #include <drm/drm_syncobj.h>
-+#include <linux/clk.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
-@@ -17,6 +18,47 @@
- #include "v3d_trace.h"
- static void
-+v3d_clock_down_work(struct work_struct *work)
-+{
-+      struct v3d_dev *v3d =
-+              container_of(work, struct v3d_dev, clk_down_work.work);
-+      int ret;
-+
-+      ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
-+      v3d->clk_up = false;
-+      WARN_ON_ONCE(ret != 0);
-+}
-+
-+static void
-+v3d_clock_up_get(struct v3d_dev *v3d)
-+{
-+      mutex_lock(&v3d->clk_lock);
-+      if (v3d->clk_refcount++ == 0) {
-+              cancel_delayed_work_sync(&v3d->clk_down_work);
-+              if (!v3d->clk_up)  {
-+                      int ret;
-+
-+                      ret = clk_set_rate(v3d->clk, v3d->clk_up_rate);
-+                      WARN_ON_ONCE(ret != 0);
-+                      v3d->clk_up = true;
-+              }
-+      }
-+      mutex_unlock(&v3d->clk_lock);
-+}
-+
-+static void
-+v3d_clock_up_put(struct v3d_dev *v3d)
-+{
-+      mutex_lock(&v3d->clk_lock);
-+      if (--v3d->clk_refcount == 0) {
-+              schedule_delayed_work(&v3d->clk_down_work,
-+                                    msecs_to_jiffies(100));
-+      }
-+      mutex_unlock(&v3d->clk_lock);
-+}
-+
-+
-+static void
- v3d_init_core(struct v3d_dev *v3d, int core)
- {
-       /* Set OVRTMUOUT, which means that the texture sampler uniform
-@@ -490,6 +532,7 @@ static void
- v3d_job_free(struct kref *ref)
- {
-       struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
-+      struct v3d_dev *v3d = job->v3d;
-       int i;
-       for (i = 0; i < job->bo_count; i++) {
-@@ -505,6 +548,8 @@ v3d_job_free(struct kref *ref)
-       dma_fence_put(job->irq_fence);
-       dma_fence_put(job->done_fence);
-+      v3d_clock_up_put(v3d);
-+
-       kfree(job);
- }
-@@ -596,6 +641,7 @@ v3d_job_init(struct v3d_dev *v3d, struct
-       if (ret)
-               return ret;
-+      v3d_clock_up_get(v3d);
-       kref_init(&job->refcount);
-       return 0;
-@@ -963,6 +1009,9 @@ v3d_gem_init(struct drm_device *dev)
-       mutex_init(&v3d->sched_lock);
-       mutex_init(&v3d->cache_clean_lock);
-+      mutex_init(&v3d->clk_lock);
-+      INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
-+
-       /* Note: We don't allocate address 0.  Various bits of HW
-        * treat 0 as special, such as the occlusion query counters
-        * where 0 means "disabled".
diff --git a/target/linux/brcm2708/patches-4.19/950-0538-drm-vc4-Log-flags-in-fkms-mode-set.patch b/target/linux/brcm2708/patches-4.19/950-0538-drm-vc4-Log-flags-in-fkms-mode-set.patch
new file mode 100644 (file)
index 0000000..59f6f79
--- /dev/null
@@ -0,0 +1,31 @@
+From 07288c2bd9733dc9317c5f9b02980a59a05ce3af Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 7 May 2019 12:13:34 +0100
+Subject: [PATCH] drm: vc4: Log flags in fkms mode set
+
+The flags contain info such as limited/full range RGB, aspect
+ratio, and a fwe other useful things.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -685,12 +685,13 @@ static void vc4_crtc_mode_set_nofb(struc
+               return;
+       }
+-      DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
++      DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u, flags 0x%04x\n",
+                     vc4_crtc->display_number, mode->name, mode->clock,
+                     mode->hdisplay, mode->hsync_start, mode->hsync_end,
+                     mode->htotal, mode->hskew, mode->vdisplay,
+                     mode->vsync_start, mode->vsync_end, mode->vtotal,
+-                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
++                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
++                    mode->flags);
+       mb.timings.display = vc4_crtc->display_number;
+       mb.timings.video_id_code = frame.avi.video_code;
diff --git a/target/linux/brcm2708/patches-4.19/950-0539-drm-vc4-firmware-kms-Fix-DSI-display-support.patch b/target/linux/brcm2708/patches-4.19/950-0539-drm-vc4-firmware-kms-Fix-DSI-display-support.patch
new file mode 100644 (file)
index 0000000..b45df39
--- /dev/null
@@ -0,0 +1,25 @@
+From d66b1d056d07b27803ba0756ecdb0d4419bcaaa2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 16 May 2019 17:49:42 +0100
+Subject: [PATCH] drm: vc4-firmware-kms: Fix DSI display support
+
+The mode was incorrectly listed as interlaced, which was then
+rejected.
+Correct this and FKMS works with the DSI display.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1003,7 +1003,7 @@ static const struct drm_display_mode lcd
+                25979400 / 1000,
+                800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
+                480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
+-               DRM_MODE_FLAG_INTERLACE)
++               0)
+ };
+ static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
diff --git a/target/linux/brcm2708/patches-4.19/950-0539-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch b/target/linux/brcm2708/patches-4.19/950-0539-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch
deleted file mode 100644 (file)
index db3f195..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From 3cd15f787b391db5224a27715fe9dc6fc8559bee Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 3 May 2019 13:58:03 +0100
-Subject: [PATCH] drm: vc4-firmware-kms: Remove incorrect overscan
- support.
-
-The overscan support was required for the old mailbox API
-in order to match up the cursor and frame buffer planes.
-With the newer API directly talking to dispmanx there is no
-difference, therefore FKMS does not need to make any
-adjustments.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 ---------------
- 1 file changed, 15 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -232,7 +232,6 @@ struct vc4_crtc {
-       void __iomem *regs;
-       struct drm_pending_vblank_event *event;
--      u32 overscan[4];
-       bool vblank_enabled;
-       u32 display_number;
-       u32 display_type;
-@@ -468,11 +467,6 @@ static void vc4_plane_atomic_update(stru
-               break;
-       }
--      if (vc4_crtc) {
--              mb->plane.dst_x += vc4_crtc->overscan[0];
--              mb->plane.dst_y += vc4_crtc->overscan[1];
--      }
--
-       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
-                        plane->base.id, plane->name,
-                        mb->plane.width,
-@@ -1228,15 +1222,6 @@ static int vc4_fkms_create_screen(struct
-               goto err_destroy_encoder;
-       }
--      ret = rpi_firmware_property(vc4->firmware,
--                                  RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
--                                  &vc4_crtc->overscan,
--                                  sizeof(vc4_crtc->overscan));
--      if (ret) {
--              DRM_ERROR("Failed to get overscan state: 0x%08x\n", vc4_crtc->overscan[0]);
--              memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
--      }
--
-       *ret_crtc = vc4_crtc;
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0540-drm-vc4-Log-flags-in-fkms-mode-set.patch b/target/linux/brcm2708/patches-4.19/950-0540-drm-vc4-Log-flags-in-fkms-mode-set.patch
deleted file mode 100644 (file)
index 59f6f79..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 07288c2bd9733dc9317c5f9b02980a59a05ce3af Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 7 May 2019 12:13:34 +0100
-Subject: [PATCH] drm: vc4: Log flags in fkms mode set
-
-The flags contain info such as limited/full range RGB, aspect
-ratio, and a fwe other useful things.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -685,12 +685,13 @@ static void vc4_crtc_mode_set_nofb(struc
-               return;
-       }
--      DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
-+      DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u, flags 0x%04x\n",
-                     vc4_crtc->display_number, mode->name, mode->clock,
-                     mode->hdisplay, mode->hsync_start, mode->hsync_end,
-                     mode->htotal, mode->hskew, mode->vdisplay,
-                     mode->vsync_start, mode->vsync_end, mode->vtotal,
--                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
-+                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
-+                    mode->flags);
-       mb.timings.display = vc4_crtc->display_number;
-       mb.timings.video_id_code = frame.avi.video_code;
diff --git a/target/linux/brcm2708/patches-4.19/950-0540-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch b/target/linux/brcm2708/patches-4.19/950-0540-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch
new file mode 100644 (file)
index 0000000..1a27777
--- /dev/null
@@ -0,0 +1,120 @@
+From b4ffa49d762a4af832d0d8660caf59722c0ff75a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 21 May 2019 11:50:00 +0100
+Subject: [PATCH] drm: vc4: Probe DPI/DSI timings from the firmware
+
+For DPI and DSI displays query the firmware as to the configuration
+and add it as the only mode for DRM.
+
+In theory we can add plumbing for setting the DPI/DSI mode from
+KMS, but this is not being added at present as the support frameworks
+aren't present in the firmware.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 60 ++++++++++++++++++----
+ include/soc/bcm2835/raspberrypi-firmware.h |  1 +
+ 2 files changed, 51 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -280,7 +280,7 @@ static u32 vc4_get_display_type(u32 disp
+               /* The firmware display (DispmanX) IDs map to specific types in
+                * a fixed manner.
+                */
+-              DRM_MODE_ENCODER_DSI,   /* MAIN_LCD */
++              DRM_MODE_ENCODER_DSI,   /* MAIN_LCD - DSI or DPI */
+               DRM_MODE_ENCODER_DSI,   /* AUX_LCD */
+               DRM_MODE_ENCODER_TMDS,  /* HDMI0 */
+               DRM_MODE_ENCODER_TVDAC, /* VEC */
+@@ -362,7 +362,6 @@ static void vc4_plane_atomic_update(stru
+                                       vc4_get_vc_image_fmt(drm_fmt->format);
+       struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+       struct mailbox_set_plane *mb = &vc4_plane->mb;
+-      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+       int num_planes = fb->format->num_planes;
+       struct drm_display_mode *mode = &state->crtc->mode;
+       unsigned int rotation = SUPPORTED_ROTATIONS;
+@@ -997,7 +996,9 @@ static int vc4_fkms_connector_get_modes(
+       return ret;
+ }
+-/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
++/* This is the DSI panel resolution. Use this as a default should the firmware
++ * not respond to our request for the timings.
++ */
+ static const struct drm_display_mode lcd_mode = {
+       DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+                25979400 / 1000,
+@@ -1008,15 +1009,54 @@ static const struct drm_display_mode lcd
+ static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
+ {
+-      //struct vc4_fkms_connector *fkms_connector =
+-      //                              to_vc4_fkms_connector(connector);
+-      //struct drm_encoder *encoder = fkms_connector->encoder;
+-      //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
++      struct vc4_fkms_connector *fkms_connector =
++                                      to_vc4_fkms_connector(connector);
++      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
+       struct drm_display_mode *mode;
+-      //int ret = 0;
++      struct mailbox_set_mode mb = {
++              .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
++                        sizeof(struct set_timings), 0},
++              .timings = { .display = fkms_connector->display_number },
++      };
++      struct drm_display_mode fw_mode;
++      int ret = 0;
++
++      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
++      if (!ret) {
++              /* Equivalent to DRM_MODE macro. */
++              memset(&fw_mode, 0, sizeof(fw_mode));
++              strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
++              fw_mode.status = 0;
++              fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
++              fw_mode.clock = mb.timings.clock;
++              fw_mode.hdisplay = mb.timings.hdisplay;
++              fw_mode.hsync_start = mb.timings.hsync_start;
++              fw_mode.hsync_end = mb.timings.hsync_end;
++              fw_mode.htotal = mb.timings.htotal;
++              fw_mode.hskew = 0;
++              fw_mode.vdisplay = mb.timings.vdisplay;
++              fw_mode.vsync_start = mb.timings.vsync_start;
++              fw_mode.vsync_end = mb.timings.vsync_end;
++              fw_mode.vtotal = mb.timings.vtotal;
++              fw_mode.vscan = mb.timings.vscan;
++              if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
++                      fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
++              else
++                      fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
++              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
++                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
++              else
++                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
++
++              fw_mode.base.type = DRM_MODE_OBJECT_MODE;
++
++              mode = drm_mode_duplicate(connector->dev,
++                                        &fw_mode);
++      } else {
++              mode = drm_mode_duplicate(connector->dev,
++                                        &lcd_mode);
++      }
+-      mode = drm_mode_duplicate(connector->dev,
+-                                &lcd_mode);
+       if (!mode) {
+               DRM_ERROR("Failed to create a new display mode\n");
+               return -ENOMEM;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -151,6 +151,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
+       RPI_FIRMWARE_SET_PLANE =                              0x00048015,
++      RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
+       RPI_FIRMWARE_SET_TIMING =                             0x00048017,
+       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
diff --git a/target/linux/brcm2708/patches-4.19/950-0541-drm-vc4-firmware-kms-Fix-DSI-display-support.patch b/target/linux/brcm2708/patches-4.19/950-0541-drm-vc4-firmware-kms-Fix-DSI-display-support.patch
deleted file mode 100644 (file)
index b45df39..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From d66b1d056d07b27803ba0756ecdb0d4419bcaaa2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 16 May 2019 17:49:42 +0100
-Subject: [PATCH] drm: vc4-firmware-kms: Fix DSI display support
-
-The mode was incorrectly listed as interlaced, which was then
-rejected.
-Correct this and FKMS works with the DSI display.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1003,7 +1003,7 @@ static const struct drm_display_mode lcd
-                25979400 / 1000,
-                800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
-                480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
--               DRM_MODE_FLAG_INTERLACE)
-+               0)
- };
- static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
diff --git a/target/linux/brcm2708/patches-4.19/950-0541-drm-vc4-handle-the-case-where-there-are-no-available.patch b/target/linux/brcm2708/patches-4.19/950-0541-drm-vc4-handle-the-case-where-there-are-no-available.patch
new file mode 100644 (file)
index 0000000..346d32e
--- /dev/null
@@ -0,0 +1,67 @@
+From dd99aa50a3ea7f7fe1ddfd59b1a2e969c744b8a0 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 28 May 2019 13:56:06 +0100
+Subject: [PATCH] drm: vc4: handle the case where there are no
+ available displays
+
+It's reasonable for the firmware to return zero as the number of
+attached displays. Handle this case as otherwise drm thinks that
+the DSI panel is attached, which is nonsense.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++-----------
+ 1 file changed, 18 insertions(+), 14 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1309,13 +1309,13 @@ static int vc4_fkms_bind(struct device *
+                                   RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
+                                   &num_displays, sizeof(u32));
+-      /* If we fail to get the number of displays, or it returns 0, then
++      /* If we fail to get the number of displays, then
+        * assume old firmware that doesn't have the mailbox call, so just
+        * set one display
+        */
+-      if (ret || num_displays == 0) {
++      if (ret) {
+               num_displays = 1;
+-              DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
++              DRM_WARN("Unable to determine number of displays - assuming 1\n");
+               ret = 0;
+       }
+@@ -1344,17 +1344,21 @@ static int vc4_fkms_bind(struct device *
+                                 display_num);
+       }
+-      /* Map the SMI interrupt reg */
+-      crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
+-      if (IS_ERR(crtc_list[0]->regs))
+-              DRM_ERROR("Oh dear, failed to map registers\n");
+-
+-      writel(0, crtc_list[0]->regs + SMICS);
+-      ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
+-                             vc4_crtc_irq_handler, 0, "vc4 firmware kms",
+-                             crtc_list);
+-      if (ret)
+-              DRM_ERROR("Oh dear, failed to register IRQ\n");
++      if (num_displays > 0) {
++              /* Map the SMI interrupt reg */
++              crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
++              if (IS_ERR(crtc_list[0]->regs))
++                      DRM_ERROR("Oh dear, failed to map registers\n");
++
++              writel(0, crtc_list[0]->regs + SMICS);
++              ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
++                                     vc4_crtc_irq_handler, 0,
++                                     "vc4 firmware kms", crtc_list);
++              if (ret)
++                      DRM_ERROR("Oh dear, failed to register IRQ\n");
++      } else {
++              DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
++      }
+       platform_set_drvdata(pdev, crtc_list);
diff --git a/target/linux/brcm2708/patches-4.19/950-0542-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch b/target/linux/brcm2708/patches-4.19/950-0542-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch
deleted file mode 100644 (file)
index 1a27777..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-From b4ffa49d762a4af832d0d8660caf59722c0ff75a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 21 May 2019 11:50:00 +0100
-Subject: [PATCH] drm: vc4: Probe DPI/DSI timings from the firmware
-
-For DPI and DSI displays query the firmware as to the configuration
-and add it as the only mode for DRM.
-
-In theory we can add plumbing for setting the DPI/DSI mode from
-KMS, but this is not being added at present as the support frameworks
-aren't present in the firmware.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 60 ++++++++++++++++++----
- include/soc/bcm2835/raspberrypi-firmware.h |  1 +
- 2 files changed, 51 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -280,7 +280,7 @@ static u32 vc4_get_display_type(u32 disp
-               /* The firmware display (DispmanX) IDs map to specific types in
-                * a fixed manner.
-                */
--              DRM_MODE_ENCODER_DSI,   /* MAIN_LCD */
-+              DRM_MODE_ENCODER_DSI,   /* MAIN_LCD - DSI or DPI */
-               DRM_MODE_ENCODER_DSI,   /* AUX_LCD */
-               DRM_MODE_ENCODER_TMDS,  /* HDMI0 */
-               DRM_MODE_ENCODER_TVDAC, /* VEC */
-@@ -362,7 +362,6 @@ static void vc4_plane_atomic_update(stru
-                                       vc4_get_vc_image_fmt(drm_fmt->format);
-       struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-       struct mailbox_set_plane *mb = &vc4_plane->mb;
--      struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
-       int num_planes = fb->format->num_planes;
-       struct drm_display_mode *mode = &state->crtc->mode;
-       unsigned int rotation = SUPPORTED_ROTATIONS;
-@@ -997,7 +996,9 @@ static int vc4_fkms_connector_get_modes(
-       return ret;
- }
--/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
-+/* This is the DSI panel resolution. Use this as a default should the firmware
-+ * not respond to our request for the timings.
-+ */
- static const struct drm_display_mode lcd_mode = {
-       DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-                25979400 / 1000,
-@@ -1008,15 +1009,54 @@ static const struct drm_display_mode lcd
- static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
- {
--      //struct vc4_fkms_connector *fkms_connector =
--      //                              to_vc4_fkms_connector(connector);
--      //struct drm_encoder *encoder = fkms_connector->encoder;
--      //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
-+      struct vc4_fkms_connector *fkms_connector =
-+                                      to_vc4_fkms_connector(connector);
-+      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
-       struct drm_display_mode *mode;
--      //int ret = 0;
-+      struct mailbox_set_mode mb = {
-+              .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
-+                        sizeof(struct set_timings), 0},
-+              .timings = { .display = fkms_connector->display_number },
-+      };
-+      struct drm_display_mode fw_mode;
-+      int ret = 0;
-+
-+      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
-+      if (!ret) {
-+              /* Equivalent to DRM_MODE macro. */
-+              memset(&fw_mode, 0, sizeof(fw_mode));
-+              strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
-+              fw_mode.status = 0;
-+              fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-+              fw_mode.clock = mb.timings.clock;
-+              fw_mode.hdisplay = mb.timings.hdisplay;
-+              fw_mode.hsync_start = mb.timings.hsync_start;
-+              fw_mode.hsync_end = mb.timings.hsync_end;
-+              fw_mode.htotal = mb.timings.htotal;
-+              fw_mode.hskew = 0;
-+              fw_mode.vdisplay = mb.timings.vdisplay;
-+              fw_mode.vsync_start = mb.timings.vsync_start;
-+              fw_mode.vsync_end = mb.timings.vsync_end;
-+              fw_mode.vtotal = mb.timings.vtotal;
-+              fw_mode.vscan = mb.timings.vscan;
-+              if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
-+                      fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
-+              else
-+                      fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
-+              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
-+                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
-+              else
-+                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
-+
-+              fw_mode.base.type = DRM_MODE_OBJECT_MODE;
-+
-+              mode = drm_mode_duplicate(connector->dev,
-+                                        &fw_mode);
-+      } else {
-+              mode = drm_mode_duplicate(connector->dev,
-+                                        &lcd_mode);
-+      }
--      mode = drm_mode_duplicate(connector->dev,
--                                &lcd_mode);
-       if (!mode) {
-               DRM_ERROR("Failed to create a new display mode\n");
-               return -ENOMEM;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -151,6 +151,7 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
-       RPI_FIRMWARE_SET_PLANE =                              0x00048015,
-+      RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
-       RPI_FIRMWARE_SET_TIMING =                             0x00048017,
-       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
diff --git a/target/linux/brcm2708/patches-4.19/950-0542-drm-vc4-Support-the-VEC-in-FKMS.patch b/target/linux/brcm2708/patches-4.19/950-0542-drm-vc4-Support-the-VEC-in-FKMS.patch
new file mode 100644 (file)
index 0000000..29db708
--- /dev/null
@@ -0,0 +1,62 @@
+From 82ef7a95f5ae86df811253d58d93ca4fb2cbd45a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 24 May 2019 17:59:01 +0100
+Subject: [PATCH] drm/vc4: Support the VEC in FKMS
+
+Extends the DPI/DSI support to also report the VEC output
+which supports interlacing too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -125,6 +125,7 @@ struct set_timings {
+ #define  TIMINGS_FLAGS_H_SYNC_NEG     0
+ #define  TIMINGS_FLAGS_V_SYNC_POS     BIT(1)
+ #define  TIMINGS_FLAGS_V_SYNC_NEG     0
++#define  TIMINGS_FLAGS_INTERLACE      BIT(2)
+ #define TIMINGS_FLAGS_ASPECT_MASK     GENMASK(7, 4)
+ #define TIMINGS_FLAGS_ASPECT_NONE     (0 << 4)
+@@ -1047,6 +1048,12 @@ static int vc4_fkms_lcd_connector_get_mo
+                       fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
+               else
+                       fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
++              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
++                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
++              else
++                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
++              if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
++                      fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
+               fw_mode.base.type = DRM_MODE_OBJECT_MODE;
+@@ -1133,17 +1140,24 @@ vc4_fkms_connector_init(struct drm_devic
+                                  DRM_MODE_CONNECTOR_DSI);
+               drm_connector_helper_add(connector,
+                                        &vc4_fkms_lcd_conn_helper_funcs);
++              connector->interlace_allowed = 0;
++      } else if (fkms_connector->display_type == DRM_MODE_ENCODER_TVDAC) {
++              drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
++                                 DRM_MODE_CONNECTOR_Composite);
++              drm_connector_helper_add(connector,
++                                       &vc4_fkms_lcd_conn_helper_funcs);
++              connector->interlace_allowed = 1;
+       } else {
+               drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+                                  DRM_MODE_CONNECTOR_HDMIA);
+               drm_connector_helper_add(connector,
+                                        &vc4_fkms_connector_helper_funcs);
++              connector->interlace_allowed = 0;
+       }
+       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+                            DRM_CONNECTOR_POLL_DISCONNECT);
+-      connector->interlace_allowed = 0;
+       connector->doublescan_allowed = 0;
+       drm_connector_attach_encoder(connector, encoder);
diff --git a/target/linux/brcm2708/patches-4.19/950-0543-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch b/target/linux/brcm2708/patches-4.19/950-0543-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch
new file mode 100644 (file)
index 0000000..69320e8
--- /dev/null
@@ -0,0 +1,39 @@
+From 2d35ddcd988499ac7bfd08997086cecfc6b5acb3 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 7 May 2019 15:00:02 +0100
+Subject: [PATCH] drm: vc4: Fixup typo when setting HDMI aspect ratio
+
+Assignment was to the wrong structure.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -717,19 +717,19 @@ static void vc4_crtc_mode_set_nofb(struc
+       switch (frame.avi.picture_aspect) {
+       default:
+       case HDMI_PICTURE_ASPECT_NONE:
+-              mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
++              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_NONE;
+               break;
+       case HDMI_PICTURE_ASPECT_4_3:
+-              mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
++              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_4_3;
+               break;
+       case HDMI_PICTURE_ASPECT_16_9:
+-              mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
++              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_16_9;
+               break;
+       case HDMI_PICTURE_ASPECT_64_27:
+-              mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
++              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_64_27;
+               break;
+       case HDMI_PICTURE_ASPECT_256_135:
+-              mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
++              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_256_135;
+               break;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0543-drm-vc4-handle-the-case-where-there-are-no-available.patch b/target/linux/brcm2708/patches-4.19/950-0543-drm-vc4-handle-the-case-where-there-are-no-available.patch
deleted file mode 100644 (file)
index 346d32e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From dd99aa50a3ea7f7fe1ddfd59b1a2e969c744b8a0 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 28 May 2019 13:56:06 +0100
-Subject: [PATCH] drm: vc4: handle the case where there are no
- available displays
-
-It's reasonable for the firmware to return zero as the number of
-attached displays. Handle this case as otherwise drm thinks that
-the DSI panel is attached, which is nonsense.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++-----------
- 1 file changed, 18 insertions(+), 14 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1309,13 +1309,13 @@ static int vc4_fkms_bind(struct device *
-                                   RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
-                                   &num_displays, sizeof(u32));
--      /* If we fail to get the number of displays, or it returns 0, then
-+      /* If we fail to get the number of displays, then
-        * assume old firmware that doesn't have the mailbox call, so just
-        * set one display
-        */
--      if (ret || num_displays == 0) {
-+      if (ret) {
-               num_displays = 1;
--              DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
-+              DRM_WARN("Unable to determine number of displays - assuming 1\n");
-               ret = 0;
-       }
-@@ -1344,17 +1344,21 @@ static int vc4_fkms_bind(struct device *
-                                 display_num);
-       }
--      /* Map the SMI interrupt reg */
--      crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
--      if (IS_ERR(crtc_list[0]->regs))
--              DRM_ERROR("Oh dear, failed to map registers\n");
--
--      writel(0, crtc_list[0]->regs + SMICS);
--      ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
--                             vc4_crtc_irq_handler, 0, "vc4 firmware kms",
--                             crtc_list);
--      if (ret)
--              DRM_ERROR("Oh dear, failed to register IRQ\n");
-+      if (num_displays > 0) {
-+              /* Map the SMI interrupt reg */
-+              crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
-+              if (IS_ERR(crtc_list[0]->regs))
-+                      DRM_ERROR("Oh dear, failed to map registers\n");
-+
-+              writel(0, crtc_list[0]->regs + SMICS);
-+              ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-+                                     vc4_crtc_irq_handler, 0,
-+                                     "vc4 firmware kms", crtc_list);
-+              if (ret)
-+                      DRM_ERROR("Oh dear, failed to register IRQ\n");
-+      } else {
-+              DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
-+      }
-       platform_set_drvdata(pdev, crtc_list);
diff --git a/target/linux/brcm2708/patches-4.19/950-0544-drm-vc4-Correct-SAND-support-for-FKMS.patch b/target/linux/brcm2708/patches-4.19/950-0544-drm-vc4-Correct-SAND-support-for-FKMS.patch
new file mode 100644 (file)
index 0000000..4299928
--- /dev/null
@@ -0,0 +1,40 @@
+From 0dbdeb9e76e956df275e162224e12eacb0cc8b02 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 29 May 2019 15:44:11 +0100
+Subject: [PATCH] drm/vc4: Correct SAND support for FKMS.
+
+It was accepting NV21 which doesn't map through, but
+also wasn't advertising the modifier so nothing would know
+to request it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -545,7 +545,6 @@ static bool vc4_fkms_format_mod_supporte
+                       return false;
+               }
+       case DRM_FORMAT_NV12:
+-      case DRM_FORMAT_NV21:
+               switch (fourcc_mod_broadcom_mod(modifier)) {
+               case DRM_FORMAT_MOD_LINEAR:
+               case DRM_FORMAT_MOD_BROADCOM_SAND128:
+@@ -553,6 +552,7 @@ static bool vc4_fkms_format_mod_supporte
+               default:
+                       return false;
+               }
++      case DRM_FORMAT_NV21:
+       case DRM_FORMAT_RGB888:
+       case DRM_FORMAT_BGR888:
+       case DRM_FORMAT_YUV422:
+@@ -599,6 +599,7 @@ static struct drm_plane *vc4_fkms_plane_
+                * would prefer to scan out linear (less bus traffic).
+                */
+               DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
++              DRM_FORMAT_MOD_BROADCOM_SAND128,
+               DRM_FORMAT_MOD_INVALID,
+       };
+       int i;
diff --git a/target/linux/brcm2708/patches-4.19/950-0544-drm-vc4-Support-the-VEC-in-FKMS.patch b/target/linux/brcm2708/patches-4.19/950-0544-drm-vc4-Support-the-VEC-in-FKMS.patch
deleted file mode 100644 (file)
index 29db708..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-From 82ef7a95f5ae86df811253d58d93ca4fb2cbd45a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 24 May 2019 17:59:01 +0100
-Subject: [PATCH] drm/vc4: Support the VEC in FKMS
-
-Extends the DPI/DSI support to also report the VEC output
-which supports interlacing too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 16 +++++++++++++++-
- 1 file changed, 15 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -125,6 +125,7 @@ struct set_timings {
- #define  TIMINGS_FLAGS_H_SYNC_NEG     0
- #define  TIMINGS_FLAGS_V_SYNC_POS     BIT(1)
- #define  TIMINGS_FLAGS_V_SYNC_NEG     0
-+#define  TIMINGS_FLAGS_INTERLACE      BIT(2)
- #define TIMINGS_FLAGS_ASPECT_MASK     GENMASK(7, 4)
- #define TIMINGS_FLAGS_ASPECT_NONE     (0 << 4)
-@@ -1047,6 +1048,12 @@ static int vc4_fkms_lcd_connector_get_mo
-                       fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
-               else
-                       fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
-+              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
-+                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
-+              else
-+                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
-+              if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
-+                      fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
-               fw_mode.base.type = DRM_MODE_OBJECT_MODE;
-@@ -1133,17 +1140,24 @@ vc4_fkms_connector_init(struct drm_devic
-                                  DRM_MODE_CONNECTOR_DSI);
-               drm_connector_helper_add(connector,
-                                        &vc4_fkms_lcd_conn_helper_funcs);
-+              connector->interlace_allowed = 0;
-+      } else if (fkms_connector->display_type == DRM_MODE_ENCODER_TVDAC) {
-+              drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-+                                 DRM_MODE_CONNECTOR_Composite);
-+              drm_connector_helper_add(connector,
-+                                       &vc4_fkms_lcd_conn_helper_funcs);
-+              connector->interlace_allowed = 1;
-       } else {
-               drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-                                  DRM_MODE_CONNECTOR_HDMIA);
-               drm_connector_helper_add(connector,
-                                        &vc4_fkms_connector_helper_funcs);
-+              connector->interlace_allowed = 0;
-       }
-       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
-                            DRM_CONNECTOR_POLL_DISCONNECT);
--      connector->interlace_allowed = 0;
-       connector->doublescan_allowed = 0;
-       drm_connector_attach_encoder(connector, encoder);
diff --git a/target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch b/target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch
deleted file mode 100644 (file)
index 69320e8..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From 2d35ddcd988499ac7bfd08997086cecfc6b5acb3 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 7 May 2019 15:00:02 +0100
-Subject: [PATCH] drm: vc4: Fixup typo when setting HDMI aspect ratio
-
-Assignment was to the wrong structure.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -717,19 +717,19 @@ static void vc4_crtc_mode_set_nofb(struc
-       switch (frame.avi.picture_aspect) {
-       default:
-       case HDMI_PICTURE_ASPECT_NONE:
--              mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
-+              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_NONE;
-               break;
-       case HDMI_PICTURE_ASPECT_4_3:
--              mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
-+              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_4_3;
-               break;
-       case HDMI_PICTURE_ASPECT_16_9:
--              mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
-+              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_16_9;
-               break;
-       case HDMI_PICTURE_ASPECT_64_27:
--              mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
-+              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_64_27;
-               break;
-       case HDMI_PICTURE_ASPECT_256_135:
--              mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
-+              mb.timings.flags |= TIMINGS_FLAGS_ASPECT_256_135;
-               break;
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch b/target/linux/brcm2708/patches-4.19/950-0545-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch
new file mode 100644 (file)
index 0000000..7f917bd
--- /dev/null
@@ -0,0 +1,134 @@
+From 23e6a2c2d33050255c76a499ea080e5279d6edfc Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 30 May 2019 13:56:15 +0100
+Subject: [PATCH] drm/vc4: fkms to query the VPU for HDMI clock limits
+
+The VPU has configured clocks for 4k (or not) via config.txt,
+and will limit the choice of video modes based on that.
+Make fkms query it for these limits too to avoid selecting modes
+that can not be handled by the current clock setup.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_drv.h              |  1 +
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 48 ++++++++++++++++++++++
+ include/soc/bcm2835/raspberrypi-firmware.h |  1 +
+ 3 files changed, 50 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -77,6 +77,7 @@ struct vc4_dev {
+       struct vc4_dsi *dsi1;
+       struct vc4_vec *vec;
+       struct vc4_txp *txp;
++      struct vc4_fkms *fkms;
+       struct vc4_hang_state *hang_state;
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -29,6 +29,14 @@
+ #include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
++struct get_display_cfg {
++      u32  max_pixel_clock[2];  //Max pixel clock for each display
++};
++
++struct vc4_fkms {
++      struct get_display_cfg cfg;
++};
++
+ #define PLANES_PER_CRTC               3
+ struct set_plane {
+@@ -794,6 +802,11 @@ static void vc4_crtc_enable(struct drm_c
+ static enum drm_mode_status
+ vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
+ {
++      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++      struct drm_device *dev = crtc->dev;
++      struct vc4_dev *vc4 = to_vc4_dev(dev);
++      struct vc4_fkms *fkms = vc4->fkms;
++
+       /* Do not allow doublescan modes from user space */
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
+               DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
+@@ -801,6 +814,22 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+               return MODE_NO_DBLESCAN;
+       }
++      /* Limit the pixel clock based on the HDMI clock limits from the
++       * firmware
++       */
++      switch (vc4_crtc->display_number) {
++      case 2: /* HDMI0 */
++              if (fkms->cfg.max_pixel_clock[0] &&
++                  mode->clock > fkms->cfg.max_pixel_clock[0])
++                      return MODE_CLOCK_HIGH;
++              break;
++      case 7: /* HDMI1 */
++              if (fkms->cfg.max_pixel_clock[1] &&
++                  mode->clock > fkms->cfg.max_pixel_clock[1])
++                      return MODE_CLOCK_HIGH;
++              break;
++      }
++
+       /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
+        * working.
+        */
+@@ -1301,11 +1330,16 @@ static int vc4_fkms_bind(struct device *
+       struct device_node *firmware_node;
+       struct vc4_crtc **crtc_list;
+       u32 num_displays, display_num;
++      struct vc4_fkms *fkms;
+       int ret;
+       u32 display_id;
+       vc4->firmware_kms = true;
++      fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL);
++      if (!fkms)
++              return -ENOMEM;
++
+       /* firmware kms doesn't have precise a scanoutpos implementation, so
+        * we can't do the precise vblank timestamp mode.
+        */
+@@ -1334,6 +1368,18 @@ static int vc4_fkms_bind(struct device *
+               ret = 0;
+       }
++      ret = rpi_firmware_property(vc4->firmware,
++                                  RPI_FIRMWARE_GET_DISPLAY_CFG,
++                                  &fkms->cfg, sizeof(fkms->cfg));
++
++      if (ret)
++              return -EINVAL;
++      /* The firmware works in Hz. This will be compared against kHz, so div
++       * 1000 now rather than multiple times later.
++       */
++      fkms->cfg.max_pixel_clock[0] /= 1000;
++      fkms->cfg.max_pixel_clock[1] /= 1000;
++
+       /* Allocate a list, with space for a NULL on the end */
+       crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
+                                GFP_KERNEL);
+@@ -1375,6 +1421,8 @@ static int vc4_fkms_bind(struct device *
+               DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
+       }
++      vc4->fkms = fkms;
++
+       platform_set_drvdata(pdev, crtc_list);
+       return 0;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -153,6 +153,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_SET_PLANE =                              0x00048015,
+       RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
+       RPI_FIRMWARE_SET_TIMING =                             0x00048017,
++      RPI_FIRMWARE_GET_DISPLAY_CFG =                        0x00040018,
+       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
+       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
diff --git a/target/linux/brcm2708/patches-4.19/950-0546-drm-vc4-Correct-SAND-support-for-FKMS.patch b/target/linux/brcm2708/patches-4.19/950-0546-drm-vc4-Correct-SAND-support-for-FKMS.patch
deleted file mode 100644 (file)
index 4299928..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From 0dbdeb9e76e956df275e162224e12eacb0cc8b02 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 29 May 2019 15:44:11 +0100
-Subject: [PATCH] drm/vc4: Correct SAND support for FKMS.
-
-It was accepting NV21 which doesn't map through, but
-also wasn't advertising the modifier so nothing would know
-to request it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -545,7 +545,6 @@ static bool vc4_fkms_format_mod_supporte
-                       return false;
-               }
-       case DRM_FORMAT_NV12:
--      case DRM_FORMAT_NV21:
-               switch (fourcc_mod_broadcom_mod(modifier)) {
-               case DRM_FORMAT_MOD_LINEAR:
-               case DRM_FORMAT_MOD_BROADCOM_SAND128:
-@@ -553,6 +552,7 @@ static bool vc4_fkms_format_mod_supporte
-               default:
-                       return false;
-               }
-+      case DRM_FORMAT_NV21:
-       case DRM_FORMAT_RGB888:
-       case DRM_FORMAT_BGR888:
-       case DRM_FORMAT_YUV422:
-@@ -599,6 +599,7 @@ static struct drm_plane *vc4_fkms_plane_
-                * would prefer to scan out linear (less bus traffic).
-                */
-               DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
-+              DRM_FORMAT_MOD_BROADCOM_SAND128,
-               DRM_FORMAT_MOD_INVALID,
-       };
-       int i;
diff --git a/target/linux/brcm2708/patches-4.19/950-0546-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch b/target/linux/brcm2708/patches-4.19/950-0546-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch
new file mode 100644 (file)
index 0000000..83e1845
--- /dev/null
@@ -0,0 +1,38 @@
+From bce8c3dc146e3287519d5f6bb965dc2458e6684d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 30 May 2019 15:55:15 +0100
+Subject: [PATCH] drm/vc4: Max resolution of 7680 is conditional on
+ being Pi4
+
+The max resolution had been increased from 2048 to 7680 for all
+platforms. This code is common with Pi0-3 which have a max render
+target for GL of 2048, therefore the increased resolution has to
+be conditional on the platform.
+Switch based on whether the bcm2835-v3d node is found, as that is
+not present on Pi4. (There is a potential configuration on Pi0-3
+with no v3d, but this is very unlikely).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -429,8 +429,14 @@ int vc4_kms_load(struct drm_device *dev)
+               return ret;
+       }
+-      dev->mode_config.max_width = 7680;
+-      dev->mode_config.max_height = 7680;
++      if (!drm_core_check_feature(dev, DRIVER_RENDER)) {
++              /* No V3D as part of vc4. Assume this is Pi4. */
++              dev->mode_config.max_width = 7680;
++              dev->mode_config.max_height = 7680;
++      } else {
++              dev->mode_config.max_width = 2048;
++              dev->mode_config.max_height = 2048;
++      }
+       dev->mode_config.funcs = &vc4_mode_funcs;
+       dev->mode_config.preferred_depth = 24;
+       dev->mode_config.async_page_flip = true;
diff --git a/target/linux/brcm2708/patches-4.19/950-0547-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch b/target/linux/brcm2708/patches-4.19/950-0547-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch
deleted file mode 100644 (file)
index 7f917bd..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-From 23e6a2c2d33050255c76a499ea080e5279d6edfc Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 30 May 2019 13:56:15 +0100
-Subject: [PATCH] drm/vc4: fkms to query the VPU for HDMI clock limits
-
-The VPU has configured clocks for 4k (or not) via config.txt,
-and will limit the choice of video modes based on that.
-Make fkms query it for these limits too to avoid selecting modes
-that can not be handled by the current clock setup.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_drv.h              |  1 +
- drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 48 ++++++++++++++++++++++
- include/soc/bcm2835/raspberrypi-firmware.h |  1 +
- 3 files changed, 50 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_drv.h
-+++ b/drivers/gpu/drm/vc4/vc4_drv.h
-@@ -77,6 +77,7 @@ struct vc4_dev {
-       struct vc4_dsi *dsi1;
-       struct vc4_vec *vec;
-       struct vc4_txp *txp;
-+      struct vc4_fkms *fkms;
-       struct vc4_hang_state *hang_state;
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -29,6 +29,14 @@
- #include "vc_image_types.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-+struct get_display_cfg {
-+      u32  max_pixel_clock[2];  //Max pixel clock for each display
-+};
-+
-+struct vc4_fkms {
-+      struct get_display_cfg cfg;
-+};
-+
- #define PLANES_PER_CRTC               3
- struct set_plane {
-@@ -794,6 +802,11 @@ static void vc4_crtc_enable(struct drm_c
- static enum drm_mode_status
- vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
- {
-+      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+      struct drm_device *dev = crtc->dev;
-+      struct vc4_dev *vc4 = to_vc4_dev(dev);
-+      struct vc4_fkms *fkms = vc4->fkms;
-+
-       /* Do not allow doublescan modes from user space */
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
-               DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
-@@ -801,6 +814,22 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
-               return MODE_NO_DBLESCAN;
-       }
-+      /* Limit the pixel clock based on the HDMI clock limits from the
-+       * firmware
-+       */
-+      switch (vc4_crtc->display_number) {
-+      case 2: /* HDMI0 */
-+              if (fkms->cfg.max_pixel_clock[0] &&
-+                  mode->clock > fkms->cfg.max_pixel_clock[0])
-+                      return MODE_CLOCK_HIGH;
-+              break;
-+      case 7: /* HDMI1 */
-+              if (fkms->cfg.max_pixel_clock[1] &&
-+                  mode->clock > fkms->cfg.max_pixel_clock[1])
-+                      return MODE_CLOCK_HIGH;
-+              break;
-+      }
-+
-       /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
-        * working.
-        */
-@@ -1301,11 +1330,16 @@ static int vc4_fkms_bind(struct device *
-       struct device_node *firmware_node;
-       struct vc4_crtc **crtc_list;
-       u32 num_displays, display_num;
-+      struct vc4_fkms *fkms;
-       int ret;
-       u32 display_id;
-       vc4->firmware_kms = true;
-+      fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL);
-+      if (!fkms)
-+              return -ENOMEM;
-+
-       /* firmware kms doesn't have precise a scanoutpos implementation, so
-        * we can't do the precise vblank timestamp mode.
-        */
-@@ -1334,6 +1368,18 @@ static int vc4_fkms_bind(struct device *
-               ret = 0;
-       }
-+      ret = rpi_firmware_property(vc4->firmware,
-+                                  RPI_FIRMWARE_GET_DISPLAY_CFG,
-+                                  &fkms->cfg, sizeof(fkms->cfg));
-+
-+      if (ret)
-+              return -EINVAL;
-+      /* The firmware works in Hz. This will be compared against kHz, so div
-+       * 1000 now rather than multiple times later.
-+       */
-+      fkms->cfg.max_pixel_clock[0] /= 1000;
-+      fkms->cfg.max_pixel_clock[1] /= 1000;
-+
-       /* Allocate a list, with space for a NULL on the end */
-       crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
-                                GFP_KERNEL);
-@@ -1375,6 +1421,8 @@ static int vc4_fkms_bind(struct device *
-               DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
-       }
-+      vc4->fkms = fkms;
-+
-       platform_set_drvdata(pdev, crtc_list);
-       return 0;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -153,6 +153,7 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_SET_PLANE =                              0x00048015,
-       RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
-       RPI_FIRMWARE_SET_TIMING =                             0x00048017,
-+      RPI_FIRMWARE_GET_DISPLAY_CFG =                        0x00040018,
-       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
-       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
diff --git a/target/linux/brcm2708/patches-4.19/950-0547-staging-vc-sm-cma-Remove-obsolete-comment-and-make-f.patch b/target/linux/brcm2708/patches-4.19/950-0547-staging-vc-sm-cma-Remove-obsolete-comment-and-make-f.patch
new file mode 100644 (file)
index 0000000..86c86af
--- /dev/null
@@ -0,0 +1,28 @@
+From 84b54ee2ff01005f0201c51f50985faf4e79edc6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 10 Dec 2018 17:35:58 +0000
+Subject: [PATCH] staging: vc-sm-cma: Remove obsolete comment and make
+ function static
+
+Removes obsolete comment about wanting to pass a function
+pointer into mmal-vchiq as we now do.
+As the function is passed as a function pointer, the function itself
+can be static.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -594,8 +594,7 @@ error:
+       return ret;
+ }
+-/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
+-void
++static void
+ vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
+               int reply_len)
+ {
diff --git a/target/linux/brcm2708/patches-4.19/950-0548-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch b/target/linux/brcm2708/patches-4.19/950-0548-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch
deleted file mode 100644 (file)
index 83e1845..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From bce8c3dc146e3287519d5f6bb965dc2458e6684d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 30 May 2019 15:55:15 +0100
-Subject: [PATCH] drm/vc4: Max resolution of 7680 is conditional on
- being Pi4
-
-The max resolution had been increased from 2048 to 7680 for all
-platforms. This code is common with Pi0-3 which have a max render
-target for GL of 2048, therefore the increased resolution has to
-be conditional on the platform.
-Switch based on whether the bcm2835-v3d node is found, as that is
-not present on Pi4. (There is a potential configuration on Pi0-3
-with no v3d, but this is very unlikely).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -429,8 +429,14 @@ int vc4_kms_load(struct drm_device *dev)
-               return ret;
-       }
--      dev->mode_config.max_width = 7680;
--      dev->mode_config.max_height = 7680;
-+      if (!drm_core_check_feature(dev, DRIVER_RENDER)) {
-+              /* No V3D as part of vc4. Assume this is Pi4. */
-+              dev->mode_config.max_width = 7680;
-+              dev->mode_config.max_height = 7680;
-+      } else {
-+              dev->mode_config.max_width = 2048;
-+              dev->mode_config.max_height = 2048;
-+      }
-       dev->mode_config.funcs = &vc4_mode_funcs;
-       dev->mode_config.preferred_depth = 24;
-       dev->mode_config.async_page_flip = true;
diff --git a/target/linux/brcm2708/patches-4.19/950-0548-staging-vc-sm-cma-Add-in-allocation-for-VPU-requests.patch b/target/linux/brcm2708/patches-4.19/950-0548-staging-vc-sm-cma-Add-in-allocation-for-VPU-requests.patch
new file mode 100644 (file)
index 0000000..105309b
--- /dev/null
@@ -0,0 +1,1206 @@
+From 275f4673d8c0601e5dbb16e743187d264e7dbed6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 21 Dec 2018 16:50:53 +0000
+Subject: [PATCH] staging: vc-sm-cma: Add in allocation for VPU
+ requests.
+
+Module has to change from tristate to bool as all CMA functions
+are boolean.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/Kconfig   |   4 +-
+ .../staging/vc04_services/vc-sm-cma/Makefile  |   2 +-
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 642 +++++++++++++++---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.h   |  30 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c       |  99 +++
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h       |  39 ++
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  |  10 +
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h  |   4 +
+ .../vc04_services/vc-sm-cma/vc_sm_defs.h      |   2 +
+ 9 files changed, 723 insertions(+), 109 deletions(-)
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
++++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
+@@ -1,6 +1,6 @@
+ config BCM_VC_SM_CMA
+-      tristate "VideoCore Shared Memory (CMA) driver"
+-      depends on BCM2835_VCHIQ
++      bool "VideoCore Shared Memory (CMA) driver"
++      depends on BCM2835_VCHIQ && DMA_CMA
+       select RBTREE
+       select DMA_SHARED_BUFFER
+       help
+--- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
++++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
+@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
+ ccflags-y += -D__VCCOREVER__=0
+ vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
+-      vc_sm.o vc_sm_cma_vchi.o
++      vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
+ obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -9,10 +9,21 @@
+  * and taking some code for CMA/dmabuf handling from the Android Ion
+  * driver (Google/Linaro).
+  *
+- * This is cut down version to only support import of dma_bufs from
+- * other kernel drivers. A more complete implementation of the old
+- * vmcs_sm functionality can follow later.
+  *
++ * This driver has 3 main uses:
++ * 1) Allocating buffers for the kernel or userspace that can be shared with the
++ *    VPU.
++ * 2) Importing dmabufs from elsewhere for sharing with the VPU.
++ * 3) Allocating buffers for use by the VPU.
++ *
++ * In the first and second cases the native handle is a dmabuf. Releasing the
++ * resource inherently comes from releasing the dmabuf, and this will trigger
++ * unmapping on the VPU. The underlying allocation and our buffer structure are
++ * retained until the VPU has confirmed that it has finished with it.
++ *
++ * For the VPU allocations the VPU is responsible for triggering the release,
++ * and therefore the released message decrements the dma_buf refcount (with the
++ * VPU mapping having already been marked as released).
+  */
+ /* ---- Include Files ----------------------------------------------------- */
+@@ -39,6 +50,7 @@
+ #include "vc_sm_cma_vchi.h"
+ #include "vc_sm.h"
++#include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
+ /* ---- Private Constants and Types --------------------------------------- */
+@@ -72,6 +84,7 @@ struct sm_state_t {
+       struct platform_device *pdev;
+       struct sm_instance *sm_handle;  /* Handle for videocore service. */
++      struct cma *cma_heap;
+       spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
+       struct idr kernelid_map;
+@@ -80,6 +93,7 @@ struct sm_state_t {
+       struct list_head buffer_list;   /* List of buffer. */
+       struct vc_sm_privdata_t *data_knl;  /* Kernel internal data tracking. */
++      struct vc_sm_privdata_t *vpu_allocs; /* All allocations from the VPU */
+       struct dentry *dir_root;        /* Debug fs entries root. */
+       struct sm_pde_t dir_state;      /* Debug fs entries state sub-tree. */
+@@ -89,6 +103,12 @@ struct sm_state_t {
+       u32 int_trans_id;               /* Interrupted transaction. */
+ };
++struct vc_sm_dma_buf_attachment {
++      struct device *dev;
++      struct sg_table *table;
++      struct list_head list;
++};
++
+ /* ---- Private Variables ----------------------------------------------- */
+ static struct sm_state_t *sm_state;
+@@ -172,12 +192,14 @@ static int vc_sm_cma_global_state_show(s
+                                  resource->size);
+                       seq_printf(s, "           DMABUF       %p\n",
+                                  resource->dma_buf);
+-                      seq_printf(s, "           ATTACH       %p\n",
+-                                 resource->attach);
++                      if (resource->imported) {
++                              seq_printf(s, "           ATTACH       %p\n",
++                                         resource->import.attach);
++                              seq_printf(s, "           SGT          %p\n",
++                                         resource->import.sgt);
++                      }
+                       seq_printf(s, "           SG_TABLE     %p\n",
+                                  resource->sg_table);
+-                      seq_printf(s, "           SGT          %p\n",
+-                                 resource->sgt);
+                       seq_printf(s, "           DMA_ADDR     %pad\n",
+                                  &resource->dma_addr);
+                       seq_printf(s, "           VC_HANDLE     %08x\n",
+@@ -209,17 +231,33 @@ static void vc_sm_add_resource(struct vc
+ }
+ /*
+- * Release an allocation.
+- * All refcounting is done via the dma buf object.
++ * Cleans up imported dmabuf.
+  */
+-static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
++static void vc_sm_clean_up_dmabuf(struct vc_sm_buffer *buffer)
+ {
+-      mutex_lock(&sm_state->map_lock);
+-      mutex_lock(&buffer->lock);
++      if (!buffer->imported)
++              return;
+-      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
+-               __func__, buffer, buffer->name, buffer->size);
++      /* Handle cleaning up imported dmabufs */
++      mutex_lock(&buffer->lock);
++      if (buffer->import.sgt) {
++              dma_buf_unmap_attachment(buffer->import.attach,
++                                       buffer->import.sgt,
++                                       DMA_BIDIRECTIONAL);
++              buffer->import.sgt = NULL;
++      }
++      if (buffer->import.attach) {
++              dma_buf_detach(buffer->dma_buf, buffer->import.attach);
++              buffer->import.attach = NULL;
++      }
++      mutex_unlock(&buffer->lock);
++}
++/*
++ * Instructs VPU to decrement the refcount on a buffer.
++ */
++static void vc_sm_vpu_free(struct vc_sm_buffer *buffer)
++{
+       if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
+               struct vc_sm_free_t free = { buffer->vc_handle, 0 };
+               int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
+@@ -230,17 +268,32 @@ static void vc_sm_release_resource(struc
+               }
+               if (sm_state->require_released_callback) {
+-                      /* Need to wait for the VPU to confirm the free */
++                      /* Need to wait for the VPU to confirm the free. */
+                       /* Retain a reference on this until the VPU has
+                        * released it
+                        */
+                       buffer->vpu_state = VPU_UNMAPPING;
+-                      goto defer;
++              } else {
++                      buffer->vpu_state = VPU_NOT_MAPPED;
++                      buffer->vc_handle = 0;
+               }
+-              buffer->vpu_state = VPU_NOT_MAPPED;
+-              buffer->vc_handle = 0;
+       }
++}
++
++/*
++ * Release an allocation.
++ * All refcounting is done via the dma buf object.
++ *
++ * Must be called with the mutex held. The function will either release the
++ * mutex (if defering the release) or destroy it. The caller must therefore not
++ * reuse the buffer on return.
++ */
++static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
++{
++      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
++               __func__, buffer, buffer->name, buffer->size);
++
+       if (buffer->vc_handle) {
+               /* We've sent the unmap request but not had the response. */
+               pr_err("[%s]: Waiting for VPU unmap response on %p\n",
+@@ -248,45 +301,43 @@ static void vc_sm_release_resource(struc
+               goto defer;
+       }
+       if (buffer->in_use) {
+-              /* Don't release dmabuf here - we await the release */
++              /* dmabuf still in use - we await the release */
+               pr_err("[%s]: buffer %p is still in use\n",
+                      __func__, buffer);
+               goto defer;
+       }
+-      /* Handle cleaning up imported dmabufs */
+-      if (buffer->sgt) {
+-              dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
+-                                       DMA_BIDIRECTIONAL);
+-              buffer->sgt = NULL;
+-      }
+-      if (buffer->attach) {
+-              dma_buf_detach(buffer->dma_buf, buffer->attach);
+-              buffer->attach = NULL;
+-      }
+-
+-      /* Release the dma_buf (whether ours or imported) */
+-      if (buffer->import_dma_buf) {
+-              dma_buf_put(buffer->import_dma_buf);
+-              buffer->import_dma_buf = NULL;
+-              buffer->dma_buf = NULL;
+-      } else if (buffer->dma_buf) {
+-              dma_buf_put(buffer->dma_buf);
+-              buffer->dma_buf = NULL;
++      /* Release the allocation (whether imported dmabuf or CMA allocation) */
++      if (buffer->imported) {
++              pr_debug("%s: Release imported dmabuf %p\n", __func__,
++                       buffer->import.dma_buf);
++              if (buffer->import.dma_buf)
++                      dma_buf_put(buffer->import.dma_buf);
++              else
++                      pr_err("%s: Imported dmabuf already been put for buf %p\n",
++                             __func__, buffer);
++              buffer->import.dma_buf = NULL;
++      } else {
++              if (buffer->sg_table) {
++                      /* Our own allocation that we need to dma_unmap_sg */
++                      dma_unmap_sg(&sm_state->pdev->dev,
++                                   buffer->sg_table->sgl,
++                                   buffer->sg_table->nents,
++                                   DMA_BIDIRECTIONAL);
++              }
++              pr_debug("%s: Release our allocation\n", __func__);
++              vc_sm_cma_buffer_free(&buffer->alloc);
++              pr_debug("%s: Release our allocation - done\n", __func__);
+       }
+-      if (buffer->sg_table && !buffer->import_dma_buf) {
+-              /* Our own allocation that we need to dma_unmap_sg */
+-              dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+-                           buffer->sg_table->nents, DMA_BIDIRECTIONAL);
+-      }
+-      /* Free the local resource. Start by removing it from the list */
+-      buffer->private = NULL;
++      /* Free our buffer. Start by removing it from the list */
++      mutex_lock(&sm_state->map_lock);
+       list_del(&buffer->global_buffer_list);
++      mutex_unlock(&sm_state->map_lock);
++      pr_debug("%s: Release our allocation - done\n", __func__);
+       mutex_unlock(&buffer->lock);
+-      mutex_unlock(&sm_state->map_lock);
+       mutex_destroy(&buffer->lock);
+@@ -295,7 +346,7 @@ static void vc_sm_release_resource(struc
+ defer:
+       mutex_unlock(&buffer->lock);
+-      mutex_unlock(&sm_state->map_lock);
++      return;
+ }
+ /* Create support for private data tracking. */
+@@ -317,16 +368,267 @@ static struct vc_sm_privdata_t *vc_sm_cm
+       return file_data;
+ }
++static struct sg_table *dup_sg_table(struct sg_table *table)
++{
++      struct sg_table *new_table;
++      int ret, i;
++      struct scatterlist *sg, *new_sg;
++
++      new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
++      if (!new_table)
++              return ERR_PTR(-ENOMEM);
++
++      ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
++      if (ret) {
++              kfree(new_table);
++              return ERR_PTR(-ENOMEM);
++      }
++
++      new_sg = new_table->sgl;
++      for_each_sg(table->sgl, sg, table->nents, i) {
++              memcpy(new_sg, sg, sizeof(*sg));
++              sg->dma_address = 0;
++              new_sg = sg_next(new_sg);
++      }
++
++      return new_table;
++}
++
++static void free_duped_table(struct sg_table *table)
++{
++      sg_free_table(table);
++      kfree(table);
++}
++
++/* Dma buf operations for use with our own allocations */
++
++static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
++                              struct dma_buf_attachment *attachment)
++
++{
++      struct vc_sm_dma_buf_attachment *a;
++      struct sg_table *table;
++      struct vc_sm_buffer *buf = dmabuf->priv;
++
++      a = kzalloc(sizeof(*a), GFP_KERNEL);
++      if (!a)
++              return -ENOMEM;
++
++      table = dup_sg_table(buf->sg_table);
++      if (IS_ERR(table)) {
++              kfree(a);
++              return -ENOMEM;
++      }
++
++      a->table = table;
++      INIT_LIST_HEAD(&a->list);
++
++      attachment->priv = a;
++
++      mutex_lock(&buf->lock);
++      list_add(&a->list, &buf->attachments);
++      mutex_unlock(&buf->lock);
++      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
++
++      return 0;
++}
++
++static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
++                                struct dma_buf_attachment *attachment)
++{
++      struct vc_sm_dma_buf_attachment *a = attachment->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
++
++      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
++      free_duped_table(a->table);
++      mutex_lock(&buf->lock);
++      list_del(&a->list);
++      mutex_unlock(&buf->lock);
++
++      kfree(a);
++}
++
++static struct sg_table *vc_sm_map_dma_buf(struct dma_buf_attachment *attachment,
++                                        enum dma_data_direction direction)
++{
++      struct vc_sm_dma_buf_attachment *a = attachment->priv;
++      struct sg_table *table;
++
++      table = a->table;
++
++      if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
++                      direction))
++              return ERR_PTR(-ENOMEM);
++
++      pr_debug("%s attachment %p\n", __func__, attachment);
++      return table;
++}
++
++static void vc_sm_unmap_dma_buf(struct dma_buf_attachment *attachment,
++                              struct sg_table *table,
++                              enum dma_data_direction direction)
++{
++      pr_debug("%s attachment %p\n", __func__, attachment);
++      dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction);
++}
++
++static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
++{
++      struct vc_sm_buffer *buf = dmabuf->priv;
++      struct sg_table *table = buf->sg_table;
++      unsigned long addr = vma->vm_start;
++      unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
++      struct scatterlist *sg;
++      int i;
++      int ret = 0;
++
++      pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
++               buf, addr);
++
++      mutex_lock(&buf->lock);
++
++      /* now map it to userspace */
++      for_each_sg(table->sgl, sg, table->nents, i) {
++              struct page *page = sg_page(sg);
++              unsigned long remainder = vma->vm_end - addr;
++              unsigned long len = sg->length;
++
++              if (offset >= sg->length) {
++                      offset -= sg->length;
++                      continue;
++              } else if (offset) {
++                      page += offset / PAGE_SIZE;
++                      len = sg->length - offset;
++                      offset = 0;
++              }
++              len = min(len, remainder);
++              ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
++                                    vma->vm_page_prot);
++              if (ret)
++                      break;
++              addr += len;
++              if (addr >= vma->vm_end)
++                      break;
++      }
++      mutex_unlock(&buf->lock);
++
++      if (ret)
++              pr_err("%s: failure mapping buffer to userspace\n",
++                     __func__);
++
++      return ret;
++}
++
++static void vc_sm_dma_buf_release(struct dma_buf *dmabuf)
++{
++      struct vc_sm_buffer *buffer;
++
++      if (!dmabuf)
++              return;
++
++      buffer = (struct vc_sm_buffer *)dmabuf->priv;
++
++      mutex_lock(&buffer->lock);
++
++      pr_debug("%s dmabuf %p, buffer %p\n", __func__, dmabuf, buffer);
++
++      buffer->in_use = 0;
++
++      /* Unmap on the VPU */
++      vc_sm_vpu_free(buffer);
++      pr_debug("%s vpu_free done\n", __func__);
++
++      /* Unmap our dma_buf object (the vc_sm_buffer remains until released
++       * on the VPU).
++       */
++      vc_sm_clean_up_dmabuf(buffer);
++      pr_debug("%s clean_up dmabuf done\n", __func__);
++
++      vc_sm_release_resource(buffer);
++      pr_debug("%s done\n", __func__);
++}
++
++static int vc_sm_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
++                                        enum dma_data_direction direction)
++{
++      struct vc_sm_buffer *buf;
++      struct vc_sm_dma_buf_attachment *a;
++
++      if (!dmabuf)
++              return -EFAULT;
++
++      buf = dmabuf->priv;
++      if (!buf)
++              return -EFAULT;
++
++      mutex_lock(&buf->lock);
++
++      list_for_each_entry(a, &buf->attachments, list) {
++              dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
++                                  direction);
++      }
++      mutex_unlock(&buf->lock);
++
++      return 0;
++}
++
++static int vc_sm_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
++                                      enum dma_data_direction direction)
++{
++      struct vc_sm_buffer *buf;
++      struct vc_sm_dma_buf_attachment *a;
++
++      if (!dmabuf)
++              return -EFAULT;
++      buf = dmabuf->priv;
++      if (!buf)
++              return -EFAULT;
++
++      mutex_lock(&buf->lock);
++
++      list_for_each_entry(a, &buf->attachments, list) {
++              dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
++                                     direction);
++      }
++      mutex_unlock(&buf->lock);
++
++      return 0;
++}
++
++static void *vc_sm_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset)
++{
++      /* FIXME */
++      return NULL;
++}
++
++static void vc_sm_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset,
++                               void *ptr)
++{
++      /* FIXME */
++}
++
++static const struct dma_buf_ops dma_buf_ops = {
++      .map_dma_buf = vc_sm_map_dma_buf,
++      .unmap_dma_buf = vc_sm_unmap_dma_buf,
++      .mmap = vc_sm_dmabuf_mmap,
++      .release = vc_sm_dma_buf_release,
++      .attach = vc_sm_dma_buf_attach,
++      .detach = vc_sm_dma_buf_detatch,
++      .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
++      .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
++      .map = vc_sm_dma_buf_kmap,
++      .unmap = vc_sm_dma_buf_kunmap,
++};
+ /* Dma_buf operations for chaining through to an imported dma_buf */
+ static
+ int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
+                               struct dma_buf_attachment *attachment)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return -EINVAL;
+-      return res->import_dma_buf->ops->attach(res->import_dma_buf,
++      return buf->import.dma_buf->ops->attach(buf->import.dma_buf,
+                                               attachment);
+ }
+@@ -334,22 +636,23 @@ static
+ void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
+                                 struct dma_buf_attachment *attachment)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return;
+-      res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
++      buf->import.dma_buf->ops->detach(buf->import.dma_buf, attachment);
+ }
+ static
+ struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
+                                         enum dma_data_direction direction)
+ {
+-      struct vc_sm_buffer *res = attachment->dmabuf->priv;
++      struct vc_sm_buffer *buf = attachment->dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return NULL;
+-      return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
++      return buf->import.dma_buf->ops->map_dma_buf(attachment,
++                                                   direction);
+ }
+ static
+@@ -357,87 +660,88 @@ void vc_sm_import_unmap_dma_buf(struct d
+                               struct sg_table *table,
+                               enum dma_data_direction direction)
+ {
+-      struct vc_sm_buffer *res = attachment->dmabuf->priv;
++      struct vc_sm_buffer *buf = attachment->dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return;
+-      res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
++      buf->import.dma_buf->ops->unmap_dma_buf(attachment, table, direction);
+ }
+ static
+ int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+-      pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
+-               dmabuf, res, res->import_dma_buf);
+-      if (!res->import_dma_buf) {
++      pr_debug("%s: mmap dma_buf %p, buf %p, imported db %p\n", __func__,
++               dmabuf, buf, buf->import.dma_buf);
++      if (!buf->imported) {
+               pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
+                      __func__, dmabuf);
+               return -EINVAL;
+       }
+-      return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
++      return buf->import.dma_buf->ops->mmap(buf->import.dma_buf, vma);
+ }
+ static
+ void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+       pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
+-      if (!res->import_dma_buf)
++      mutex_lock(&buf->lock);
++      if (!buf->imported)
+               return;
+-      res->in_use = 0;
++      buf->in_use = 0;
+-      vc_sm_release_resource(res, 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)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return NULL;
+-      return res->import_dma_buf->ops->map(res->import_dma_buf,
+-                                                    offset);
++      return buf->import.dma_buf->ops->map(buf->import.dma_buf, offset);
+ }
+ static
+ void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
+                                unsigned long offset, void *ptr)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return;
+-      res->import_dma_buf->ops->unmap(res->import_dma_buf,
+-                                             offset, ptr);
++      buf->import.dma_buf->ops->unmap(buf->import.dma_buf, offset, ptr);
+ }
+ static
+ int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+                                         enum dma_data_direction direction)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return -EINVAL;
+-      return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
+-                                                          direction);
++      return buf->import.dma_buf->ops->begin_cpu_access(buf->import.dma_buf,
++                                                        direction);
+ }
+ static
+ int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
+                                       enum dma_data_direction direction)
+ {
+-      struct vc_sm_buffer *res = dmabuf->priv;
++      struct vc_sm_buffer *buf = dmabuf->priv;
+-      if (!res->import_dma_buf)
++      if (!buf->imported)
+               return -EINVAL;
+-      return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
++      return buf->import.dma_buf->ops->end_cpu_access(buf->import.dma_buf,
+                                                         direction);
+ }
+@@ -516,9 +820,8 @@ vc_sm_cma_import_dmabuf_internal(struct
+       memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
+              sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
+-      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
+-               __func__, import.name, import.type, &dma_addr,
+-               import.size);
++      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u.\n",
++               __func__, import.name, import.type, &dma_addr, import.size);
+       /* Allocate the videocore buffer. */
+       status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
+@@ -548,12 +851,14 @@ vc_sm_cma_import_dmabuf_internal(struct
+       buffer->size = import.size;
+       buffer->vpu_state = VPU_MAPPED;
+-      buffer->import_dma_buf = dma_buf;
++      buffer->imported = 1;
++      buffer->import.dma_buf = dma_buf;
+-      buffer->attach = attach;
+-      buffer->sgt = sgt;
++      buffer->import.attach = attach;
++      buffer->import.sgt = sgt;
+       buffer->dma_addr = dma_addr;
+       buffer->in_use = 1;
++      buffer->kernel_id = import.kernel_id;
+       /*
+        * We're done - we need to export a new dmabuf chaining through most
+@@ -594,6 +899,91 @@ error:
+       return ret;
+ }
++static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
++                             u32 mem_handle, struct vc_sm_buffer **ret_buffer)
++{
++      DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
++      struct vc_sm_buffer *buffer = NULL;
++      int aligned_size;
++      int ret = 0;
++
++      /* Align to the user requested align */
++      aligned_size = ALIGN(size, align);
++      /* and then to a page boundary */
++      aligned_size = PAGE_ALIGN(aligned_size);
++
++      if (!aligned_size)
++              return -EINVAL;
++
++      /* Allocate local buffer to track this allocation. */
++      buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
++      if (!buffer)
++              return -ENOMEM;
++
++      mutex_init(&buffer->lock);
++
++      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
++                                    aligned_size)) {
++              pr_err("[%s]: cma alloc of %d bytes failed\n",
++                     __func__, aligned_size);
++              ret = -ENOMEM;
++              goto error;
++      }
++      buffer->sg_table = buffer->alloc.sg_table;
++
++      pr_debug("[%s]: cma alloc of %d bytes success\n",
++               __func__, aligned_size);
++
++      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
++                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
++              pr_err("[%s]: dma_map_sg failed\n", __func__);
++              goto error;
++      }
++
++      INIT_LIST_HEAD(&buffer->attachments);
++
++      memcpy(buffer->name, name,
++             min(sizeof(buffer->name), strlen(name)));
++
++      exp_info.ops = &dma_buf_ops;
++      exp_info.size = aligned_size;
++      exp_info.flags = O_RDWR;
++      exp_info.priv = buffer;
++
++      buffer->dma_buf = dma_buf_export(&exp_info);
++      if (IS_ERR(buffer->dma_buf)) {
++              ret = PTR_ERR(buffer->dma_buf);
++              goto error;
++      }
++      buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++      if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
++              pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
++                     __func__, &buffer->dma_addr);
++              buffer->dma_addr |= 0xC0000000;
++      }
++      buffer->private = sm_state->vpu_allocs;
++
++      buffer->vc_handle = mem_handle;
++      buffer->vpu_state = VPU_MAPPED;
++      buffer->vpu_allocated = 1;
++      buffer->size = size;
++      /*
++       * Create an ID that will be passed along with our message so
++       * that when we service the release reply, we can look up which
++       * resource is being released.
++       */
++      buffer->kernel_id = get_kernel_id(buffer);
++
++      vc_sm_add_resource(sm_state->vpu_allocs, buffer);
++
++      *ret_buffer = buffer;
++      return 0;
++error:
++      if (buffer)
++              vc_sm_release_resource(buffer);
++      return ret;
++}
++
+ static void
+ vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
+               int reply_len)
+@@ -612,21 +1002,61 @@ vc_sm_vpu_event(struct sm_instance *inst
+               struct vc_sm_released *release = (struct vc_sm_released *)reply;
+               struct vc_sm_buffer *buffer =
+                                       lookup_kernel_id(release->kernel_id);
++              if (!buffer) {
++                      pr_err("%s: VC released a buffer that is already released, kernel_id %d\n",
++                             __func__, release->kernel_id);
++                      break;
++              }
++              mutex_lock(&buffer->lock);
+-              /*
+-               * FIXME: Need to check buffer is still valid and allocated
+-               * before continuing
+-               */
+               pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
+                        __func__, release->addr, release->size,
+                        release->kernel_id, release->vc_handle);
+-              mutex_lock(&buffer->lock);
++
+               buffer->vc_handle = 0;
+               buffer->vpu_state = VPU_NOT_MAPPED;
+-              mutex_unlock(&buffer->lock);
+               free_kernel_id(release->kernel_id);
+-              vc_sm_release_resource(buffer, 0);
++              if (buffer->vpu_allocated) {
++                      /* VPU allocation, so release the dmabuf which will
++                       * trigger the clean up.
++                       */
++                      mutex_unlock(&buffer->lock);
++                      dma_buf_put(buffer->dma_buf);
++              } else {
++                      vc_sm_release_resource(buffer);
++              }
++      }
++      break;
++      case VC_SM_MSG_TYPE_VC_MEM_REQUEST:
++      {
++              struct vc_sm_buffer *buffer = NULL;
++              struct vc_sm_vc_mem_request *req =
++                                      (struct vc_sm_vc_mem_request *)reply;
++              struct vc_sm_vc_mem_request_result reply;
++              int ret;
++
++              pr_debug("%s: Request %u bytes of memory, align %d name %s, trans_id %08x\n",
++                       __func__, req->size, req->align, req->name,
++                       req->trans_id);
++              ret = vc_sm_cma_vpu_alloc(req->size, req->align, req->name,
++                                        req->vc_handle, &buffer);
++
++              reply.trans_id = req->trans_id;
++              if (!ret) {
++                      reply.addr = buffer->dma_addr;
++                      reply.kernel_id = buffer->kernel_id;
++                      pr_debug("%s: Allocated resource buffer %p, addr %pad\n",
++                               __func__, buffer, &buffer->dma_addr);
++              } else {
++                      pr_err("%s: Allocation failed size %u, name %s, vc_handle %u\n",
++                             __func__, req->size, req->name, req->vc_handle);
++                      reply.addr = 0;
++                      reply.kernel_id = 0;
++              }
++              vc_sm_vchi_client_vc_mem_req_reply(sm_state->sm_handle, &reply,
++                                                 &sm_state->int_trans_id);
++              break;
+       }
+       break;
+       default:
+@@ -645,6 +1075,14 @@ static void vc_sm_connected_init(void)
+       pr_info("[%s]: start\n", __func__);
++      if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
++          !sm_state->cma_heap) {
++              pr_err("[%s]: failed to initialise CMA heaps\n",
++                     __func__);
++              ret = -EIO;
++              goto err_free_mem;
++      }
++
+       /*
+        * Initialize and create a VCHI connection for the shared memory service
+        * running on videocore.
+@@ -696,7 +1134,7 @@ static void vc_sm_connected_init(void)
+               goto err_remove_shared_memory;
+       }
+-      version.version = 1;
++      version.version = 2;
+       ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
+                                           &version_result,
+                                           &sm_state->int_trans_id);
+@@ -768,7 +1206,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+ int vc_sm_cma_int_handle(void *handle)
+ {
+       struct dma_buf *dma_buf = (struct dma_buf *)handle;
+-      struct vc_sm_buffer *res;
++      struct vc_sm_buffer *buf;
+       /* Validate we can work with this device. */
+       if (!sm_state || !handle) {
+@@ -776,8 +1214,8 @@ int vc_sm_cma_int_handle(void *handle)
+               return 0;
+       }
+-      res = (struct vc_sm_buffer *)dma_buf->priv;
+-      return res->vc_handle;
++      buf = (struct vc_sm_buffer *)dma_buf->priv;
++      return buf->vc_handle;
+ }
+ EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
+@@ -804,7 +1242,7 @@ EXPORT_SYMBOL_GPL(vc_sm_cma_free);
+ int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
+ {
+       struct dma_buf *new_dma_buf;
+-      struct vc_sm_buffer *res;
++      struct vc_sm_buffer *buf;
+       int ret;
+       /* Validate we can work with this device. */
+@@ -818,7 +1256,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
+       if (!ret) {
+               pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
+-              res = (struct vc_sm_buffer *)new_dma_buf->priv;
++              buf = (struct vc_sm_buffer *)new_dma_buf->priv;
+               /* Assign valid handle at this time.*/
+               *handle = new_dma_buf;
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+@@ -21,6 +21,8 @@
+ #include <linux/types.h>
+ #include <linux/miscdevice.h>
++#include "vc_sm_cma.h"
++
+ #define VC_SM_MAX_NAME_LEN 32
+ enum vc_sm_vpu_mapping_state {
+@@ -29,31 +31,51 @@ enum vc_sm_vpu_mapping_state {
+       VPU_UNMAPPING
+ };
++struct vc_sm_imported {
++      struct dma_buf *dma_buf;
++      struct dma_buf_attachment *attach;
++      struct sg_table *sgt;
++};
++
+ struct vc_sm_buffer {
+       struct list_head global_buffer_list;    /* Global list of buffers. */
++      /* Index in the kernel_id idr so that we can find the
++       * mmal_msg_context again when servicing the VCHI reply.
++       */
++      int kernel_id;
++
+       size_t size;
+       /* Lock over all the following state for this buffer */
+       struct mutex lock;
+-      struct sg_table *sg_table;
+       struct list_head attachments;
+       char name[VC_SM_MAX_NAME_LEN];
+       int in_use:1;   /* Kernel is still using this resource */
++      int imported:1; /* Imported dmabuf */
++
++      struct sg_table *sg_table;
+       enum vc_sm_vpu_mapping_state vpu_state;
+       u32 vc_handle;  /* VideoCore handle for this buffer */
++      int vpu_allocated;      /*
++                               * The VPU made this allocation. Release the
++                               * local dma_buf when the VPU releases the
++                               * resource.
++                               */
+       /* DMABUF related fields */
+-      struct dma_buf *import_dma_buf;
+       struct dma_buf *dma_buf;
+-      struct dma_buf_attachment *attach;
+-      struct sg_table *sgt;
+       dma_addr_t dma_addr;
+       struct vc_sm_privdata_t *private;
++
++      union {
++              struct vc_sm_cma_alloc_data alloc;
++              struct vc_sm_imported import;
++      };
+ };
+ #endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+@@ -0,0 +1,99 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on the Android ION allocator
++ * Copyright (C) Linaro 2012
++ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
++ *
++ */
++
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/cma.h>
++#include <linux/scatterlist.h>
++
++#include "vc_sm_cma.h"
++
++/* CMA heap operations functions */
++int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
++                            struct vc_sm_cma_alloc_data *buffer,
++                            unsigned long len)
++{
++      /* len should already be page aligned */
++      unsigned long num_pages = len / PAGE_SIZE;
++      struct sg_table *table;
++      struct page *pages;
++      int ret;
++
++      pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
++      if (!pages)
++              return -ENOMEM;
++
++      table = kmalloc(sizeof(*table), GFP_KERNEL);
++      if (!table)
++              goto err;
++
++      ret = sg_alloc_table(table, 1, GFP_KERNEL);
++      if (ret)
++              goto free_mem;
++
++      sg_set_page(table->sgl, pages, len, 0);
++
++      buffer->priv_virt = pages;
++      buffer->sg_table = table;
++      buffer->cma_heap = cma_heap;
++      buffer->num_pages = num_pages;
++      return 0;
++
++free_mem:
++      kfree(table);
++err:
++      cma_release(cma_heap, pages, num_pages);
++      return -ENOMEM;
++}
++
++void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
++{
++      struct cma *cma_heap = buffer->cma_heap;
++      struct page *pages = buffer->priv_virt;
++
++      /* release memory */
++      if (cma_heap)
++              cma_release(cma_heap, pages, buffer->num_pages);
++
++      /* release sg table */
++      if (buffer->sg_table) {
++              sg_free_table(buffer->sg_table);
++              kfree(buffer->sg_table);
++              buffer->sg_table = NULL;
++      }
++}
++
++int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
++{
++      struct cma **heap = (struct cma **)priv;
++      const char *name = cma_get_name(cma);
++
++      if (!(*heap)) {
++              phys_addr_t phys_addr = cma_get_base(cma);
++
++              pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
++                       __func__, name, &phys_addr, cma_get_size(cma));
++              *heap = cma;
++      } else {
++              pr_err("%s: Ignoring heap %s as already set\n",
++                     __func__, name);
++      }
++
++      return 0;
++}
++
++int vc_sm_cma_add_heaps(struct cma **cma_heap)
++{
++      cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
++      return 0;
++}
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+@@ -0,0 +1,39 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on the Android ION allocator
++ * Copyright (C) Linaro 2012
++ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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.
++ *
++ */
++#ifndef VC_SM_CMA_H
++#define VC_SM_CMA_H
++
++struct vc_sm_cma_alloc_data {
++      struct cma *cma_heap;
++      unsigned long num_pages;
++      void *priv_virt;
++      struct sg_table *sg_table;
++};
++
++int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
++                            struct vc_sm_cma_alloc_data *buffer,
++                            unsigned long len);
++void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
++
++int vc_sm_cma_add_heaps(struct cma **cma_heap);
++
++#endif
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -500,3 +500,13 @@ int vc_sm_cma_vchi_client_version(struct
+                                  msg, sizeof(*msg), NULL, 0,
+                                  cur_trans_id, 0);
+ }
++
++int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
++                                     struct vc_sm_vc_mem_request_result *msg,
++                                     uint32_t *cur_trans_id)
++{
++      return vc_sm_cma_vchi_send_msg(handle,
++                                     VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
++                                     msg, sizeof(*msg), 0, 0, cur_trans_id,
++                                     0);
++}
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
+@@ -56,4 +56,8 @@ int vc_sm_cma_vchi_client_version(struct
+                                 struct vc_sm_result_t *result,
+                                 u32 *cur_trans_id);
++int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
++                                     struct vc_sm_vc_mem_request_result *msg,
++                                     uint32_t *cur_trans_id);
++
+ #endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
+@@ -264,6 +264,8 @@ struct vc_sm_vc_mem_request {
+       u32 align;
+       /* resource name (for easier tracking) */
+       char     name[VC_SM_RESOURCE_NAME];
++      /* VPU handle for the resource */
++      u32 vc_handle;
+ };
+ /* Response from the kernel to provide the VPU with some memory */
diff --git a/target/linux/brcm2708/patches-4.19/950-0549-staging-vc-sm-cma-Remove-obsolete-comment-and-make-f.patch b/target/linux/brcm2708/patches-4.19/950-0549-staging-vc-sm-cma-Remove-obsolete-comment-and-make-f.patch
deleted file mode 100644 (file)
index 86c86af..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 84b54ee2ff01005f0201c51f50985faf4e79edc6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 10 Dec 2018 17:35:58 +0000
-Subject: [PATCH] staging: vc-sm-cma: Remove obsolete comment and make
- function static
-
-Removes obsolete comment about wanting to pass a function
-pointer into mmal-vchiq as we now do.
-As the function is passed as a function pointer, the function itself
-can be static.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -594,8 +594,7 @@ error:
-       return ret;
- }
--/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
--void
-+static void
- vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
-               int reply_len)
- {
diff --git a/target/linux/brcm2708/patches-4.19/950-0549-staging-vc-sm-cma-Update-TODO.patch b/target/linux/brcm2708/patches-4.19/950-0549-staging-vc-sm-cma-Update-TODO.patch
new file mode 100644 (file)
index 0000000..c4d303a
--- /dev/null
@@ -0,0 +1,20 @@
+From 753e73267994a88505b6883cdf463d1d0bacf090 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 11 Mar 2019 16:38:32 +0000
+Subject: [PATCH] staging: vc-sm-cma: Update TODO.
+
+The driver is already a platform driver, so that can be
+deleted from the TODO.
+There are no known issues that need to be resolved.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/TODO | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/TODO
++++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
+@@ -1,2 +1 @@
+-1) Convert to a platform driver.
+-
++No currently outstanding tasks except some clean-up.
diff --git a/target/linux/brcm2708/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-allocation-for-VPU-requests.patch b/target/linux/brcm2708/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-allocation-for-VPU-requests.patch
deleted file mode 100644 (file)
index 105309b..0000000
+++ /dev/null
@@ -1,1206 +0,0 @@
-From 275f4673d8c0601e5dbb16e743187d264e7dbed6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 21 Dec 2018 16:50:53 +0000
-Subject: [PATCH] staging: vc-sm-cma: Add in allocation for VPU
- requests.
-
-Module has to change from tristate to bool as all CMA functions
-are boolean.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/Kconfig   |   4 +-
- .../staging/vc04_services/vc-sm-cma/Makefile  |   2 +-
- .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 642 +++++++++++++++---
- .../staging/vc04_services/vc-sm-cma/vc_sm.h   |  30 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma.c       |  99 +++
- .../vc04_services/vc-sm-cma/vc_sm_cma.h       |  39 ++
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  |  10 +
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h  |   4 +
- .../vc04_services/vc-sm-cma/vc_sm_defs.h      |   2 +
- 9 files changed, 723 insertions(+), 109 deletions(-)
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-
---- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-@@ -1,6 +1,6 @@
- config BCM_VC_SM_CMA
--      tristate "VideoCore Shared Memory (CMA) driver"
--      depends on BCM2835_VCHIQ
-+      bool "VideoCore Shared Memory (CMA) driver"
-+      depends on BCM2835_VCHIQ && DMA_CMA
-       select RBTREE
-       select DMA_SHARED_BUFFER
-       help
---- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
-@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
- ccflags-y += -D__VCCOREVER__=0
- vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
--      vc_sm.o vc_sm_cma_vchi.o
-+      vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
- obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -9,10 +9,21 @@
-  * and taking some code for CMA/dmabuf handling from the Android Ion
-  * driver (Google/Linaro).
-  *
-- * This is cut down version to only support import of dma_bufs from
-- * other kernel drivers. A more complete implementation of the old
-- * vmcs_sm functionality can follow later.
-  *
-+ * This driver has 3 main uses:
-+ * 1) Allocating buffers for the kernel or userspace that can be shared with the
-+ *    VPU.
-+ * 2) Importing dmabufs from elsewhere for sharing with the VPU.
-+ * 3) Allocating buffers for use by the VPU.
-+ *
-+ * In the first and second cases the native handle is a dmabuf. Releasing the
-+ * resource inherently comes from releasing the dmabuf, and this will trigger
-+ * unmapping on the VPU. The underlying allocation and our buffer structure are
-+ * retained until the VPU has confirmed that it has finished with it.
-+ *
-+ * For the VPU allocations the VPU is responsible for triggering the release,
-+ * and therefore the released message decrements the dma_buf refcount (with the
-+ * VPU mapping having already been marked as released).
-  */
- /* ---- Include Files ----------------------------------------------------- */
-@@ -39,6 +50,7 @@
- #include "vc_sm_cma_vchi.h"
- #include "vc_sm.h"
-+#include "vc_sm_cma.h"
- #include "vc_sm_knl.h"
- /* ---- Private Constants and Types --------------------------------------- */
-@@ -72,6 +84,7 @@ struct sm_state_t {
-       struct platform_device *pdev;
-       struct sm_instance *sm_handle;  /* Handle for videocore service. */
-+      struct cma *cma_heap;
-       spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
-       struct idr kernelid_map;
-@@ -80,6 +93,7 @@ struct sm_state_t {
-       struct list_head buffer_list;   /* List of buffer. */
-       struct vc_sm_privdata_t *data_knl;  /* Kernel internal data tracking. */
-+      struct vc_sm_privdata_t *vpu_allocs; /* All allocations from the VPU */
-       struct dentry *dir_root;        /* Debug fs entries root. */
-       struct sm_pde_t dir_state;      /* Debug fs entries state sub-tree. */
-@@ -89,6 +103,12 @@ struct sm_state_t {
-       u32 int_trans_id;               /* Interrupted transaction. */
- };
-+struct vc_sm_dma_buf_attachment {
-+      struct device *dev;
-+      struct sg_table *table;
-+      struct list_head list;
-+};
-+
- /* ---- Private Variables ----------------------------------------------- */
- static struct sm_state_t *sm_state;
-@@ -172,12 +192,14 @@ static int vc_sm_cma_global_state_show(s
-                                  resource->size);
-                       seq_printf(s, "           DMABUF       %p\n",
-                                  resource->dma_buf);
--                      seq_printf(s, "           ATTACH       %p\n",
--                                 resource->attach);
-+                      if (resource->imported) {
-+                              seq_printf(s, "           ATTACH       %p\n",
-+                                         resource->import.attach);
-+                              seq_printf(s, "           SGT          %p\n",
-+                                         resource->import.sgt);
-+                      }
-                       seq_printf(s, "           SG_TABLE     %p\n",
-                                  resource->sg_table);
--                      seq_printf(s, "           SGT          %p\n",
--                                 resource->sgt);
-                       seq_printf(s, "           DMA_ADDR     %pad\n",
-                                  &resource->dma_addr);
-                       seq_printf(s, "           VC_HANDLE     %08x\n",
-@@ -209,17 +231,33 @@ static void vc_sm_add_resource(struct vc
- }
- /*
-- * Release an allocation.
-- * All refcounting is done via the dma buf object.
-+ * Cleans up imported dmabuf.
-  */
--static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
-+static void vc_sm_clean_up_dmabuf(struct vc_sm_buffer *buffer)
- {
--      mutex_lock(&sm_state->map_lock);
--      mutex_lock(&buffer->lock);
-+      if (!buffer->imported)
-+              return;
--      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
--               __func__, buffer, buffer->name, buffer->size);
-+      /* Handle cleaning up imported dmabufs */
-+      mutex_lock(&buffer->lock);
-+      if (buffer->import.sgt) {
-+              dma_buf_unmap_attachment(buffer->import.attach,
-+                                       buffer->import.sgt,
-+                                       DMA_BIDIRECTIONAL);
-+              buffer->import.sgt = NULL;
-+      }
-+      if (buffer->import.attach) {
-+              dma_buf_detach(buffer->dma_buf, buffer->import.attach);
-+              buffer->import.attach = NULL;
-+      }
-+      mutex_unlock(&buffer->lock);
-+}
-+/*
-+ * Instructs VPU to decrement the refcount on a buffer.
-+ */
-+static void vc_sm_vpu_free(struct vc_sm_buffer *buffer)
-+{
-       if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
-               struct vc_sm_free_t free = { buffer->vc_handle, 0 };
-               int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
-@@ -230,17 +268,32 @@ static void vc_sm_release_resource(struc
-               }
-               if (sm_state->require_released_callback) {
--                      /* Need to wait for the VPU to confirm the free */
-+                      /* Need to wait for the VPU to confirm the free. */
-                       /* Retain a reference on this until the VPU has
-                        * released it
-                        */
-                       buffer->vpu_state = VPU_UNMAPPING;
--                      goto defer;
-+              } else {
-+                      buffer->vpu_state = VPU_NOT_MAPPED;
-+                      buffer->vc_handle = 0;
-               }
--              buffer->vpu_state = VPU_NOT_MAPPED;
--              buffer->vc_handle = 0;
-       }
-+}
-+
-+/*
-+ * Release an allocation.
-+ * All refcounting is done via the dma buf object.
-+ *
-+ * Must be called with the mutex held. The function will either release the
-+ * mutex (if defering the release) or destroy it. The caller must therefore not
-+ * reuse the buffer on return.
-+ */
-+static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
-+{
-+      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
-+               __func__, buffer, buffer->name, buffer->size);
-+
-       if (buffer->vc_handle) {
-               /* We've sent the unmap request but not had the response. */
-               pr_err("[%s]: Waiting for VPU unmap response on %p\n",
-@@ -248,45 +301,43 @@ static void vc_sm_release_resource(struc
-               goto defer;
-       }
-       if (buffer->in_use) {
--              /* Don't release dmabuf here - we await the release */
-+              /* dmabuf still in use - we await the release */
-               pr_err("[%s]: buffer %p is still in use\n",
-                      __func__, buffer);
-               goto defer;
-       }
--      /* Handle cleaning up imported dmabufs */
--      if (buffer->sgt) {
--              dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
--                                       DMA_BIDIRECTIONAL);
--              buffer->sgt = NULL;
--      }
--      if (buffer->attach) {
--              dma_buf_detach(buffer->dma_buf, buffer->attach);
--              buffer->attach = NULL;
--      }
--
--      /* Release the dma_buf (whether ours or imported) */
--      if (buffer->import_dma_buf) {
--              dma_buf_put(buffer->import_dma_buf);
--              buffer->import_dma_buf = NULL;
--              buffer->dma_buf = NULL;
--      } else if (buffer->dma_buf) {
--              dma_buf_put(buffer->dma_buf);
--              buffer->dma_buf = NULL;
-+      /* Release the allocation (whether imported dmabuf or CMA allocation) */
-+      if (buffer->imported) {
-+              pr_debug("%s: Release imported dmabuf %p\n", __func__,
-+                       buffer->import.dma_buf);
-+              if (buffer->import.dma_buf)
-+                      dma_buf_put(buffer->import.dma_buf);
-+              else
-+                      pr_err("%s: Imported dmabuf already been put for buf %p\n",
-+                             __func__, buffer);
-+              buffer->import.dma_buf = NULL;
-+      } else {
-+              if (buffer->sg_table) {
-+                      /* Our own allocation that we need to dma_unmap_sg */
-+                      dma_unmap_sg(&sm_state->pdev->dev,
-+                                   buffer->sg_table->sgl,
-+                                   buffer->sg_table->nents,
-+                                   DMA_BIDIRECTIONAL);
-+              }
-+              pr_debug("%s: Release our allocation\n", __func__);
-+              vc_sm_cma_buffer_free(&buffer->alloc);
-+              pr_debug("%s: Release our allocation - done\n", __func__);
-       }
--      if (buffer->sg_table && !buffer->import_dma_buf) {
--              /* Our own allocation that we need to dma_unmap_sg */
--              dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
--                           buffer->sg_table->nents, DMA_BIDIRECTIONAL);
--      }
--      /* Free the local resource. Start by removing it from the list */
--      buffer->private = NULL;
-+      /* Free our buffer. Start by removing it from the list */
-+      mutex_lock(&sm_state->map_lock);
-       list_del(&buffer->global_buffer_list);
-+      mutex_unlock(&sm_state->map_lock);
-+      pr_debug("%s: Release our allocation - done\n", __func__);
-       mutex_unlock(&buffer->lock);
--      mutex_unlock(&sm_state->map_lock);
-       mutex_destroy(&buffer->lock);
-@@ -295,7 +346,7 @@ static void vc_sm_release_resource(struc
- defer:
-       mutex_unlock(&buffer->lock);
--      mutex_unlock(&sm_state->map_lock);
-+      return;
- }
- /* Create support for private data tracking. */
-@@ -317,16 +368,267 @@ static struct vc_sm_privdata_t *vc_sm_cm
-       return file_data;
- }
-+static struct sg_table *dup_sg_table(struct sg_table *table)
-+{
-+      struct sg_table *new_table;
-+      int ret, i;
-+      struct scatterlist *sg, *new_sg;
-+
-+      new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
-+      if (!new_table)
-+              return ERR_PTR(-ENOMEM);
-+
-+      ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
-+      if (ret) {
-+              kfree(new_table);
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      new_sg = new_table->sgl;
-+      for_each_sg(table->sgl, sg, table->nents, i) {
-+              memcpy(new_sg, sg, sizeof(*sg));
-+              sg->dma_address = 0;
-+              new_sg = sg_next(new_sg);
-+      }
-+
-+      return new_table;
-+}
-+
-+static void free_duped_table(struct sg_table *table)
-+{
-+      sg_free_table(table);
-+      kfree(table);
-+}
-+
-+/* Dma buf operations for use with our own allocations */
-+
-+static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
-+                              struct dma_buf_attachment *attachment)
-+
-+{
-+      struct vc_sm_dma_buf_attachment *a;
-+      struct sg_table *table;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
-+
-+      a = kzalloc(sizeof(*a), GFP_KERNEL);
-+      if (!a)
-+              return -ENOMEM;
-+
-+      table = dup_sg_table(buf->sg_table);
-+      if (IS_ERR(table)) {
-+              kfree(a);
-+              return -ENOMEM;
-+      }
-+
-+      a->table = table;
-+      INIT_LIST_HEAD(&a->list);
-+
-+      attachment->priv = a;
-+
-+      mutex_lock(&buf->lock);
-+      list_add(&a->list, &buf->attachments);
-+      mutex_unlock(&buf->lock);
-+      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-+
-+      return 0;
-+}
-+
-+static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
-+                                struct dma_buf_attachment *attachment)
-+{
-+      struct vc_sm_dma_buf_attachment *a = attachment->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
-+
-+      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-+      free_duped_table(a->table);
-+      mutex_lock(&buf->lock);
-+      list_del(&a->list);
-+      mutex_unlock(&buf->lock);
-+
-+      kfree(a);
-+}
-+
-+static struct sg_table *vc_sm_map_dma_buf(struct dma_buf_attachment *attachment,
-+                                        enum dma_data_direction direction)
-+{
-+      struct vc_sm_dma_buf_attachment *a = attachment->priv;
-+      struct sg_table *table;
-+
-+      table = a->table;
-+
-+      if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
-+                      direction))
-+              return ERR_PTR(-ENOMEM);
-+
-+      pr_debug("%s attachment %p\n", __func__, attachment);
-+      return table;
-+}
-+
-+static void vc_sm_unmap_dma_buf(struct dma_buf_attachment *attachment,
-+                              struct sg_table *table,
-+                              enum dma_data_direction direction)
-+{
-+      pr_debug("%s attachment %p\n", __func__, attachment);
-+      dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction);
-+}
-+
-+static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
-+{
-+      struct vc_sm_buffer *buf = dmabuf->priv;
-+      struct sg_table *table = buf->sg_table;
-+      unsigned long addr = vma->vm_start;
-+      unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
-+      struct scatterlist *sg;
-+      int i;
-+      int ret = 0;
-+
-+      pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
-+               buf, addr);
-+
-+      mutex_lock(&buf->lock);
-+
-+      /* now map it to userspace */
-+      for_each_sg(table->sgl, sg, table->nents, i) {
-+              struct page *page = sg_page(sg);
-+              unsigned long remainder = vma->vm_end - addr;
-+              unsigned long len = sg->length;
-+
-+              if (offset >= sg->length) {
-+                      offset -= sg->length;
-+                      continue;
-+              } else if (offset) {
-+                      page += offset / PAGE_SIZE;
-+                      len = sg->length - offset;
-+                      offset = 0;
-+              }
-+              len = min(len, remainder);
-+              ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
-+                                    vma->vm_page_prot);
-+              if (ret)
-+                      break;
-+              addr += len;
-+              if (addr >= vma->vm_end)
-+                      break;
-+      }
-+      mutex_unlock(&buf->lock);
-+
-+      if (ret)
-+              pr_err("%s: failure mapping buffer to userspace\n",
-+                     __func__);
-+
-+      return ret;
-+}
-+
-+static void vc_sm_dma_buf_release(struct dma_buf *dmabuf)
-+{
-+      struct vc_sm_buffer *buffer;
-+
-+      if (!dmabuf)
-+              return;
-+
-+      buffer = (struct vc_sm_buffer *)dmabuf->priv;
-+
-+      mutex_lock(&buffer->lock);
-+
-+      pr_debug("%s dmabuf %p, buffer %p\n", __func__, dmabuf, buffer);
-+
-+      buffer->in_use = 0;
-+
-+      /* Unmap on the VPU */
-+      vc_sm_vpu_free(buffer);
-+      pr_debug("%s vpu_free done\n", __func__);
-+
-+      /* Unmap our dma_buf object (the vc_sm_buffer remains until released
-+       * on the VPU).
-+       */
-+      vc_sm_clean_up_dmabuf(buffer);
-+      pr_debug("%s clean_up dmabuf done\n", __func__);
-+
-+      vc_sm_release_resource(buffer);
-+      pr_debug("%s done\n", __func__);
-+}
-+
-+static int vc_sm_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
-+                                        enum dma_data_direction direction)
-+{
-+      struct vc_sm_buffer *buf;
-+      struct vc_sm_dma_buf_attachment *a;
-+
-+      if (!dmabuf)
-+              return -EFAULT;
-+
-+      buf = dmabuf->priv;
-+      if (!buf)
-+              return -EFAULT;
-+
-+      mutex_lock(&buf->lock);
-+
-+      list_for_each_entry(a, &buf->attachments, list) {
-+              dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
-+                                  direction);
-+      }
-+      mutex_unlock(&buf->lock);
-+
-+      return 0;
-+}
-+
-+static int vc_sm_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
-+                                      enum dma_data_direction direction)
-+{
-+      struct vc_sm_buffer *buf;
-+      struct vc_sm_dma_buf_attachment *a;
-+
-+      if (!dmabuf)
-+              return -EFAULT;
-+      buf = dmabuf->priv;
-+      if (!buf)
-+              return -EFAULT;
-+
-+      mutex_lock(&buf->lock);
-+
-+      list_for_each_entry(a, &buf->attachments, list) {
-+              dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
-+                                     direction);
-+      }
-+      mutex_unlock(&buf->lock);
-+
-+      return 0;
-+}
-+
-+static void *vc_sm_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset)
-+{
-+      /* FIXME */
-+      return NULL;
-+}
-+
-+static void vc_sm_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset,
-+                               void *ptr)
-+{
-+      /* FIXME */
-+}
-+
-+static const struct dma_buf_ops dma_buf_ops = {
-+      .map_dma_buf = vc_sm_map_dma_buf,
-+      .unmap_dma_buf = vc_sm_unmap_dma_buf,
-+      .mmap = vc_sm_dmabuf_mmap,
-+      .release = vc_sm_dma_buf_release,
-+      .attach = vc_sm_dma_buf_attach,
-+      .detach = vc_sm_dma_buf_detatch,
-+      .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
-+      .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
-+      .map = vc_sm_dma_buf_kmap,
-+      .unmap = vc_sm_dma_buf_kunmap,
-+};
- /* Dma_buf operations for chaining through to an imported dma_buf */
- static
- int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
-                               struct dma_buf_attachment *attachment)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return -EINVAL;
--      return res->import_dma_buf->ops->attach(res->import_dma_buf,
-+      return buf->import.dma_buf->ops->attach(buf->import.dma_buf,
-                                               attachment);
- }
-@@ -334,22 +636,23 @@ static
- void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
-                                 struct dma_buf_attachment *attachment)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return;
--      res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
-+      buf->import.dma_buf->ops->detach(buf->import.dma_buf, attachment);
- }
- static
- struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
-                                         enum dma_data_direction direction)
- {
--      struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+      struct vc_sm_buffer *buf = attachment->dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return NULL;
--      return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
-+      return buf->import.dma_buf->ops->map_dma_buf(attachment,
-+                                                   direction);
- }
- static
-@@ -357,87 +660,88 @@ void vc_sm_import_unmap_dma_buf(struct d
-                               struct sg_table *table,
-                               enum dma_data_direction direction)
- {
--      struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+      struct vc_sm_buffer *buf = attachment->dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return;
--      res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
-+      buf->import.dma_buf->ops->unmap_dma_buf(attachment, table, direction);
- }
- static
- int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
--      pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
--               dmabuf, res, res->import_dma_buf);
--      if (!res->import_dma_buf) {
-+      pr_debug("%s: mmap dma_buf %p, buf %p, imported db %p\n", __func__,
-+               dmabuf, buf, buf->import.dma_buf);
-+      if (!buf->imported) {
-               pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
-                      __func__, dmabuf);
-               return -EINVAL;
-       }
--      return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
-+      return buf->import.dma_buf->ops->mmap(buf->import.dma_buf, vma);
- }
- static
- void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
-       pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
--      if (!res->import_dma_buf)
-+      mutex_lock(&buf->lock);
-+      if (!buf->imported)
-               return;
--      res->in_use = 0;
-+      buf->in_use = 0;
--      vc_sm_release_resource(res, 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)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return NULL;
--      return res->import_dma_buf->ops->map(res->import_dma_buf,
--                                                    offset);
-+      return buf->import.dma_buf->ops->map(buf->import.dma_buf, offset);
- }
- static
- void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
-                                unsigned long offset, void *ptr)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return;
--      res->import_dma_buf->ops->unmap(res->import_dma_buf,
--                                             offset, ptr);
-+      buf->import.dma_buf->ops->unmap(buf->import.dma_buf, offset, ptr);
- }
- static
- int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
-                                         enum dma_data_direction direction)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return -EINVAL;
--      return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
--                                                          direction);
-+      return buf->import.dma_buf->ops->begin_cpu_access(buf->import.dma_buf,
-+                                                        direction);
- }
- static
- int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
-                                       enum dma_data_direction direction)
- {
--      struct vc_sm_buffer *res = dmabuf->priv;
-+      struct vc_sm_buffer *buf = dmabuf->priv;
--      if (!res->import_dma_buf)
-+      if (!buf->imported)
-               return -EINVAL;
--      return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
-+      return buf->import.dma_buf->ops->end_cpu_access(buf->import.dma_buf,
-                                                         direction);
- }
-@@ -516,9 +820,8 @@ vc_sm_cma_import_dmabuf_internal(struct
-       memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
-              sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
--      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
--               __func__, import.name, import.type, &dma_addr,
--               import.size);
-+      pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u.\n",
-+               __func__, import.name, import.type, &dma_addr, import.size);
-       /* Allocate the videocore buffer. */
-       status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-@@ -548,12 +851,14 @@ vc_sm_cma_import_dmabuf_internal(struct
-       buffer->size = import.size;
-       buffer->vpu_state = VPU_MAPPED;
--      buffer->import_dma_buf = dma_buf;
-+      buffer->imported = 1;
-+      buffer->import.dma_buf = dma_buf;
--      buffer->attach = attach;
--      buffer->sgt = sgt;
-+      buffer->import.attach = attach;
-+      buffer->import.sgt = sgt;
-       buffer->dma_addr = dma_addr;
-       buffer->in_use = 1;
-+      buffer->kernel_id = import.kernel_id;
-       /*
-        * We're done - we need to export a new dmabuf chaining through most
-@@ -594,6 +899,91 @@ error:
-       return ret;
- }
-+static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
-+                             u32 mem_handle, struct vc_sm_buffer **ret_buffer)
-+{
-+      DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-+      struct vc_sm_buffer *buffer = NULL;
-+      int aligned_size;
-+      int ret = 0;
-+
-+      /* Align to the user requested align */
-+      aligned_size = ALIGN(size, align);
-+      /* and then to a page boundary */
-+      aligned_size = PAGE_ALIGN(aligned_size);
-+
-+      if (!aligned_size)
-+              return -EINVAL;
-+
-+      /* Allocate local buffer to track this allocation. */
-+      buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-+      if (!buffer)
-+              return -ENOMEM;
-+
-+      mutex_init(&buffer->lock);
-+
-+      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
-+                                    aligned_size)) {
-+              pr_err("[%s]: cma alloc of %d bytes failed\n",
-+                     __func__, aligned_size);
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+      buffer->sg_table = buffer->alloc.sg_table;
-+
-+      pr_debug("[%s]: cma alloc of %d bytes success\n",
-+               __func__, aligned_size);
-+
-+      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-+                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
-+              pr_err("[%s]: dma_map_sg failed\n", __func__);
-+              goto error;
-+      }
-+
-+      INIT_LIST_HEAD(&buffer->attachments);
-+
-+      memcpy(buffer->name, name,
-+             min(sizeof(buffer->name), strlen(name)));
-+
-+      exp_info.ops = &dma_buf_ops;
-+      exp_info.size = aligned_size;
-+      exp_info.flags = O_RDWR;
-+      exp_info.priv = buffer;
-+
-+      buffer->dma_buf = dma_buf_export(&exp_info);
-+      if (IS_ERR(buffer->dma_buf)) {
-+              ret = PTR_ERR(buffer->dma_buf);
-+              goto error;
-+      }
-+      buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+      if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
-+              pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
-+                     __func__, &buffer->dma_addr);
-+              buffer->dma_addr |= 0xC0000000;
-+      }
-+      buffer->private = sm_state->vpu_allocs;
-+
-+      buffer->vc_handle = mem_handle;
-+      buffer->vpu_state = VPU_MAPPED;
-+      buffer->vpu_allocated = 1;
-+      buffer->size = size;
-+      /*
-+       * Create an ID that will be passed along with our message so
-+       * that when we service the release reply, we can look up which
-+       * resource is being released.
-+       */
-+      buffer->kernel_id = get_kernel_id(buffer);
-+
-+      vc_sm_add_resource(sm_state->vpu_allocs, buffer);
-+
-+      *ret_buffer = buffer;
-+      return 0;
-+error:
-+      if (buffer)
-+              vc_sm_release_resource(buffer);
-+      return ret;
-+}
-+
- static void
- vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
-               int reply_len)
-@@ -612,21 +1002,61 @@ vc_sm_vpu_event(struct sm_instance *inst
-               struct vc_sm_released *release = (struct vc_sm_released *)reply;
-               struct vc_sm_buffer *buffer =
-                                       lookup_kernel_id(release->kernel_id);
-+              if (!buffer) {
-+                      pr_err("%s: VC released a buffer that is already released, kernel_id %d\n",
-+                             __func__, release->kernel_id);
-+                      break;
-+              }
-+              mutex_lock(&buffer->lock);
--              /*
--               * FIXME: Need to check buffer is still valid and allocated
--               * before continuing
--               */
-               pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
-                        __func__, release->addr, release->size,
-                        release->kernel_id, release->vc_handle);
--              mutex_lock(&buffer->lock);
-+
-               buffer->vc_handle = 0;
-               buffer->vpu_state = VPU_NOT_MAPPED;
--              mutex_unlock(&buffer->lock);
-               free_kernel_id(release->kernel_id);
--              vc_sm_release_resource(buffer, 0);
-+              if (buffer->vpu_allocated) {
-+                      /* VPU allocation, so release the dmabuf which will
-+                       * trigger the clean up.
-+                       */
-+                      mutex_unlock(&buffer->lock);
-+                      dma_buf_put(buffer->dma_buf);
-+              } else {
-+                      vc_sm_release_resource(buffer);
-+              }
-+      }
-+      break;
-+      case VC_SM_MSG_TYPE_VC_MEM_REQUEST:
-+      {
-+              struct vc_sm_buffer *buffer = NULL;
-+              struct vc_sm_vc_mem_request *req =
-+                                      (struct vc_sm_vc_mem_request *)reply;
-+              struct vc_sm_vc_mem_request_result reply;
-+              int ret;
-+
-+              pr_debug("%s: Request %u bytes of memory, align %d name %s, trans_id %08x\n",
-+                       __func__, req->size, req->align, req->name,
-+                       req->trans_id);
-+              ret = vc_sm_cma_vpu_alloc(req->size, req->align, req->name,
-+                                        req->vc_handle, &buffer);
-+
-+              reply.trans_id = req->trans_id;
-+              if (!ret) {
-+                      reply.addr = buffer->dma_addr;
-+                      reply.kernel_id = buffer->kernel_id;
-+                      pr_debug("%s: Allocated resource buffer %p, addr %pad\n",
-+                               __func__, buffer, &buffer->dma_addr);
-+              } else {
-+                      pr_err("%s: Allocation failed size %u, name %s, vc_handle %u\n",
-+                             __func__, req->size, req->name, req->vc_handle);
-+                      reply.addr = 0;
-+                      reply.kernel_id = 0;
-+              }
-+              vc_sm_vchi_client_vc_mem_req_reply(sm_state->sm_handle, &reply,
-+                                                 &sm_state->int_trans_id);
-+              break;
-       }
-       break;
-       default:
-@@ -645,6 +1075,14 @@ static void vc_sm_connected_init(void)
-       pr_info("[%s]: start\n", __func__);
-+      if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
-+          !sm_state->cma_heap) {
-+              pr_err("[%s]: failed to initialise CMA heaps\n",
-+                     __func__);
-+              ret = -EIO;
-+              goto err_free_mem;
-+      }
-+
-       /*
-        * Initialize and create a VCHI connection for the shared memory service
-        * running on videocore.
-@@ -696,7 +1134,7 @@ static void vc_sm_connected_init(void)
-               goto err_remove_shared_memory;
-       }
--      version.version = 1;
-+      version.version = 2;
-       ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
-                                           &version_result,
-                                           &sm_state->int_trans_id);
-@@ -768,7 +1206,7 @@ static int bcm2835_vc_sm_cma_remove(stru
- int vc_sm_cma_int_handle(void *handle)
- {
-       struct dma_buf *dma_buf = (struct dma_buf *)handle;
--      struct vc_sm_buffer *res;
-+      struct vc_sm_buffer *buf;
-       /* Validate we can work with this device. */
-       if (!sm_state || !handle) {
-@@ -776,8 +1214,8 @@ int vc_sm_cma_int_handle(void *handle)
-               return 0;
-       }
--      res = (struct vc_sm_buffer *)dma_buf->priv;
--      return res->vc_handle;
-+      buf = (struct vc_sm_buffer *)dma_buf->priv;
-+      return buf->vc_handle;
- }
- EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
-@@ -804,7 +1242,7 @@ EXPORT_SYMBOL_GPL(vc_sm_cma_free);
- int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
- {
-       struct dma_buf *new_dma_buf;
--      struct vc_sm_buffer *res;
-+      struct vc_sm_buffer *buf;
-       int ret;
-       /* Validate we can work with this device. */
-@@ -818,7 +1256,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
-       if (!ret) {
-               pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
--              res = (struct vc_sm_buffer *)new_dma_buf->priv;
-+              buf = (struct vc_sm_buffer *)new_dma_buf->priv;
-               /* Assign valid handle at this time.*/
-               *handle = new_dma_buf;
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-@@ -21,6 +21,8 @@
- #include <linux/types.h>
- #include <linux/miscdevice.h>
-+#include "vc_sm_cma.h"
-+
- #define VC_SM_MAX_NAME_LEN 32
- enum vc_sm_vpu_mapping_state {
-@@ -29,31 +31,51 @@ enum vc_sm_vpu_mapping_state {
-       VPU_UNMAPPING
- };
-+struct vc_sm_imported {
-+      struct dma_buf *dma_buf;
-+      struct dma_buf_attachment *attach;
-+      struct sg_table *sgt;
-+};
-+
- struct vc_sm_buffer {
-       struct list_head global_buffer_list;    /* Global list of buffers. */
-+      /* Index in the kernel_id idr so that we can find the
-+       * mmal_msg_context again when servicing the VCHI reply.
-+       */
-+      int kernel_id;
-+
-       size_t size;
-       /* Lock over all the following state for this buffer */
-       struct mutex lock;
--      struct sg_table *sg_table;
-       struct list_head attachments;
-       char name[VC_SM_MAX_NAME_LEN];
-       int in_use:1;   /* Kernel is still using this resource */
-+      int imported:1; /* Imported dmabuf */
-+
-+      struct sg_table *sg_table;
-       enum vc_sm_vpu_mapping_state vpu_state;
-       u32 vc_handle;  /* VideoCore handle for this buffer */
-+      int vpu_allocated;      /*
-+                               * The VPU made this allocation. Release the
-+                               * local dma_buf when the VPU releases the
-+                               * resource.
-+                               */
-       /* DMABUF related fields */
--      struct dma_buf *import_dma_buf;
-       struct dma_buf *dma_buf;
--      struct dma_buf_attachment *attach;
--      struct sg_table *sgt;
-       dma_addr_t dma_addr;
-       struct vc_sm_privdata_t *private;
-+
-+      union {
-+              struct vc_sm_cma_alloc_data alloc;
-+              struct vc_sm_imported import;
-+      };
- };
- #endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-@@ -0,0 +1,99 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on the Android ION allocator
-+ * Copyright (C) Linaro 2012
-+ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-+ *
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/err.h>
-+#include <linux/cma.h>
-+#include <linux/scatterlist.h>
-+
-+#include "vc_sm_cma.h"
-+
-+/* CMA heap operations functions */
-+int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
-+                            struct vc_sm_cma_alloc_data *buffer,
-+                            unsigned long len)
-+{
-+      /* len should already be page aligned */
-+      unsigned long num_pages = len / PAGE_SIZE;
-+      struct sg_table *table;
-+      struct page *pages;
-+      int ret;
-+
-+      pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
-+      if (!pages)
-+              return -ENOMEM;
-+
-+      table = kmalloc(sizeof(*table), GFP_KERNEL);
-+      if (!table)
-+              goto err;
-+
-+      ret = sg_alloc_table(table, 1, GFP_KERNEL);
-+      if (ret)
-+              goto free_mem;
-+
-+      sg_set_page(table->sgl, pages, len, 0);
-+
-+      buffer->priv_virt = pages;
-+      buffer->sg_table = table;
-+      buffer->cma_heap = cma_heap;
-+      buffer->num_pages = num_pages;
-+      return 0;
-+
-+free_mem:
-+      kfree(table);
-+err:
-+      cma_release(cma_heap, pages, num_pages);
-+      return -ENOMEM;
-+}
-+
-+void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
-+{
-+      struct cma *cma_heap = buffer->cma_heap;
-+      struct page *pages = buffer->priv_virt;
-+
-+      /* release memory */
-+      if (cma_heap)
-+              cma_release(cma_heap, pages, buffer->num_pages);
-+
-+      /* release sg table */
-+      if (buffer->sg_table) {
-+              sg_free_table(buffer->sg_table);
-+              kfree(buffer->sg_table);
-+              buffer->sg_table = NULL;
-+      }
-+}
-+
-+int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
-+{
-+      struct cma **heap = (struct cma **)priv;
-+      const char *name = cma_get_name(cma);
-+
-+      if (!(*heap)) {
-+              phys_addr_t phys_addr = cma_get_base(cma);
-+
-+              pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
-+                       __func__, name, &phys_addr, cma_get_size(cma));
-+              *heap = cma;
-+      } else {
-+              pr_err("%s: Ignoring heap %s as already set\n",
-+                     __func__, name);
-+      }
-+
-+      return 0;
-+}
-+
-+int vc_sm_cma_add_heaps(struct cma **cma_heap)
-+{
-+      cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
-+      return 0;
-+}
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-@@ -0,0 +1,39 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on the Android ION allocator
-+ * Copyright (C) Linaro 2012
-+ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-+ *
-+ * This software is licensed under the terms of the GNU General Public
-+ * License version 2, as published by the Free Software Foundation, and
-+ * may be copied, distributed, and modified under those terms.
-+ *
-+ * 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.
-+ *
-+ */
-+#ifndef VC_SM_CMA_H
-+#define VC_SM_CMA_H
-+
-+struct vc_sm_cma_alloc_data {
-+      struct cma *cma_heap;
-+      unsigned long num_pages;
-+      void *priv_virt;
-+      struct sg_table *sg_table;
-+};
-+
-+int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
-+                            struct vc_sm_cma_alloc_data *buffer,
-+                            unsigned long len);
-+void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
-+
-+int vc_sm_cma_add_heaps(struct cma **cma_heap);
-+
-+#endif
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -500,3 +500,13 @@ int vc_sm_cma_vchi_client_version(struct
-                                  msg, sizeof(*msg), NULL, 0,
-                                  cur_trans_id, 0);
- }
-+
-+int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
-+                                     struct vc_sm_vc_mem_request_result *msg,
-+                                     uint32_t *cur_trans_id)
-+{
-+      return vc_sm_cma_vchi_send_msg(handle,
-+                                     VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
-+                                     msg, sizeof(*msg), 0, 0, cur_trans_id,
-+                                     0);
-+}
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
-@@ -56,4 +56,8 @@ int vc_sm_cma_vchi_client_version(struct
-                                 struct vc_sm_result_t *result,
-                                 u32 *cur_trans_id);
-+int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
-+                                     struct vc_sm_vc_mem_request_result *msg,
-+                                     uint32_t *cur_trans_id);
-+
- #endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
-@@ -264,6 +264,8 @@ struct vc_sm_vc_mem_request {
-       u32 align;
-       /* resource name (for easier tracking) */
-       char     name[VC_SM_RESOURCE_NAME];
-+      /* VPU handle for the resource */
-+      u32 vc_handle;
- };
- /* Response from the kernel to provide the VPU with some memory */
diff --git a/target/linux/brcm2708/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch b/target/linux/brcm2708/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch
new file mode 100644 (file)
index 0000000..53a936e
--- /dev/null
@@ -0,0 +1,675 @@
+From 549c0266e570da686f19e4435d76411cd7137954 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 11 Mar 2019 16:35:23 +0000
+Subject: [PATCH] staging: vc-sm-cma: Add in userspace allocation API
+
+Replacing the functionality from the older vc-sm driver,
+add in a userspace API that allows allocation of buffers,
+and importing of dma-bufs.
+The driver hands out dma-buf fds, therefore much of the
+handling around lifespan and odd mmaps from the old driver
+goes away.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 371 ++++++++++++++++--
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c       |   3 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h       |   2 +-
+ include/linux/broadcom/vc_sm_cma_ioctl.h      |  87 ++++
+ 4 files changed, 435 insertions(+), 28 deletions(-)
+ create mode 100644 include/linux/broadcom/vc_sm_cma_ioctl.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -36,6 +36,7 @@
+ #include <linux/fs.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
++#include <linux/miscdevice.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/of_device.h>
+@@ -52,6 +53,7 @@
+ #include "vc_sm.h"
+ #include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
++#include <linux/broadcom/vc_sm_cma_ioctl.h>
+ /* ---- Private Constants and Types --------------------------------------- */
+@@ -83,6 +85,8 @@ struct sm_pde_t {
+ struct sm_state_t {
+       struct platform_device *pdev;
++      struct miscdevice misc_dev;
++
+       struct sm_instance *sm_handle;  /* Handle for videocore service. */
+       struct cma *cma_heap;
+@@ -346,7 +350,6 @@ static void vc_sm_release_resource(struc
+ defer:
+       mutex_unlock(&buffer->lock);
+-      return;
+ }
+ /* Create support for private data tracking. */
+@@ -381,7 +384,7 @@ static struct sg_table *dup_sg_table(str
+       ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
+       if (ret) {
+               kfree(new_table);
+-              return ERR_PTR(-ENOMEM);
++              return ERR_PTR(ret);
+       }
+       new_sg = new_table->sgl;
+@@ -417,7 +420,7 @@ static int vc_sm_dma_buf_attach(struct d
+       table = dup_sg_table(buf->sg_table);
+       if (IS_ERR(table)) {
+               kfree(a);
+-              return -ENOMEM;
++              return PTR_ERR(table);
+       }
+       a->table = table;
+@@ -433,8 +436,8 @@ static int vc_sm_dma_buf_attach(struct d
+       return 0;
+ }
+-static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
+-                                struct dma_buf_attachment *attachment)
++static void vc_sm_dma_buf_detach(struct dma_buf *dmabuf,
++                               struct dma_buf_attachment *attachment)
+ {
+       struct vc_sm_dma_buf_attachment *a = attachment->priv;
+       struct vc_sm_buffer *buf = dmabuf->priv;
+@@ -544,6 +547,9 @@ static void vc_sm_dma_buf_release(struct
+       vc_sm_clean_up_dmabuf(buffer);
+       pr_debug("%s clean_up dmabuf done\n", __func__);
++      /* buffer->lock will be destroyed by vc_sm_release_resource if finished
++       * with, otherwise unlocked. Do NOT unlock here.
++       */
+       vc_sm_release_resource(buffer);
+       pr_debug("%s done\n", __func__);
+ }
+@@ -613,7 +619,7 @@ static const struct dma_buf_ops dma_buf_
+       .mmap = vc_sm_dmabuf_mmap,
+       .release = vc_sm_dma_buf_release,
+       .attach = vc_sm_dma_buf_attach,
+-      .detach = vc_sm_dma_buf_detatch,
++      .detach = vc_sm_dma_buf_detach,
+       .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
+       .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
+       .map = vc_sm_dma_buf_kmap,
+@@ -762,6 +768,7 @@ static const struct dma_buf_ops dma_buf_
+ int
+ vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
+                                struct dma_buf *dma_buf,
++                               int fd,
+                                struct dma_buf **imported_buf)
+ {
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+@@ -775,10 +782,15 @@ vc_sm_cma_import_dmabuf_internal(struct
+       int status;
+       /* Setup our allocation parameters */
+-      pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
++      pr_debug("%s: importing dma_buf %p/fd %d\n", __func__, dma_buf, fd);
+-      get_dma_buf(dma_buf);
+-      dma_buf = dma_buf;
++      if (fd < 0)
++              get_dma_buf(dma_buf);
++      else
++              dma_buf = dma_buf_get(fd);
++
++      if (!dma_buf)
++              return -EINVAL;
+       attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
+       if (IS_ERR(attach)) {
+@@ -921,6 +933,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+               return -ENOMEM;
+       mutex_init(&buffer->lock);
++      /* Acquire the mutex as vc_sm_release_resource will release it in the
++       * error path.
++       */
++      mutex_lock(&buffer->lock);
+       if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+                                     aligned_size)) {
+@@ -976,6 +992,8 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+       vc_sm_add_resource(sm_state->vpu_allocs, buffer);
++      mutex_unlock(&buffer->lock);
++
+       *ret_buffer = buffer;
+       return 0;
+ error:
+@@ -1065,6 +1083,297 @@ vc_sm_vpu_event(struct sm_instance *inst
+       }
+ }
++/* Userspace handling */
++/*
++ * Open the device.  Creates a private state to help track all allocation
++ * associated with this device.
++ */
++static int vc_sm_cma_open(struct inode *inode, struct file *file)
++{
++      /* Make sure the device was started properly. */
++      if (!sm_state) {
++              pr_err("[%s]: invalid device\n", __func__);
++              return -EPERM;
++      }
++
++      file->private_data = vc_sm_cma_create_priv_data(current->tgid);
++      if (!file->private_data) {
++              pr_err("[%s]: failed to create data tracker\n", __func__);
++
++              return -ENOMEM;
++      }
++
++      return 0;
++}
++
++/*
++ * Close the vcsm-cma device.
++ * All allocations are file descriptors to the dmabuf objects, so we will get
++ * the clean up request on those as those are cleaned up.
++ */
++static int vc_sm_cma_release(struct inode *inode, struct file *file)
++{
++      struct vc_sm_privdata_t *file_data =
++          (struct vc_sm_privdata_t *)file->private_data;
++      int ret = 0;
++
++      /* Make sure the device was started properly. */
++      if (!sm_state || !file_data) {
++              pr_err("[%s]: invalid device\n", __func__);
++              ret = -EPERM;
++              goto out;
++      }
++
++      pr_debug("[%s]: using private data %p\n", __func__, file_data);
++
++      /* Terminate the private data. */
++      kfree(file_data);
++
++out:
++      return ret;
++}
++
++/*
++ * Allocate a shared memory handle and block.
++ * Allocation is from CMA, and then imported into the VPU mappings.
++ */
++int vc_sm_cma_ioctl_alloc(struct vc_sm_privdata_t *private,
++                        struct vc_sm_cma_ioctl_alloc *ioparam)
++{
++      DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
++      struct vc_sm_buffer *buffer = NULL;
++      struct vc_sm_import import = { 0 };
++      struct vc_sm_import_result result = { 0 };
++      struct dma_buf *dmabuf = NULL;
++      int aligned_size;
++      int ret = 0;
++      int status;
++      int fd = -1;
++
++      aligned_size = PAGE_ALIGN(ioparam->size);
++
++      if (!aligned_size)
++              return -EINVAL;
++
++      /* Allocate local buffer to track this allocation. */
++      buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
++      if (!buffer) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
++                                    aligned_size)) {
++              pr_err("[%s]: cma alloc of %d bytes failed\n",
++                     __func__, aligned_size);
++              kfree(buffer);
++              return -ENOMEM;
++      }
++      buffer->sg_table = buffer->alloc.sg_table;
++
++      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
++                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
++              pr_err("[%s]: dma_map_sg failed\n", __func__);
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      import.type = VC_SM_ALLOC_NON_CACHED;
++      import.allocator = current->tgid;
++
++      if (*ioparam->name)
++              memcpy(import.name, ioparam->name, sizeof(import.name) - 1);
++      else
++              memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
++                     sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
++
++      mutex_init(&buffer->lock);
++      INIT_LIST_HEAD(&buffer->attachments);
++      memcpy(buffer->name, import.name,
++             min(sizeof(buffer->name), sizeof(import.name) - 1));
++
++      exp_info.ops = &dma_buf_ops;
++      exp_info.size = aligned_size;
++      exp_info.flags = O_RDWR;
++      exp_info.priv = buffer;
++
++      dmabuf = dma_buf_export(&exp_info);
++      if (IS_ERR(dmabuf)) {
++              ret = PTR_ERR(dmabuf);
++              goto error;
++      }
++      buffer->dma_buf = dmabuf;
++
++      import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++      import.size = aligned_size;
++      import.kernel_id = (uint32_t)buffer;
++
++      /* Wrap it into a videocore buffer. */
++      status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
++                                     &sm_state->int_trans_id);
++      if (status == -EINTR) {
++              pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
++                       __func__, sm_state->int_trans_id);
++              ret = -ERESTARTSYS;
++              private->restart_sys = -EINTR;
++              private->int_action = VC_SM_MSG_TYPE_IMPORT;
++              goto error;
++      } else if (status || !result.res_handle) {
++              pr_err("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
++                     __func__, status, sm_state->int_trans_id);
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      /* Keep track of the buffer we created. */
++      buffer->private = private;
++      buffer->vc_handle = result.res_handle;
++      buffer->size = import.size;
++      buffer->dma_addr = import.addr;
++      buffer->vpu_state = VPU_MAPPED;
++      //buffer->res_cached = ioparam->cached;
++
++      fd = dma_buf_fd(dmabuf, O_CLOEXEC);
++      if (fd < 0)
++              goto error;
++
++      vc_sm_add_resource(private, buffer);
++
++      pr_debug("[%s]: Added resource as fd %d, buffer %p, private %p, dma_addr %pad\n",
++               __func__, fd, buffer, private, &buffer->dma_addr);
++
++      /* We're done */
++      ioparam->handle = fd;
++      ioparam->vc_handle = buffer->vc_handle;
++      ioparam->dma_addr = buffer->dma_addr;
++      return 0;
++
++error:
++      if (buffer) {
++              pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
++                     ret);
++
++              dma_buf_put(dmabuf);
++      }
++      return ret;
++}
++
++static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
++                          unsigned long arg)
++{
++      int ret = 0;
++      unsigned int cmdnr = _IOC_NR(cmd);
++      struct vc_sm_privdata_t *file_data =
++          (struct vc_sm_privdata_t *)file->private_data;
++
++      /* Validate we can work with this device. */
++      if (!sm_state || !file_data) {
++              pr_err("[%s]: invalid device\n", __func__);
++              return -EPERM;
++      }
++
++      pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
++               current->tgid, file_data->pid);
++
++      /* Action is a re-post of a previously interrupted action? */
++      if (file_data->restart_sys == -EINTR) {
++              struct vc_sm_action_clean_t action_clean;
++
++              pr_debug("[%s]: clean up of action %u (trans_id: %u) following EINTR\n",
++                       __func__, file_data->int_action,
++                       file_data->int_trans_id);
++
++              action_clean.res_action = file_data->int_action;
++              action_clean.action_trans_id = file_data->int_trans_id;
++
++              file_data->restart_sys = 0;
++      }
++
++      /* Now process the command. */
++      switch (cmdnr) {
++              /* New memory allocation.
++               */
++      case VC_SM_CMA_CMD_ALLOC:
++      {
++              struct vc_sm_cma_ioctl_alloc ioparam;
++
++              /* Get the parameter data. */
++              if (copy_from_user
++                  (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++                      pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++                             __func__, cmdnr);
++                      ret = -EFAULT;
++                      break;
++              }
++
++              ret = vc_sm_cma_ioctl_alloc(file_data, &ioparam);
++              if (!ret &&
++                  (copy_to_user((void *)arg, &ioparam,
++                                sizeof(ioparam)) != 0)) {
++                      /* FIXME: Release allocation */
++                      pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++                             __func__, cmdnr);
++                      ret = -EFAULT;
++              }
++              break;
++      }
++
++      case VC_SM_CMA_CMD_IMPORT_DMABUF:
++      {
++              struct vc_sm_cma_ioctl_import_dmabuf ioparam;
++              struct dma_buf *new_dmabuf;
++
++              /* Get the parameter data. */
++              if (copy_from_user
++                  (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++                      pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++                             __func__, cmdnr);
++                      ret = -EFAULT;
++                      break;
++              }
++
++              ret = vc_sm_cma_import_dmabuf_internal(file_data,
++                                                     NULL,
++                                                     ioparam.dmabuf_fd,
++                                                     &new_dmabuf);
++
++              if (!ret) {
++                      struct vc_sm_buffer *buf = new_dmabuf->priv;
++
++                      ioparam.size = buf->size;
++                      ioparam.handle = dma_buf_fd(new_dmabuf,
++                                                  O_CLOEXEC);
++                      ioparam.vc_handle = buf->vc_handle;
++                      ioparam.dma_addr = buf->dma_addr;
++
++                      if (ioparam.handle < 0 ||
++                          (copy_to_user((void *)arg, &ioparam,
++                                        sizeof(ioparam)) != 0)) {
++                              dma_buf_put(new_dmabuf);
++                              /* FIXME: Release allocation */
++                              ret = -EFAULT;
++                      }
++              }
++              break;
++      }
++
++      default:
++              ret = -EINVAL;
++              break;
++      }
++
++      return ret;
++}
++
++/* Device operations that we managed in this driver. */
++static const struct file_operations vc_sm_ops = {
++      .owner = THIS_MODULE,
++      .unlocked_ioctl = vc_sm_cma_ioctl,
++      .open = vc_sm_cma_open,
++      .release = vc_sm_cma_release,
++};
++
++/* Driver load/unload functions */
+ /* Videocore connected.  */
+ static void vc_sm_connected_init(void)
+ {
+@@ -1075,12 +1384,11 @@ static void vc_sm_connected_init(void)
+       pr_info("[%s]: start\n", __func__);
+-      if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
+-          !sm_state->cma_heap) {
+-              pr_err("[%s]: failed to initialise CMA heaps\n",
++      vc_sm_cma_add_heaps(&sm_state->cma_heap);
++      if (!sm_state->cma_heap) {
++              pr_err("[%s]: failed to initialise CMA heap\n",
+                      __func__);
+-              ret = -EIO;
+-              goto err_free_mem;
++              return;
+       }
+       /*
+@@ -1092,8 +1400,7 @@ static void vc_sm_connected_init(void)
+               pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
+                      __func__, ret);
+-              ret = -EIO;
+-              goto err_failed;
++              return;
+       }
+       ret = vchi_connect(NULL, 0, vchi_instance);
+@@ -1101,8 +1408,7 @@ static void vc_sm_connected_init(void)
+               pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
+                      __func__, ret);
+-              ret = -EIO;
+-              goto err_failed;
++              return;
+       }
+       /* Initialize an instance of the shared memory service. */
+@@ -1112,8 +1418,7 @@ static void vc_sm_connected_init(void)
+               pr_err("[%s]: failed to initialize shared memory service\n",
+                      __func__);
+-              ret = -EPERM;
+-              goto err_failed;
++              return;
+       }
+       /* Create a debug fs directory entry (root). */
+@@ -1127,11 +1432,22 @@ static void vc_sm_connected_init(void)
+       INIT_LIST_HEAD(&sm_state->buffer_list);
++      /* Create a shared memory device. */
++      sm_state->misc_dev.minor = MISC_DYNAMIC_MINOR;
++      sm_state->misc_dev.name = DEVICE_NAME;
++      sm_state->misc_dev.fops = &vc_sm_ops;
++      sm_state->misc_dev.parent = NULL;
++      ret = misc_register(&sm_state->misc_dev);
++      if (ret) {
++              pr_err("vcsm-cma: failed to register misc device.\n");
++              goto err_remove_debugfs;
++      }
++
+       sm_state->data_knl = vc_sm_cma_create_priv_data(0);
+       if (!sm_state->data_knl) {
+               pr_err("[%s]: failed to create kernel private data tracker\n",
+                      __func__);
+-              goto err_remove_shared_memory;
++              goto err_remove_misc_dev;
+       }
+       version.version = 2;
+@@ -1148,11 +1464,13 @@ static void vc_sm_connected_init(void)
+       pr_info("[%s]: installed successfully\n", __func__);
+       return;
+-err_remove_shared_memory:
++err_remove_misc_dev:
++      misc_deregister(&sm_state->misc_dev);
++err_remove_debugfs:
+       debugfs_remove_recursive(sm_state->dir_root);
+       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+-err_failed:
+-      pr_info("[%s]: failed, ret %d\n", __func__, ret);
++
++      return;
+ }
+ /* Driver loading. */
+@@ -1184,6 +1502,8 @@ static int bcm2835_vc_sm_cma_remove(stru
+ {
+       pr_debug("[%s]: start\n", __func__);
+       if (sm_inited) {
++              misc_deregister(&sm_state->misc_dev);
++
+               /* Remove all proc entries. */
+               debugfs_remove_recursive(sm_state->dir_root);
+@@ -1202,6 +1522,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+       return 0;
+ }
++/* Kernel API calls */
+ /* Get an internal resource handle mapped from the external one. */
+ int vc_sm_cma_int_handle(void *handle)
+ {
+@@ -1252,7 +1573,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
+       }
+       ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
+-                                             &new_dma_buf);
++                                             -1, &new_dma_buf);
+       if (!ret) {
+               pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+@@ -92,8 +92,7 @@ int __vc_sm_cma_add_heaps(struct cma *cm
+       return 0;
+ }
+-int vc_sm_cma_add_heaps(struct cma **cma_heap)
++void vc_sm_cma_add_heaps(struct cma **cma_heap)
+ {
+       cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
+-      return 0;
+ }
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+@@ -34,6 +34,6 @@ int vc_sm_cma_buffer_allocate(struct cma
+                             unsigned long len);
+ void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
+-int vc_sm_cma_add_heaps(struct cma **cma_heap);
++void vc_sm_cma_add_heaps(struct cma **cma_heap);
+ #endif
+--- /dev/null
++++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
+@@ -0,0 +1,87 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * Copyright 2019 Raspberry Pi (Trading) Ltd.  All rights reserved.
++ *
++ * Based on vmcs_sm_ioctl.h Copyright Broadcom Corporation.
++ */
++
++#ifndef __VC_SM_CMA_IOCTL_H
++#define __VC_SM_CMA_IOCTL_H
++
++/* ---- Include Files ---------------------------------------------------- */
++
++#if defined(__KERNEL__)
++#include <linux/types.h>      /* Needed for standard types */
++#else
++#include <stdint.h>
++#endif
++
++#include <linux/ioctl.h>
++
++/* ---- Constants and Types ---------------------------------------------- */
++
++#define VC_SM_CMA_RESOURCE_NAME               32
++#define VC_SM_CMA_RESOURCE_NAME_DEFAULT       "sm-host-resource"
++
++/* Type define used to create unique IOCTL number */
++#define VC_SM_CMA_MAGIC_TYPE                  'J'
++
++/* IOCTL commands on /dev/vc-sm-cma */
++enum vc_sm_cma_cmd_e {
++      VC_SM_CMA_CMD_ALLOC = 0x5A,     /* Start at 0x5A arbitrarily */
++
++      VC_SM_CMA_CMD_IMPORT_DMABUF,
++
++      VC_SM_CMA_CMD_LAST      /* Do not delete */
++};
++
++/* Cache type supported, conveniently matches the user space definition in
++ * user-vcsm.h.
++ */
++enum vc_sm_cma_cache_e {
++      VC_SM_CMA_CACHE_NONE,
++      VC_SM_CMA_CACHE_HOST,
++      VC_SM_CMA_CACHE_VC,
++      VC_SM_CMA_CACHE_BOTH,
++};
++
++/* IOCTL Data structures */
++struct vc_sm_cma_ioctl_alloc {
++      /* user -> kernel */
++      __u32 size;
++      __u32 num;
++      __u32 cached;           /* enum vc_sm_cma_cache_e */
++      __u32 pad;
++      __u8 name[VC_SM_CMA_RESOURCE_NAME];
++
++      /* kernel -> user */
++      __s32 handle;
++      __u32 vc_handle;
++      __u64 dma_addr;
++};
++
++struct vc_sm_cma_ioctl_import_dmabuf {
++      /* user -> kernel */
++      __s32 dmabuf_fd;
++      __u32 cached;           /* enum vc_sm_cma_cache_e */
++      __u8 name[VC_SM_CMA_RESOURCE_NAME];
++
++      /* kernel -> user */
++      __s32 handle;
++      __u32 vc_handle;
++      __u32 size;
++      __u32 pad;
++      __u64 dma_addr;
++};
++
++/* IOCTL numbers */
++#define VC_SM_CMA_IOCTL_MEM_ALLOC\
++      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
++       struct vc_sm_cma_ioctl_alloc)
++
++#define VC_SM_CMA_IOCTL_MEM_IMPORT_DMABUF\
++      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
++       struct vc_sm_cma_ioctl_import_dmabuf)
++
++#endif /* __VC_SM_CMA_IOCTL_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0551-staging-vc-sm-cma-Update-TODO.patch b/target/linux/brcm2708/patches-4.19/950-0551-staging-vc-sm-cma-Update-TODO.patch
deleted file mode 100644 (file)
index c4d303a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From 753e73267994a88505b6883cdf463d1d0bacf090 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 11 Mar 2019 16:38:32 +0000
-Subject: [PATCH] staging: vc-sm-cma: Update TODO.
-
-The driver is already a platform driver, so that can be
-deleted from the TODO.
-There are no known issues that need to be resolved.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/TODO | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/TODO
-+++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
-@@ -1,2 +1 @@
--1) Convert to a platform driver.
--
-+No currently outstanding tasks except some clean-up.
diff --git a/target/linux/brcm2708/patches-4.19/950-0551-staging-vcsm-cma-Add-cache-control-ioctls.patch b/target/linux/brcm2708/patches-4.19/950-0551-staging-vcsm-cma-Add-cache-control-ioctls.patch
new file mode 100644 (file)
index 0000000..500ec5f
--- /dev/null
@@ -0,0 +1,245 @@
+From b17f6dc1d79ae057294ac2d8d824aa2258ab09a8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 20 Mar 2019 10:40:00 +0000
+Subject: [PATCH] staging: vcsm-cma: Add cache control ioctls
+
+The old driver allowed for direct cache manipulation and that
+was used by various clients. Replicate here.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 141 +++++++++++++++++-
+ include/linux/broadcom/vc_sm_cma_ioctl.h      |  27 ++++
+ 2 files changed, 165 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -46,6 +46,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/syscalls.h>
+ #include <linux/types.h>
++#include <asm/cacheflush.h>
+ #include "vchiq_connected.h"
+ #include "vc_sm_cma_vchi.h"
+@@ -1258,6 +1259,99 @@ error:
+       return ret;
+ }
++/* Converts VCSM_CACHE_OP_* to an operating function. */
++static void (*cache_op_to_func(const unsigned int cache_op))
++                                              (const void*, const void*)
++{
++      switch (cache_op) {
++      case VC_SM_CACHE_OP_NOP:
++              return NULL;
++
++      case VC_SM_CACHE_OP_INV:
++              return dmac_inv_range;
++
++      case VC_SM_CACHE_OP_CLEAN:
++              return dmac_clean_range;
++
++      case VC_SM_CACHE_OP_FLUSH:
++              return dmac_flush_range;
++
++      default:
++              pr_err("[%s]: Invalid cache_op: 0x%08x\n", __func__, cache_op);
++              return NULL;
++      }
++}
++
++/*
++ * Clean/invalid/flush cache of which buffer is already pinned (i.e. accessed).
++ */
++static int clean_invalid_contig_2d(const void __user *addr,
++                                 const size_t block_count,
++                                 const size_t block_size,
++                                 const size_t stride,
++                                 const unsigned int cache_op)
++{
++      size_t i;
++      void (*op_fn)(const void *start, const void *end);
++
++      if (!block_size) {
++              pr_err("[%s]: size cannot be 0\n", __func__);
++              return -EINVAL;
++      }
++
++      op_fn = cache_op_to_func(cache_op);
++      if (!op_fn)
++              return -EINVAL;
++
++      for (i = 0; i < block_count; i ++, addr += stride)
++              op_fn(addr, addr + block_size);
++
++      return 0;
++}
++
++static int vc_sm_cma_clean_invalid2(unsigned int cmdnr, unsigned long arg)
++{
++      struct vc_sm_cma_ioctl_clean_invalid2 ioparam;
++      struct vc_sm_cma_ioctl_clean_invalid_block *block = NULL;
++      int i, ret = 0;
++
++      /* Get parameter data. */
++      if (copy_from_user(&ioparam, (void *)arg, sizeof(ioparam))) {
++              pr_err("[%s]: failed to copy-from-user header for cmd %x\n",
++                     __func__, cmdnr);
++              return -EFAULT;
++      }
++      block = kmalloc(ioparam.op_count * sizeof(*block), GFP_KERNEL);
++      if (!block)
++              return -EFAULT;
++
++      if (copy_from_user(block, (void *)(arg + sizeof(ioparam)),
++                         ioparam.op_count * sizeof(*block)) != 0) {
++              pr_err("[%s]: failed to copy-from-user payload for cmd %x\n",
++                     __func__, cmdnr);
++              ret = -EFAULT;
++              goto out;
++      }
++
++      for (i = 0; i < ioparam.op_count; i++) {
++              const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
++
++              if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
++                      continue;
++
++              ret = clean_invalid_contig_2d((void __user *)op->start_address,
++                                            op->block_count, op->block_size,
++                                            op->inter_block_stride,
++                                            op->invalidate_mode);
++              if (ret)
++                      break;
++      }
++out:
++      kfree(block);
++
++      return ret;
++}
++
+ static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
+                           unsigned long arg)
+ {
+@@ -1272,9 +1366,6 @@ static long vc_sm_cma_ioctl(struct file
+               return -EPERM;
+       }
+-      pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
+-               current->tgid, file_data->pid);
+-
+       /* Action is a re-post of a previously interrupted action? */
+       if (file_data->restart_sys == -EINTR) {
+               struct vc_sm_action_clean_t action_clean;
+@@ -1357,7 +1448,18 @@ static long vc_sm_cma_ioctl(struct file
+               break;
+       }
++      /*
++       * Flush/Invalidate the cache for a given mapping.
++       * Blocks must be pinned (i.e. accessed) before this call.
++       */
++      case VC_SM_CMA_CMD_CLEAN_INVALID2:
++              ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
++              break;
++
+       default:
++              pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
++                       current->tgid, file_data->pid);
++
+               ret = -EINVAL;
+               break;
+       }
+@@ -1365,10 +1467,43 @@ static long vc_sm_cma_ioctl(struct file
+       return ret;
+ }
++#ifdef CONFIG_COMPAT
++struct vc_sm_cma_ioctl_clean_invalid2_32 {
++      u32 op_count;
++      struct vc_sm_cma_ioctl_clean_invalid_block {
++              u16 invalidate_mode;
++              u16 block_count;
++              compat_uptr_t start_address;
++              u32 block_size;
++              u32 inter_block_stride;
++      } s[0];
++};
++
++#define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
++      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
++       struct vc_sm_cma_ioctl_clean_invalid2)
++
++static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
++                                 unsigned long arg)
++{
++      switch (cmd) {
++      case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
++              /* FIXME */
++              break;
++
++      default:
++              return vc_sm_cma_compat_ioctl(file, cmd, arg);
++      }
++}
++#endif
++
+ /* Device operations that we managed in this driver. */
+ static const struct file_operations vc_sm_ops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = vc_sm_cma_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl = vc_sm_cma_compat_ioctl,
++#endif
+       .open = vc_sm_cma_open,
+       .release = vc_sm_cma_release,
+ };
+--- a/include/linux/broadcom/vc_sm_cma_ioctl.h
++++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
+@@ -33,6 +33,8 @@ enum vc_sm_cma_cmd_e {
+       VC_SM_CMA_CMD_IMPORT_DMABUF,
++      VC_SM_CMA_CMD_CLEAN_INVALID2,
++
+       VC_SM_CMA_CMD_LAST      /* Do not delete */
+ };
+@@ -75,6 +77,27 @@ struct vc_sm_cma_ioctl_import_dmabuf {
+       __u64 dma_addr;
+ };
++/*
++ * Cache functions to be set to struct vc_sm_cma_ioctl_clean_invalid2
++ * invalidate_mode.
++ */
++#define VC_SM_CACHE_OP_NOP       0x00
++#define VC_SM_CACHE_OP_INV       0x01
++#define VC_SM_CACHE_OP_CLEAN     0x02
++#define VC_SM_CACHE_OP_FLUSH     0x03
++
++struct vc_sm_cma_ioctl_clean_invalid2 {
++      __u32 op_count;
++      __u32 pad;
++      struct vc_sm_cma_ioctl_clean_invalid_block {
++              __u32 invalidate_mode;
++              __u32 block_count;
++              void *  __user start_address;
++              __u32 block_size;
++              __u32 inter_block_stride;
++      } s[0];
++};
++
+ /* IOCTL numbers */
+ #define VC_SM_CMA_IOCTL_MEM_ALLOC\
+       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
+@@ -84,4 +107,8 @@ struct vc_sm_cma_ioctl_import_dmabuf {
+       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
+        struct vc_sm_cma_ioctl_import_dmabuf)
++#define VC_SM_CMA_IOCTL_MEM_CLEAN_INVALID2\
++      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
++       struct vc_sm_cma_ioctl_clean_invalid2)
++
+ #endif /* __VC_SM_CMA_IOCTL_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0552-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch b/target/linux/brcm2708/patches-4.19/950-0552-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch
deleted file mode 100644 (file)
index 53a936e..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-From 549c0266e570da686f19e4435d76411cd7137954 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 11 Mar 2019 16:35:23 +0000
-Subject: [PATCH] staging: vc-sm-cma: Add in userspace allocation API
-
-Replacing the functionality from the older vc-sm driver,
-add in a userspace API that allows allocation of buffers,
-and importing of dma-bufs.
-The driver hands out dma-buf fds, therefore much of the
-handling around lifespan and odd mmaps from the old driver
-goes away.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 371 ++++++++++++++++--
- .../vc04_services/vc-sm-cma/vc_sm_cma.c       |   3 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma.h       |   2 +-
- include/linux/broadcom/vc_sm_cma_ioctl.h      |  87 ++++
- 4 files changed, 435 insertions(+), 28 deletions(-)
- create mode 100644 include/linux/broadcom/vc_sm_cma_ioctl.h
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -36,6 +36,7 @@
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
-+#include <linux/miscdevice.h>
- #include <linux/module.h>
- #include <linux/mm.h>
- #include <linux/of_device.h>
-@@ -52,6 +53,7 @@
- #include "vc_sm.h"
- #include "vc_sm_cma.h"
- #include "vc_sm_knl.h"
-+#include <linux/broadcom/vc_sm_cma_ioctl.h>
- /* ---- Private Constants and Types --------------------------------------- */
-@@ -83,6 +85,8 @@ struct sm_pde_t {
- struct sm_state_t {
-       struct platform_device *pdev;
-+      struct miscdevice misc_dev;
-+
-       struct sm_instance *sm_handle;  /* Handle for videocore service. */
-       struct cma *cma_heap;
-@@ -346,7 +350,6 @@ static void vc_sm_release_resource(struc
- defer:
-       mutex_unlock(&buffer->lock);
--      return;
- }
- /* Create support for private data tracking. */
-@@ -381,7 +384,7 @@ static struct sg_table *dup_sg_table(str
-       ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
-       if (ret) {
-               kfree(new_table);
--              return ERR_PTR(-ENOMEM);
-+              return ERR_PTR(ret);
-       }
-       new_sg = new_table->sgl;
-@@ -417,7 +420,7 @@ static int vc_sm_dma_buf_attach(struct d
-       table = dup_sg_table(buf->sg_table);
-       if (IS_ERR(table)) {
-               kfree(a);
--              return -ENOMEM;
-+              return PTR_ERR(table);
-       }
-       a->table = table;
-@@ -433,8 +436,8 @@ static int vc_sm_dma_buf_attach(struct d
-       return 0;
- }
--static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
--                                struct dma_buf_attachment *attachment)
-+static void vc_sm_dma_buf_detach(struct dma_buf *dmabuf,
-+                               struct dma_buf_attachment *attachment)
- {
-       struct vc_sm_dma_buf_attachment *a = attachment->priv;
-       struct vc_sm_buffer *buf = dmabuf->priv;
-@@ -544,6 +547,9 @@ static void vc_sm_dma_buf_release(struct
-       vc_sm_clean_up_dmabuf(buffer);
-       pr_debug("%s clean_up dmabuf done\n", __func__);
-+      /* buffer->lock will be destroyed by vc_sm_release_resource if finished
-+       * with, otherwise unlocked. Do NOT unlock here.
-+       */
-       vc_sm_release_resource(buffer);
-       pr_debug("%s done\n", __func__);
- }
-@@ -613,7 +619,7 @@ static const struct dma_buf_ops dma_buf_
-       .mmap = vc_sm_dmabuf_mmap,
-       .release = vc_sm_dma_buf_release,
-       .attach = vc_sm_dma_buf_attach,
--      .detach = vc_sm_dma_buf_detatch,
-+      .detach = vc_sm_dma_buf_detach,
-       .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
-       .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
-       .map = vc_sm_dma_buf_kmap,
-@@ -762,6 +768,7 @@ static const struct dma_buf_ops dma_buf_
- int
- vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
-                                struct dma_buf *dma_buf,
-+                               int fd,
-                                struct dma_buf **imported_buf)
- {
-       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-@@ -775,10 +782,15 @@ vc_sm_cma_import_dmabuf_internal(struct
-       int status;
-       /* Setup our allocation parameters */
--      pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
-+      pr_debug("%s: importing dma_buf %p/fd %d\n", __func__, dma_buf, fd);
--      get_dma_buf(dma_buf);
--      dma_buf = dma_buf;
-+      if (fd < 0)
-+              get_dma_buf(dma_buf);
-+      else
-+              dma_buf = dma_buf_get(fd);
-+
-+      if (!dma_buf)
-+              return -EINVAL;
-       attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
-       if (IS_ERR(attach)) {
-@@ -921,6 +933,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
-               return -ENOMEM;
-       mutex_init(&buffer->lock);
-+      /* Acquire the mutex as vc_sm_release_resource will release it in the
-+       * error path.
-+       */
-+      mutex_lock(&buffer->lock);
-       if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
-                                     aligned_size)) {
-@@ -976,6 +992,8 @@ static int vc_sm_cma_vpu_alloc(u32 size,
-       vc_sm_add_resource(sm_state->vpu_allocs, buffer);
-+      mutex_unlock(&buffer->lock);
-+
-       *ret_buffer = buffer;
-       return 0;
- error:
-@@ -1065,6 +1083,297 @@ vc_sm_vpu_event(struct sm_instance *inst
-       }
- }
-+/* Userspace handling */
-+/*
-+ * Open the device.  Creates a private state to help track all allocation
-+ * associated with this device.
-+ */
-+static int vc_sm_cma_open(struct inode *inode, struct file *file)
-+{
-+      /* Make sure the device was started properly. */
-+      if (!sm_state) {
-+              pr_err("[%s]: invalid device\n", __func__);
-+              return -EPERM;
-+      }
-+
-+      file->private_data = vc_sm_cma_create_priv_data(current->tgid);
-+      if (!file->private_data) {
-+              pr_err("[%s]: failed to create data tracker\n", __func__);
-+
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * Close the vcsm-cma device.
-+ * All allocations are file descriptors to the dmabuf objects, so we will get
-+ * the clean up request on those as those are cleaned up.
-+ */
-+static int vc_sm_cma_release(struct inode *inode, struct file *file)
-+{
-+      struct vc_sm_privdata_t *file_data =
-+          (struct vc_sm_privdata_t *)file->private_data;
-+      int ret = 0;
-+
-+      /* Make sure the device was started properly. */
-+      if (!sm_state || !file_data) {
-+              pr_err("[%s]: invalid device\n", __func__);
-+              ret = -EPERM;
-+              goto out;
-+      }
-+
-+      pr_debug("[%s]: using private data %p\n", __func__, file_data);
-+
-+      /* Terminate the private data. */
-+      kfree(file_data);
-+
-+out:
-+      return ret;
-+}
-+
-+/*
-+ * Allocate a shared memory handle and block.
-+ * Allocation is from CMA, and then imported into the VPU mappings.
-+ */
-+int vc_sm_cma_ioctl_alloc(struct vc_sm_privdata_t *private,
-+                        struct vc_sm_cma_ioctl_alloc *ioparam)
-+{
-+      DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-+      struct vc_sm_buffer *buffer = NULL;
-+      struct vc_sm_import import = { 0 };
-+      struct vc_sm_import_result result = { 0 };
-+      struct dma_buf *dmabuf = NULL;
-+      int aligned_size;
-+      int ret = 0;
-+      int status;
-+      int fd = -1;
-+
-+      aligned_size = PAGE_ALIGN(ioparam->size);
-+
-+      if (!aligned_size)
-+              return -EINVAL;
-+
-+      /* Allocate local buffer to track this allocation. */
-+      buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-+      if (!buffer) {
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
-+                                    aligned_size)) {
-+              pr_err("[%s]: cma alloc of %d bytes failed\n",
-+                     __func__, aligned_size);
-+              kfree(buffer);
-+              return -ENOMEM;
-+      }
-+      buffer->sg_table = buffer->alloc.sg_table;
-+
-+      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-+                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
-+              pr_err("[%s]: dma_map_sg failed\n", __func__);
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      import.type = VC_SM_ALLOC_NON_CACHED;
-+      import.allocator = current->tgid;
-+
-+      if (*ioparam->name)
-+              memcpy(import.name, ioparam->name, sizeof(import.name) - 1);
-+      else
-+              memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
-+                     sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
-+
-+      mutex_init(&buffer->lock);
-+      INIT_LIST_HEAD(&buffer->attachments);
-+      memcpy(buffer->name, import.name,
-+             min(sizeof(buffer->name), sizeof(import.name) - 1));
-+
-+      exp_info.ops = &dma_buf_ops;
-+      exp_info.size = aligned_size;
-+      exp_info.flags = O_RDWR;
-+      exp_info.priv = buffer;
-+
-+      dmabuf = dma_buf_export(&exp_info);
-+      if (IS_ERR(dmabuf)) {
-+              ret = PTR_ERR(dmabuf);
-+              goto error;
-+      }
-+      buffer->dma_buf = dmabuf;
-+
-+      import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+      import.size = aligned_size;
-+      import.kernel_id = (uint32_t)buffer;
-+
-+      /* Wrap it into a videocore buffer. */
-+      status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-+                                     &sm_state->int_trans_id);
-+      if (status == -EINTR) {
-+              pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
-+                       __func__, sm_state->int_trans_id);
-+              ret = -ERESTARTSYS;
-+              private->restart_sys = -EINTR;
-+              private->int_action = VC_SM_MSG_TYPE_IMPORT;
-+              goto error;
-+      } else if (status || !result.res_handle) {
-+              pr_err("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
-+                     __func__, status, sm_state->int_trans_id);
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      /* Keep track of the buffer we created. */
-+      buffer->private = private;
-+      buffer->vc_handle = result.res_handle;
-+      buffer->size = import.size;
-+      buffer->dma_addr = import.addr;
-+      buffer->vpu_state = VPU_MAPPED;
-+      //buffer->res_cached = ioparam->cached;
-+
-+      fd = dma_buf_fd(dmabuf, O_CLOEXEC);
-+      if (fd < 0)
-+              goto error;
-+
-+      vc_sm_add_resource(private, buffer);
-+
-+      pr_debug("[%s]: Added resource as fd %d, buffer %p, private %p, dma_addr %pad\n",
-+               __func__, fd, buffer, private, &buffer->dma_addr);
-+
-+      /* We're done */
-+      ioparam->handle = fd;
-+      ioparam->vc_handle = buffer->vc_handle;
-+      ioparam->dma_addr = buffer->dma_addr;
-+      return 0;
-+
-+error:
-+      if (buffer) {
-+              pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
-+                     ret);
-+
-+              dma_buf_put(dmabuf);
-+      }
-+      return ret;
-+}
-+
-+static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
-+                          unsigned long arg)
-+{
-+      int ret = 0;
-+      unsigned int cmdnr = _IOC_NR(cmd);
-+      struct vc_sm_privdata_t *file_data =
-+          (struct vc_sm_privdata_t *)file->private_data;
-+
-+      /* Validate we can work with this device. */
-+      if (!sm_state || !file_data) {
-+              pr_err("[%s]: invalid device\n", __func__);
-+              return -EPERM;
-+      }
-+
-+      pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
-+               current->tgid, file_data->pid);
-+
-+      /* Action is a re-post of a previously interrupted action? */
-+      if (file_data->restart_sys == -EINTR) {
-+              struct vc_sm_action_clean_t action_clean;
-+
-+              pr_debug("[%s]: clean up of action %u (trans_id: %u) following EINTR\n",
-+                       __func__, file_data->int_action,
-+                       file_data->int_trans_id);
-+
-+              action_clean.res_action = file_data->int_action;
-+              action_clean.action_trans_id = file_data->int_trans_id;
-+
-+              file_data->restart_sys = 0;
-+      }
-+
-+      /* Now process the command. */
-+      switch (cmdnr) {
-+              /* New memory allocation.
-+               */
-+      case VC_SM_CMA_CMD_ALLOC:
-+      {
-+              struct vc_sm_cma_ioctl_alloc ioparam;
-+
-+              /* Get the parameter data. */
-+              if (copy_from_user
-+                  (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
-+                      pr_err("[%s]: failed to copy-from-user for cmd %x\n",
-+                             __func__, cmdnr);
-+                      ret = -EFAULT;
-+                      break;
-+              }
-+
-+              ret = vc_sm_cma_ioctl_alloc(file_data, &ioparam);
-+              if (!ret &&
-+                  (copy_to_user((void *)arg, &ioparam,
-+                                sizeof(ioparam)) != 0)) {
-+                      /* FIXME: Release allocation */
-+                      pr_err("[%s]: failed to copy-to-user for cmd %x\n",
-+                             __func__, cmdnr);
-+                      ret = -EFAULT;
-+              }
-+              break;
-+      }
-+
-+      case VC_SM_CMA_CMD_IMPORT_DMABUF:
-+      {
-+              struct vc_sm_cma_ioctl_import_dmabuf ioparam;
-+              struct dma_buf *new_dmabuf;
-+
-+              /* Get the parameter data. */
-+              if (copy_from_user
-+                  (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
-+                      pr_err("[%s]: failed to copy-from-user for cmd %x\n",
-+                             __func__, cmdnr);
-+                      ret = -EFAULT;
-+                      break;
-+              }
-+
-+              ret = vc_sm_cma_import_dmabuf_internal(file_data,
-+                                                     NULL,
-+                                                     ioparam.dmabuf_fd,
-+                                                     &new_dmabuf);
-+
-+              if (!ret) {
-+                      struct vc_sm_buffer *buf = new_dmabuf->priv;
-+
-+                      ioparam.size = buf->size;
-+                      ioparam.handle = dma_buf_fd(new_dmabuf,
-+                                                  O_CLOEXEC);
-+                      ioparam.vc_handle = buf->vc_handle;
-+                      ioparam.dma_addr = buf->dma_addr;
-+
-+                      if (ioparam.handle < 0 ||
-+                          (copy_to_user((void *)arg, &ioparam,
-+                                        sizeof(ioparam)) != 0)) {
-+                              dma_buf_put(new_dmabuf);
-+                              /* FIXME: Release allocation */
-+                              ret = -EFAULT;
-+                      }
-+              }
-+              break;
-+      }
-+
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+/* Device operations that we managed in this driver. */
-+static const struct file_operations vc_sm_ops = {
-+      .owner = THIS_MODULE,
-+      .unlocked_ioctl = vc_sm_cma_ioctl,
-+      .open = vc_sm_cma_open,
-+      .release = vc_sm_cma_release,
-+};
-+
-+/* Driver load/unload functions */
- /* Videocore connected.  */
- static void vc_sm_connected_init(void)
- {
-@@ -1075,12 +1384,11 @@ static void vc_sm_connected_init(void)
-       pr_info("[%s]: start\n", __func__);
--      if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
--          !sm_state->cma_heap) {
--              pr_err("[%s]: failed to initialise CMA heaps\n",
-+      vc_sm_cma_add_heaps(&sm_state->cma_heap);
-+      if (!sm_state->cma_heap) {
-+              pr_err("[%s]: failed to initialise CMA heap\n",
-                      __func__);
--              ret = -EIO;
--              goto err_free_mem;
-+              return;
-       }
-       /*
-@@ -1092,8 +1400,7 @@ static void vc_sm_connected_init(void)
-               pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
-                      __func__, ret);
--              ret = -EIO;
--              goto err_failed;
-+              return;
-       }
-       ret = vchi_connect(NULL, 0, vchi_instance);
-@@ -1101,8 +1408,7 @@ static void vc_sm_connected_init(void)
-               pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
-                      __func__, ret);
--              ret = -EIO;
--              goto err_failed;
-+              return;
-       }
-       /* Initialize an instance of the shared memory service. */
-@@ -1112,8 +1418,7 @@ static void vc_sm_connected_init(void)
-               pr_err("[%s]: failed to initialize shared memory service\n",
-                      __func__);
--              ret = -EPERM;
--              goto err_failed;
-+              return;
-       }
-       /* Create a debug fs directory entry (root). */
-@@ -1127,11 +1432,22 @@ static void vc_sm_connected_init(void)
-       INIT_LIST_HEAD(&sm_state->buffer_list);
-+      /* Create a shared memory device. */
-+      sm_state->misc_dev.minor = MISC_DYNAMIC_MINOR;
-+      sm_state->misc_dev.name = DEVICE_NAME;
-+      sm_state->misc_dev.fops = &vc_sm_ops;
-+      sm_state->misc_dev.parent = NULL;
-+      ret = misc_register(&sm_state->misc_dev);
-+      if (ret) {
-+              pr_err("vcsm-cma: failed to register misc device.\n");
-+              goto err_remove_debugfs;
-+      }
-+
-       sm_state->data_knl = vc_sm_cma_create_priv_data(0);
-       if (!sm_state->data_knl) {
-               pr_err("[%s]: failed to create kernel private data tracker\n",
-                      __func__);
--              goto err_remove_shared_memory;
-+              goto err_remove_misc_dev;
-       }
-       version.version = 2;
-@@ -1148,11 +1464,13 @@ static void vc_sm_connected_init(void)
-       pr_info("[%s]: installed successfully\n", __func__);
-       return;
--err_remove_shared_memory:
-+err_remove_misc_dev:
-+      misc_deregister(&sm_state->misc_dev);
-+err_remove_debugfs:
-       debugfs_remove_recursive(sm_state->dir_root);
-       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
--err_failed:
--      pr_info("[%s]: failed, ret %d\n", __func__, ret);
-+
-+      return;
- }
- /* Driver loading. */
-@@ -1184,6 +1502,8 @@ static int bcm2835_vc_sm_cma_remove(stru
- {
-       pr_debug("[%s]: start\n", __func__);
-       if (sm_inited) {
-+              misc_deregister(&sm_state->misc_dev);
-+
-               /* Remove all proc entries. */
-               debugfs_remove_recursive(sm_state->dir_root);
-@@ -1202,6 +1522,7 @@ static int bcm2835_vc_sm_cma_remove(stru
-       return 0;
- }
-+/* Kernel API calls */
- /* Get an internal resource handle mapped from the external one. */
- int vc_sm_cma_int_handle(void *handle)
- {
-@@ -1252,7 +1573,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
-       }
-       ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
--                                             &new_dma_buf);
-+                                             -1, &new_dma_buf);
-       if (!ret) {
-               pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-@@ -92,8 +92,7 @@ int __vc_sm_cma_add_heaps(struct cma *cm
-       return 0;
- }
--int vc_sm_cma_add_heaps(struct cma **cma_heap)
-+void vc_sm_cma_add_heaps(struct cma **cma_heap)
- {
-       cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
--      return 0;
- }
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-@@ -34,6 +34,6 @@ int vc_sm_cma_buffer_allocate(struct cma
-                             unsigned long len);
- void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
--int vc_sm_cma_add_heaps(struct cma **cma_heap);
-+void vc_sm_cma_add_heaps(struct cma **cma_heap);
- #endif
---- /dev/null
-+++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
-@@ -0,0 +1,87 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * Copyright 2019 Raspberry Pi (Trading) Ltd.  All rights reserved.
-+ *
-+ * Based on vmcs_sm_ioctl.h Copyright Broadcom Corporation.
-+ */
-+
-+#ifndef __VC_SM_CMA_IOCTL_H
-+#define __VC_SM_CMA_IOCTL_H
-+
-+/* ---- Include Files ---------------------------------------------------- */
-+
-+#if defined(__KERNEL__)
-+#include <linux/types.h>      /* Needed for standard types */
-+#else
-+#include <stdint.h>
-+#endif
-+
-+#include <linux/ioctl.h>
-+
-+/* ---- Constants and Types ---------------------------------------------- */
-+
-+#define VC_SM_CMA_RESOURCE_NAME               32
-+#define VC_SM_CMA_RESOURCE_NAME_DEFAULT       "sm-host-resource"
-+
-+/* Type define used to create unique IOCTL number */
-+#define VC_SM_CMA_MAGIC_TYPE                  'J'
-+
-+/* IOCTL commands on /dev/vc-sm-cma */
-+enum vc_sm_cma_cmd_e {
-+      VC_SM_CMA_CMD_ALLOC = 0x5A,     /* Start at 0x5A arbitrarily */
-+
-+      VC_SM_CMA_CMD_IMPORT_DMABUF,
-+
-+      VC_SM_CMA_CMD_LAST      /* Do not delete */
-+};
-+
-+/* Cache type supported, conveniently matches the user space definition in
-+ * user-vcsm.h.
-+ */
-+enum vc_sm_cma_cache_e {
-+      VC_SM_CMA_CACHE_NONE,
-+      VC_SM_CMA_CACHE_HOST,
-+      VC_SM_CMA_CACHE_VC,
-+      VC_SM_CMA_CACHE_BOTH,
-+};
-+
-+/* IOCTL Data structures */
-+struct vc_sm_cma_ioctl_alloc {
-+      /* user -> kernel */
-+      __u32 size;
-+      __u32 num;
-+      __u32 cached;           /* enum vc_sm_cma_cache_e */
-+      __u32 pad;
-+      __u8 name[VC_SM_CMA_RESOURCE_NAME];
-+
-+      /* kernel -> user */
-+      __s32 handle;
-+      __u32 vc_handle;
-+      __u64 dma_addr;
-+};
-+
-+struct vc_sm_cma_ioctl_import_dmabuf {
-+      /* user -> kernel */
-+      __s32 dmabuf_fd;
-+      __u32 cached;           /* enum vc_sm_cma_cache_e */
-+      __u8 name[VC_SM_CMA_RESOURCE_NAME];
-+
-+      /* kernel -> user */
-+      __s32 handle;
-+      __u32 vc_handle;
-+      __u32 size;
-+      __u32 pad;
-+      __u64 dma_addr;
-+};
-+
-+/* IOCTL numbers */
-+#define VC_SM_CMA_IOCTL_MEM_ALLOC\
-+      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
-+       struct vc_sm_cma_ioctl_alloc)
-+
-+#define VC_SM_CMA_IOCTL_MEM_IMPORT_DMABUF\
-+      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
-+       struct vc_sm_cma_ioctl_import_dmabuf)
-+
-+#endif /* __VC_SM_CMA_IOCTL_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0552-staging-vcsm-cma-Alter-dev-node-permissions-to-0666.patch b/target/linux/brcm2708/patches-4.19/950-0552-staging-vcsm-cma-Alter-dev-node-permissions-to-0666.patch
new file mode 100644 (file)
index 0000000..ee3d1de
--- /dev/null
@@ -0,0 +1,24 @@
+From 4b78daea312bd39e892eb94f8c7905e2d5b682b4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 13 May 2019 16:47:54 +0100
+Subject: [PATCH] staging: vcsm-cma: Alter dev node permissions to 0666
+
+Until the udev rules are updated, open up access to this node by
+default.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1572,6 +1572,8 @@ static void vc_sm_connected_init(void)
+       sm_state->misc_dev.name = DEVICE_NAME;
+       sm_state->misc_dev.fops = &vc_sm_ops;
+       sm_state->misc_dev.parent = NULL;
++      /* Temporarily set as 666 until udev rules have been sorted */
++      sm_state->misc_dev.mode = 0666;
+       ret = misc_register(&sm_state->misc_dev);
+       if (ret) {
+               pr_err("vcsm-cma: failed to register misc device.\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0553-staging-vcsm-cma-Add-cache-control-ioctls.patch b/target/linux/brcm2708/patches-4.19/950-0553-staging-vcsm-cma-Add-cache-control-ioctls.patch
deleted file mode 100644 (file)
index 500ec5f..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-From b17f6dc1d79ae057294ac2d8d824aa2258ab09a8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 20 Mar 2019 10:40:00 +0000
-Subject: [PATCH] staging: vcsm-cma: Add cache control ioctls
-
-The old driver allowed for direct cache manipulation and that
-was used by various clients. Replicate here.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 141 +++++++++++++++++-
- include/linux/broadcom/vc_sm_cma_ioctl.h      |  27 ++++
- 2 files changed, 165 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -46,6 +46,7 @@
- #include <linux/seq_file.h>
- #include <linux/syscalls.h>
- #include <linux/types.h>
-+#include <asm/cacheflush.h>
- #include "vchiq_connected.h"
- #include "vc_sm_cma_vchi.h"
-@@ -1258,6 +1259,99 @@ error:
-       return ret;
- }
-+/* Converts VCSM_CACHE_OP_* to an operating function. */
-+static void (*cache_op_to_func(const unsigned int cache_op))
-+                                              (const void*, const void*)
-+{
-+      switch (cache_op) {
-+      case VC_SM_CACHE_OP_NOP:
-+              return NULL;
-+
-+      case VC_SM_CACHE_OP_INV:
-+              return dmac_inv_range;
-+
-+      case VC_SM_CACHE_OP_CLEAN:
-+              return dmac_clean_range;
-+
-+      case VC_SM_CACHE_OP_FLUSH:
-+              return dmac_flush_range;
-+
-+      default:
-+              pr_err("[%s]: Invalid cache_op: 0x%08x\n", __func__, cache_op);
-+              return NULL;
-+      }
-+}
-+
-+/*
-+ * Clean/invalid/flush cache of which buffer is already pinned (i.e. accessed).
-+ */
-+static int clean_invalid_contig_2d(const void __user *addr,
-+                                 const size_t block_count,
-+                                 const size_t block_size,
-+                                 const size_t stride,
-+                                 const unsigned int cache_op)
-+{
-+      size_t i;
-+      void (*op_fn)(const void *start, const void *end);
-+
-+      if (!block_size) {
-+              pr_err("[%s]: size cannot be 0\n", __func__);
-+              return -EINVAL;
-+      }
-+
-+      op_fn = cache_op_to_func(cache_op);
-+      if (!op_fn)
-+              return -EINVAL;
-+
-+      for (i = 0; i < block_count; i ++, addr += stride)
-+              op_fn(addr, addr + block_size);
-+
-+      return 0;
-+}
-+
-+static int vc_sm_cma_clean_invalid2(unsigned int cmdnr, unsigned long arg)
-+{
-+      struct vc_sm_cma_ioctl_clean_invalid2 ioparam;
-+      struct vc_sm_cma_ioctl_clean_invalid_block *block = NULL;
-+      int i, ret = 0;
-+
-+      /* Get parameter data. */
-+      if (copy_from_user(&ioparam, (void *)arg, sizeof(ioparam))) {
-+              pr_err("[%s]: failed to copy-from-user header for cmd %x\n",
-+                     __func__, cmdnr);
-+              return -EFAULT;
-+      }
-+      block = kmalloc(ioparam.op_count * sizeof(*block), GFP_KERNEL);
-+      if (!block)
-+              return -EFAULT;
-+
-+      if (copy_from_user(block, (void *)(arg + sizeof(ioparam)),
-+                         ioparam.op_count * sizeof(*block)) != 0) {
-+              pr_err("[%s]: failed to copy-from-user payload for cmd %x\n",
-+                     __func__, cmdnr);
-+              ret = -EFAULT;
-+              goto out;
-+      }
-+
-+      for (i = 0; i < ioparam.op_count; i++) {
-+              const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
-+
-+              if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
-+                      continue;
-+
-+              ret = clean_invalid_contig_2d((void __user *)op->start_address,
-+                                            op->block_count, op->block_size,
-+                                            op->inter_block_stride,
-+                                            op->invalidate_mode);
-+              if (ret)
-+                      break;
-+      }
-+out:
-+      kfree(block);
-+
-+      return ret;
-+}
-+
- static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
-                           unsigned long arg)
- {
-@@ -1272,9 +1366,6 @@ static long vc_sm_cma_ioctl(struct file
-               return -EPERM;
-       }
--      pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
--               current->tgid, file_data->pid);
--
-       /* Action is a re-post of a previously interrupted action? */
-       if (file_data->restart_sys == -EINTR) {
-               struct vc_sm_action_clean_t action_clean;
-@@ -1357,7 +1448,18 @@ static long vc_sm_cma_ioctl(struct file
-               break;
-       }
-+      /*
-+       * Flush/Invalidate the cache for a given mapping.
-+       * Blocks must be pinned (i.e. accessed) before this call.
-+       */
-+      case VC_SM_CMA_CMD_CLEAN_INVALID2:
-+              ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
-+              break;
-+
-       default:
-+              pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
-+                       current->tgid, file_data->pid);
-+
-               ret = -EINVAL;
-               break;
-       }
-@@ -1365,10 +1467,43 @@ static long vc_sm_cma_ioctl(struct file
-       return ret;
- }
-+#ifdef CONFIG_COMPAT
-+struct vc_sm_cma_ioctl_clean_invalid2_32 {
-+      u32 op_count;
-+      struct vc_sm_cma_ioctl_clean_invalid_block {
-+              u16 invalidate_mode;
-+              u16 block_count;
-+              compat_uptr_t start_address;
-+              u32 block_size;
-+              u32 inter_block_stride;
-+      } s[0];
-+};
-+
-+#define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
-+      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
-+       struct vc_sm_cma_ioctl_clean_invalid2)
-+
-+static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
-+                                 unsigned long arg)
-+{
-+      switch (cmd) {
-+      case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
-+              /* FIXME */
-+              break;
-+
-+      default:
-+              return vc_sm_cma_compat_ioctl(file, cmd, arg);
-+      }
-+}
-+#endif
-+
- /* Device operations that we managed in this driver. */
- static const struct file_operations vc_sm_ops = {
-       .owner = THIS_MODULE,
-       .unlocked_ioctl = vc_sm_cma_ioctl,
-+#ifdef CONFIG_COMPAT
-+      .compat_ioctl = vc_sm_cma_compat_ioctl,
-+#endif
-       .open = vc_sm_cma_open,
-       .release = vc_sm_cma_release,
- };
---- a/include/linux/broadcom/vc_sm_cma_ioctl.h
-+++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
-@@ -33,6 +33,8 @@ enum vc_sm_cma_cmd_e {
-       VC_SM_CMA_CMD_IMPORT_DMABUF,
-+      VC_SM_CMA_CMD_CLEAN_INVALID2,
-+
-       VC_SM_CMA_CMD_LAST      /* Do not delete */
- };
-@@ -75,6 +77,27 @@ struct vc_sm_cma_ioctl_import_dmabuf {
-       __u64 dma_addr;
- };
-+/*
-+ * Cache functions to be set to struct vc_sm_cma_ioctl_clean_invalid2
-+ * invalidate_mode.
-+ */
-+#define VC_SM_CACHE_OP_NOP       0x00
-+#define VC_SM_CACHE_OP_INV       0x01
-+#define VC_SM_CACHE_OP_CLEAN     0x02
-+#define VC_SM_CACHE_OP_FLUSH     0x03
-+
-+struct vc_sm_cma_ioctl_clean_invalid2 {
-+      __u32 op_count;
-+      __u32 pad;
-+      struct vc_sm_cma_ioctl_clean_invalid_block {
-+              __u32 invalidate_mode;
-+              __u32 block_count;
-+              void *  __user start_address;
-+              __u32 block_size;
-+              __u32 inter_block_stride;
-+      } s[0];
-+};
-+
- /* IOCTL numbers */
- #define VC_SM_CMA_IOCTL_MEM_ALLOC\
-       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
-@@ -84,4 +107,8 @@ struct vc_sm_cma_ioctl_import_dmabuf {
-       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
-        struct vc_sm_cma_ioctl_import_dmabuf)
-+#define VC_SM_CMA_IOCTL_MEM_CLEAN_INVALID2\
-+      _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
-+       struct vc_sm_cma_ioctl_clean_invalid2)
-+
- #endif /* __VC_SM_CMA_IOCTL_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0553-staging-vcsm-cma-Drop-logging-level-on-messages-in-v.patch b/target/linux/brcm2708/patches-4.19/950-0553-staging-vcsm-cma-Drop-logging-level-on-messages-in-v.patch
new file mode 100644 (file)
index 0000000..320552e
--- /dev/null
@@ -0,0 +1,33 @@
+From c38256621d4dffbbc0c19737d724724f04b0df9a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 16 May 2019 15:17:19 +0100
+Subject: [PATCH] staging: vcsm-cma: Drop logging level on messages in
+ vc_sm_release_resource
+
+They weren't errors but were logged as such.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -301,14 +301,13 @@ static void vc_sm_release_resource(struc
+       if (buffer->vc_handle) {
+               /* We've sent the unmap request but not had the response. */
+-              pr_err("[%s]: Waiting for VPU unmap response on %p\n",
+-                     __func__, buffer);
++              pr_debug("[%s]: Waiting for VPU unmap response on %p\n",
++                       __func__, buffer);
+               goto defer;
+       }
+       if (buffer->in_use) {
+               /* dmabuf still in use - we await the release */
+-              pr_err("[%s]: buffer %p is still in use\n",
+-                     __func__, buffer);
++              pr_debug("[%s]: buffer %p is still in use\n", __func__, buffer);
+               goto defer;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0554-staging-vcsm-cma-Alter-dev-node-permissions-to-0666.patch b/target/linux/brcm2708/patches-4.19/950-0554-staging-vcsm-cma-Alter-dev-node-permissions-to-0666.patch
deleted file mode 100644 (file)
index ee3d1de..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 4b78daea312bd39e892eb94f8c7905e2d5b682b4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 13 May 2019 16:47:54 +0100
-Subject: [PATCH] staging: vcsm-cma: Alter dev node permissions to 0666
-
-Until the udev rules are updated, open up access to this node by
-default.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -1572,6 +1572,8 @@ static void vc_sm_connected_init(void)
-       sm_state->misc_dev.name = DEVICE_NAME;
-       sm_state->misc_dev.fops = &vc_sm_ops;
-       sm_state->misc_dev.parent = NULL;
-+      /* Temporarily set as 666 until udev rules have been sorted */
-+      sm_state->misc_dev.mode = 0666;
-       ret = misc_register(&sm_state->misc_dev);
-       if (ret) {
-               pr_err("vcsm-cma: failed to register misc device.\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0554-staging-vcsm-cma-Fixup-the-alloc-code-handling-of-ke.patch b/target/linux/brcm2708/patches-4.19/950-0554-staging-vcsm-cma-Fixup-the-alloc-code-handling-of-ke.patch
new file mode 100644 (file)
index 0000000..5e5c6bc
--- /dev/null
@@ -0,0 +1,35 @@
+From 52f881e3afa89bb1ca9e8b037f7600bcc97626e8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 22 May 2019 15:40:37 +0100
+Subject: [PATCH] staging: vcsm-cma: Fixup the alloc code handling of
+ kernel_id
+
+The allocation code had been copied in from an old branch prior
+to having added the IDR for 64bit support. It was therefore pushing
+a pointer into the kernel_id field instead of an IDR handle, the
+lookup therefore failed, and we never released the buffer.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1206,7 +1206,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
+       import.size = aligned_size;
+-      import.kernel_id = (uint32_t)buffer;
++      import.kernel_id = get_kernel_id(buffer);
+       /* Wrap it into a videocore buffer. */
+       status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
+@@ -1231,6 +1231,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       buffer->size = import.size;
+       buffer->dma_addr = import.addr;
+       buffer->vpu_state = VPU_MAPPED;
++      buffer->kernel_id = import.kernel_id;
+       //buffer->res_cached = ioparam->cached;
+       fd = dma_buf_fd(dmabuf, O_CLOEXEC);
diff --git a/target/linux/brcm2708/patches-4.19/950-0555-Pulled-in-the-multi-frame-buffer-support-from-the-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0555-Pulled-in-the-multi-frame-buffer-support-from-the-Pi.patch
new file mode 100644 (file)
index 0000000..883d947
--- /dev/null
@@ -0,0 +1,925 @@
+From 3e33fb46eb8791ba39fe4781f278487bcc2c3356 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Thu, 14 Mar 2019 13:27:54 +0000
+Subject: [PATCH] Pulled in the multi frame buffer support from the Pi3
+ repo
+
+---
+ drivers/video/fbdev/bcm2708_fb.c           | 580 +++++++++++++++------
+ include/soc/bcm2835/raspberrypi-firmware.h |   4 +
+ 2 files changed, 432 insertions(+), 152 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -2,6 +2,7 @@
+  *  linux/drivers/video/bcm2708_fb.c
+  *
+  * Copyright (C) 2010 Broadcom
++ * Copyright (C) 2018 Raspberry Pi (Trading) Ltd
+  *
+  * This file is subject to the terms and conditions of the GNU General Public
+  * License.  See the file COPYING in the main directory of this archive
+@@ -13,6 +14,7 @@
+  * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
+  *
+  */
++
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -36,6 +38,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/cred.h>
+ #include <soc/bcm2835/raspberrypi-firmware.h>
++#include <linux/mutex.h>
+ //#define BCM2708_FB_DEBUG
+ #define MODULE_NAME "bcm2708_fb"
+@@ -82,62 +85,139 @@ struct bcm2708_fb_stats {
+       u32 dma_irqs;
+ };
++struct vc4_display_settings_t {
++      u32 display_num;
++      u32 width;
++      u32 height;
++      u32 pitch;
++      u32 depth;
++      u32 virtual_width;
++      u32 virtual_height;
++      u32 virtual_width_offset;
++      u32 virtual_height_offset;
++      unsigned long fb_bus_address;
++};
++
++struct bcm2708_fb_dev;
++
+ struct bcm2708_fb {
+       struct fb_info fb;
+       struct platform_device *dev;
+-      struct rpi_firmware *fw;
+       u32 cmap[16];
+       u32 gpu_cmap[256];
++      struct dentry *debugfs_dir;
++      struct dentry *debugfs_subdir;
++      unsigned long fb_bus_address;
++      struct { u32 base, length; } gpu;
++      struct vc4_display_settings_t display_settings;
++      struct debugfs_regset32 screeninfo_regset;
++      struct bcm2708_fb_dev *fbdev;
++      unsigned int image_size;
++      dma_addr_t dma_addr;
++      void *cpuaddr;
++};
++
++#define MAX_FRAMEBUFFERS 3
++
++struct bcm2708_fb_dev {
++      int firmware_supports_multifb;
++      /* Protects the DMA system from multiple FB access */
++      struct mutex dma_mutex;
+       int dma_chan;
+       int dma_irq;
+       void __iomem *dma_chan_base;
+-      void *cb_base;          /* DMA control blocks */
+-      dma_addr_t cb_handle;
+-      struct dentry *debugfs_dir;
+       wait_queue_head_t dma_waitq;
+-      struct bcm2708_fb_stats stats;
+-      unsigned long fb_bus_address;
+-      struct { u32 base, length; } gpu;
++      bool disable_arm_alloc;
++      struct bcm2708_fb_stats dma_stats;
++      void *cb_base;  /* DMA control blocks */
++      dma_addr_t cb_handle;
++      int instance_count;
++      int num_displays;
++      struct rpi_firmware *fw;
++      struct bcm2708_fb displays[MAX_FRAMEBUFFERS];
+ };
+ #define to_bcm2708(info)      container_of(info, struct bcm2708_fb, fb)
+ static void bcm2708_fb_debugfs_deinit(struct bcm2708_fb *fb)
+ {
+-      debugfs_remove_recursive(fb->debugfs_dir);
+-      fb->debugfs_dir = NULL;
++      debugfs_remove_recursive(fb->debugfs_subdir);
++      fb->debugfs_subdir = NULL;
++
++      fb->fbdev->instance_count--;
++
++      if (!fb->fbdev->instance_count) {
++              debugfs_remove_recursive(fb->debugfs_dir);
++              fb->debugfs_dir = NULL;
++      }
+ }
+ static int bcm2708_fb_debugfs_init(struct bcm2708_fb *fb)
+ {
++      char buf[3];
++      struct bcm2708_fb_dev *fbdev = fb->fbdev;
++
+       static struct debugfs_reg32 stats_registers[] = {
+-              {
+-                      "dma_copies",
+-                      offsetof(struct bcm2708_fb_stats, dma_copies)
+-              },
+-              {
+-                      "dma_irqs",
+-                      offsetof(struct bcm2708_fb_stats, dma_irqs)
+-              },
++      {"dma_copies", offsetof(struct bcm2708_fb_stats, dma_copies)},
++      {"dma_irqs",   offsetof(struct bcm2708_fb_stats, dma_irqs)},
+       };
+-      fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
++      static struct debugfs_reg32 screeninfo[] = {
++      {"width",        offsetof(struct fb_var_screeninfo, xres)},
++      {"height",       offsetof(struct fb_var_screeninfo, yres)},
++      {"bpp",          offsetof(struct fb_var_screeninfo, bits_per_pixel)},
++      {"xres_virtual", offsetof(struct fb_var_screeninfo, xres_virtual)},
++      {"yres_virtual", offsetof(struct fb_var_screeninfo, yres_virtual)},
++      {"xoffset",      offsetof(struct fb_var_screeninfo, xoffset)},
++      {"yoffset",      offsetof(struct fb_var_screeninfo, yoffset)},
++      };
++
++      fb->debugfs_dir = debugfs_lookup(DRIVER_NAME, NULL);
++
++      if (!fb->debugfs_dir)
++              fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
++
+       if (!fb->debugfs_dir) {
+-              pr_warn("%s: could not create debugfs entry\n",
+-                      __func__);
++              dev_warn(fb->fb.dev, "%s: could not create debugfs folder\n",
++                       __func__);
++              return -EFAULT;
++      }
++
++      snprintf(buf, sizeof(buf), "%u", fb->display_settings.display_num);
++
++      fb->debugfs_subdir = debugfs_create_dir(buf, fb->debugfs_dir);
++
++      if (!fb->debugfs_subdir) {
++              dev_warn(fb->fb.dev, "%s: could not create debugfs entry %u\n",
++                       __func__, fb->display_settings.display_num);
+               return -EFAULT;
+       }
+-      fb->stats.regset.regs = stats_registers;
+-      fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
+-      fb->stats.regset.base = &fb->stats;
+-
+-      if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
+-                                   &fb->stats.regset)) {
+-              pr_warn("%s: could not create statistics registers\n",
+-                      __func__);
++      fbdev->dma_stats.regset.regs = stats_registers;
++      fbdev->dma_stats.regset.nregs = ARRAY_SIZE(stats_registers);
++      fbdev->dma_stats.regset.base = &fbdev->dma_stats;
++
++      if (!debugfs_create_regset32("dma_stats", 0444, fb->debugfs_subdir,
++                                   &fbdev->dma_stats.regset)) {
++              dev_warn(fb->fb.dev, "%s: could not create statistics registers\n",
++                       __func__);
++              goto fail;
++      }
++
++      fb->screeninfo_regset.regs = screeninfo;
++      fb->screeninfo_regset.nregs = ARRAY_SIZE(screeninfo);
++      fb->screeninfo_regset.base = &fb->fb.var;
++
++      if (!debugfs_create_regset32("screeninfo", 0444, fb->debugfs_subdir,
++                                   &fb->screeninfo_regset)) {
++              dev_warn(fb->fb.dev,
++                       "%s: could not create dimensions registers\n",
++                       __func__);
+               goto fail;
+       }
++
++      fbdev->instance_count++;
++
+       return 0;
+ fail:
+@@ -145,6 +225,20 @@ fail:
+       return -EFAULT;
+ }
++static void set_display_num(struct bcm2708_fb *fb)
++{
++      if (fb && fb->fbdev && fb->fbdev->firmware_supports_multifb) {
++              u32 tmp = fb->display_settings.display_num;
++
++              if (rpi_firmware_property(fb->fbdev->fw,
++                                        RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM,
++                                        &tmp,
++                                        sizeof(tmp)))
++                      dev_warn_once(fb->fb.dev,
++                                    "Set display number call failed. Old GPU firmware?");
++      }
++}
++
+ static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var)
+ {
+       int ret = 0;
+@@ -222,11 +316,11 @@ static int bcm2708_fb_check_var(struct f
+                               struct fb_info *info)
+ {
+       /* info input, var output */
+-      print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
++      print_debug("%s(%p) %ux%u (%ux%u), %ul, %u\n",
+                   __func__, info, info->var.xres, info->var.yres,
+                   info->var.xres_virtual, info->var.yres_virtual,
+-                  (int)info->screen_size, info->var.bits_per_pixel);
+-      print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
++                  info->screen_size, info->var.bits_per_pixel);
++      print_debug("%s(%p) %ux%u (%ux%u), %u\n", __func__, var, var->xres,
+                   var->yres, var->xres_virtual, var->yres_virtual,
+                   var->bits_per_pixel);
+@@ -283,23 +377,96 @@ static int bcm2708_fb_set_par(struct fb_
+                       .xoffset = info->var.xoffset,
+                       .yoffset = info->var.yoffset,
+               .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+-                      .base = 0,
+-                      .screen_size = 0,
+-              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
+-                      .pitch = 0,
++                      /* base and screen_size will be initialised later */
++              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
++                      /* pitch will be initialised later */
+       };
+-      int ret;
++      int ret, image_size;
++
+-      print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
++      print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
++                  info,
+                   info->var.xres, info->var.yres, info->var.xres_virtual,
+                   info->var.yres_virtual, (int)info->screen_size,
+-                  info->var.bits_per_pixel);
++                  info->var.bits_per_pixel, value);
++
++      /* Need to set the display number to act on first
++       * Cannot do it in the tag list because on older firmware the call
++       * will fail and stop the rest of the list being executed.
++       * We can ignore this call failing as the default at other end is 0
++       */
++      set_display_num(fb);
++
++      /* Try allocating our own buffer. We can specify all the parameters */
++      image_size = ((info->var.xres * info->var.yres) *
++                    info->var.bits_per_pixel) >> 3;
++
++      if (!fb->fbdev->disable_arm_alloc &&
++          (image_size != fb->image_size || !fb->dma_addr)) {
++              if (fb->dma_addr) {
++                      dma_free_coherent(info->device, fb->image_size,
++                                        fb->cpuaddr, fb->dma_addr);
++                      fb->image_size = 0;
++                      fb->cpuaddr = NULL;
++                      fb->dma_addr = 0;
++              }
++
++              fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
++                                               &fb->dma_addr, GFP_KERNEL);
++
++              if (!fb->cpuaddr) {
++                      fb->dma_addr = 0;
++                      fb->fbdev->disable_arm_alloc = true;
++              } else {
++                      fb->image_size = image_size;
++              }
++      }
++
++      if (fb->cpuaddr) {
++              fbinfo.base = fb->dma_addr;
++              fbinfo.screen_size = image_size;
++              fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
++
++              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
++                                               sizeof(fbinfo));
++              if (ret || fbinfo.base != fb->dma_addr) {
++                      /* Firmware either failed, or assigned a different base
++                       * address (ie it doesn't support being passed an FB
++                       * allocation).
++                       * Destroy the allocation, and don't try again.
++                       */
++                      dma_free_coherent(info->device, fb->image_size,
++                                        fb->cpuaddr, fb->dma_addr);
++                      fb->image_size = 0;
++                      fb->cpuaddr = NULL;
++                      fb->dma_addr = 0;
++                      fb->fbdev->disable_arm_alloc = true;
++              }
++      } else {
++              /* Our allocation failed - drop into the old scheme of
++               * allocation by the VPU.
++               */
++              ret = -ENOMEM;
++      }
+-      ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
+       if (ret) {
+-              dev_err(info->device,
+-                      "Failed to allocate GPU framebuffer (%d)\n", ret);
+-              return ret;
++              /* Old scheme:
++               * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
++               * - GET_PITCH instead of SET_PITCH.
++               */
++              fbinfo.base = 0;
++              fbinfo.screen_size = 0;
++              fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
++              fbinfo.pitch = 0;
++
++              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
++                                               sizeof(fbinfo));
++              if (ret) {
++                      dev_err(info->device,
++                              "Failed to allocate GPU framebuffer (%d)\n",
++                              ret);
++                      return ret;
++              }
+       }
+       if (info->var.bits_per_pixel <= 8)
+@@ -314,9 +481,17 @@ static int bcm2708_fb_set_par(struct fb_
+       fb->fb.fix.smem_start = fbinfo.base;
+       fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
+       fb->fb.screen_size = fbinfo.screen_size;
+-      if (fb->fb.screen_base)
+-              iounmap(fb->fb.screen_base);
+-      fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
++
++      if (!fb->dma_addr) {
++              if (fb->fb.screen_base)
++                      iounmap(fb->fb.screen_base);
++
++              fb->fb.screen_base = ioremap_wc(fbinfo.base,
++                                              fb->fb.screen_size);
++      } else {
++              fb->fb.screen_base = fb->cpuaddr;
++      }
++
+       if (!fb->fb.screen_base) {
+               /* the console may currently be locked */
+               console_trylock();
+@@ -374,7 +549,10 @@ static int bcm2708_fb_setcolreg(unsigned
+                       packet->length = regno + 1;
+                       memcpy(packet->cmap, fb->gpu_cmap,
+                              sizeof(packet->cmap));
+-                      ret = rpi_firmware_property(fb->fw,
++
++                      set_display_num(fb);
++
++                      ret = rpi_firmware_property(fb->fbdev->fw,
+                                                   RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
+                                                   packet,
+                                                   (2 + packet->length) * sizeof(u32));
+@@ -413,8 +591,11 @@ static int bcm2708_fb_blank(int blank_mo
+               return -EINVAL;
+       }
+-      ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
++      set_display_num(fb);
++
++      ret = rpi_firmware_property(fb->fbdev->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+                                   &value, sizeof(value));
++
+       if (ret)
+               dev_err(info->device, "%s(%d) failed: %d\n", __func__,
+                       blank_mode, ret);
+@@ -431,7 +612,7 @@ static int bcm2708_fb_pan_display(struct
+       info->var.yoffset = var->yoffset;
+       result = bcm2708_fb_set_par(info);
+       if (result != 0)
+-              pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
++              pr_err("%s(%u,%u) returns=%d\n", __func__, var->xoffset,
+                      var->yoffset, result);
+       return result;
+ }
+@@ -439,8 +620,9 @@ static int bcm2708_fb_pan_display(struct
+ static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src,
+                      int size)
+ {
+-      int burst_size = (fb->dma_chan == 0) ? 8 : 2;
+-      struct bcm2708_dma_cb *cb = fb->cb_base;
++      struct bcm2708_fb_dev *fbdev = fb->fbdev;
++      struct bcm2708_dma_cb *cb = fbdev->cb_base;
++      int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
+       cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
+                  BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
+@@ -453,21 +635,27 @@ static void dma_memcpy(struct bcm2708_fb
+       cb->pad[1] = 0;
+       cb->next = 0;
++      // Not sure what to do if this gets a signal whilst waiting
++      if (mutex_lock_interruptible(&fbdev->dma_mutex))
++              return;
++
+       if (size < dma_busy_wait_threshold) {
+-              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+-              bcm_dma_wait_idle(fb->dma_chan_base);
++              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++              bcm_dma_wait_idle(fbdev->dma_chan_base);
+       } else {
+-              void __iomem *dma_chan = fb->dma_chan_base;
++              void __iomem *local_dma_chan = fbdev->dma_chan_base;
+               cb->info |= BCM2708_DMA_INT_EN;
+-              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+-              while (bcm_dma_is_busy(dma_chan)) {
+-                      wait_event_interruptible(fb->dma_waitq,
+-                                               !bcm_dma_is_busy(dma_chan));
++              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++              while (bcm_dma_is_busy(local_dma_chan)) {
++                      wait_event_interruptible(fbdev->dma_waitq,
++                                               !bcm_dma_is_busy(local_dma_chan));
+               }
+-              fb->stats.dma_irqs++;
++              fbdev->dma_stats.dma_irqs++;
+       }
+-      fb->stats.dma_copies++;
++      fbdev->dma_stats.dma_copies++;
++
++      mutex_unlock(&fbdev->dma_mutex);
+ }
+ /* address with no aliases */
+@@ -542,10 +730,13 @@ static int bcm2708_ioctl(struct fb_info
+       switch (cmd) {
+       case FBIO_WAITFORVSYNC:
+-              ret = rpi_firmware_property(fb->fw,
++              set_display_num(fb);
++
++              ret = rpi_firmware_property(fb->fbdev->fw,
+                                           RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC,
+                                           &dummy, sizeof(dummy));
+               break;
++
+       case FBIODMACOPY:
+       {
+               struct fb_dmacopy ioparam;
+@@ -615,23 +806,22 @@ static int bcm2708_compat_ioctl(struct f
+ static void bcm2708_fb_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *rect)
+ {
+-      /* (is called) print_debug("bcm2708_fb_fillrect\n"); */
+       cfb_fillrect(info, rect);
+ }
+ /* A helper function for configuring dma control block */
+ static void set_dma_cb(struct bcm2708_dma_cb *cb,
+-                     int        burst_size,
+-                     dma_addr_t dst,
+-                     int        dst_stride,
+-                     dma_addr_t src,
+-                     int        src_stride,
+-                     int        w,
+-                     int        h)
++              int        burst_size,
++              dma_addr_t dst,
++              int        dst_stride,
++              dma_addr_t src,
++              int        src_stride,
++              int        w,
++              int        h)
+ {
+       cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
+-                 BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
+-                 BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
++              BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
++              BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
+       cb->dst = dst;
+       cb->src = src;
+       /*
+@@ -649,15 +839,19 @@ static void bcm2708_fb_copyarea(struct f
+                               const struct fb_copyarea *region)
+ {
+       struct bcm2708_fb *fb = to_bcm2708(info);
+-      struct bcm2708_dma_cb *cb = fb->cb_base;
++      struct bcm2708_fb_dev *fbdev = fb->fbdev;
++      struct bcm2708_dma_cb *cb = fbdev->cb_base;
+       int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
+       /* Channel 0 supports larger bursts and is a bit faster */
+-      int burst_size = (fb->dma_chan == 0) ? 8 : 2;
++      int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
+       int pixels = region->width * region->height;
+-      /* Fallback to cfb_copyarea() if we don't like something */
+-      if (bytes_per_pixel > 4 ||
++      /* If DMA is currently in use (ie being used on another FB), then
++       * rather than wait for it to finish, just use the cfb_copyarea
++       */
++      if (!mutex_trylock(&fbdev->dma_mutex) ||
++          bytes_per_pixel > 4 ||
+           info->var.xres * info->var.yres > 1920 * 1200 ||
+           region->width <= 0 || region->width > info->var.xres ||
+           region->height <= 0 || region->height > info->var.yres ||
+@@ -684,8 +878,8 @@ static void bcm2708_fb_copyarea(struct f
+                * 1920x1200 resolution at 32bpp pixel depth.
+                */
+               int y;
+-              dma_addr_t control_block_pa = fb->cb_handle;
+-              dma_addr_t scratchbuf = fb->cb_handle + 16 * 1024;
++              dma_addr_t control_block_pa = fbdev->cb_handle;
++              dma_addr_t scratchbuf = fbdev->cb_handle + 16 * 1024;
+               int scanline_size = bytes_per_pixel * region->width;
+               int scanlines_per_cb = (64 * 1024 - 16 * 1024) / scanline_size;
+@@ -735,10 +929,10 @@ static void bcm2708_fb_copyarea(struct f
+               }
+               set_dma_cb(cb, burst_size,
+                          fb->fb_bus_address + dy * fb->fb.fix.line_length +
+-                                                 bytes_per_pixel * region->dx,
++                         bytes_per_pixel * region->dx,
+                          stride,
+                          fb->fb_bus_address + sy * fb->fb.fix.line_length +
+-                                                 bytes_per_pixel * region->sx,
++                         bytes_per_pixel * region->sx,
+                          stride,
+                          region->width * bytes_per_pixel,
+                          region->height);
+@@ -748,32 +942,33 @@ static void bcm2708_fb_copyarea(struct f
+       cb->next = 0;
+       if (pixels < dma_busy_wait_threshold) {
+-              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+-              bcm_dma_wait_idle(fb->dma_chan_base);
++              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++              bcm_dma_wait_idle(fbdev->dma_chan_base);
+       } else {
+-              void __iomem *dma_chan = fb->dma_chan_base;
++              void __iomem *local_dma_chan = fbdev->dma_chan_base;
+               cb->info |= BCM2708_DMA_INT_EN;
+-              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+-              while (bcm_dma_is_busy(dma_chan)) {
+-                      wait_event_interruptible(fb->dma_waitq,
+-                                               !bcm_dma_is_busy(dma_chan));
++              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++              while (bcm_dma_is_busy(local_dma_chan)) {
++                      wait_event_interruptible(fbdev->dma_waitq,
++                                               !bcm_dma_is_busy(local_dma_chan));
+               }
+-              fb->stats.dma_irqs++;
++              fbdev->dma_stats.dma_irqs++;
+       }
+-      fb->stats.dma_copies++;
++      fbdev->dma_stats.dma_copies++;
++
++      mutex_unlock(&fbdev->dma_mutex);
+ }
+ static void bcm2708_fb_imageblit(struct fb_info *info,
+                                const struct fb_image *image)
+ {
+-      /* (is called) print_debug("bcm2708_fb_imageblit\n"); */
+       cfb_imageblit(info, image);
+ }
+ static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt)
+ {
+-      struct bcm2708_fb *fb = cxt;
++      struct bcm2708_fb_dev *fbdev = cxt;
+       /* FIXME: should read status register to check if this is
+        * actually interrupting us or not, in case this interrupt
+@@ -783,9 +978,9 @@ static irqreturn_t bcm2708_fb_dma_irq(in
+        */
+       /* acknowledge the interrupt */
+-      writel(BCM2708_DMA_INT, fb->dma_chan_base + BCM2708_DMA_CS);
++      writel(BCM2708_DMA_INT, fbdev->dma_chan_base + BCM2708_DMA_CS);
+-      wake_up(&fb->dma_waitq);
++      wake_up(&fbdev->dma_waitq);
+       return IRQ_HANDLED;
+ }
+@@ -821,11 +1016,23 @@ static int bcm2708_fb_register(struct bc
+       fb->fb.fix.ywrapstep = 0;
+       fb->fb.fix.accel = FB_ACCEL_NONE;
+-      fb->fb.var.xres = fbwidth;
+-      fb->fb.var.yres = fbheight;
+-      fb->fb.var.xres_virtual = fbwidth;
+-      fb->fb.var.yres_virtual = fbheight;
+-      fb->fb.var.bits_per_pixel = fbdepth;
++      /* If we have data from the VC4 on FB's, use that, otherwise use the
++       * module parameters
++       */
++      if (fb->display_settings.width) {
++              fb->fb.var.xres = fb->display_settings.width;
++              fb->fb.var.yres = fb->display_settings.height;
++              fb->fb.var.xres_virtual = fb->fb.var.xres;
++              fb->fb.var.yres_virtual = fb->fb.var.yres;
++              fb->fb.var.bits_per_pixel = fb->display_settings.depth;
++      } else {
++              fb->fb.var.xres = fbwidth;
++              fb->fb.var.yres = fbheight;
++              fb->fb.var.xres_virtual = fbwidth;
++              fb->fb.var.yres_virtual = fbheight;
++              fb->fb.var.bits_per_pixel = fbdepth;
++      }
++
+       fb->fb.var.vmode = FB_VMODE_NONINTERLACED;
+       fb->fb.var.activate = FB_ACTIVATE_NOW;
+       fb->fb.var.nonstd = 0;
+@@ -841,26 +1048,23 @@ static int bcm2708_fb_register(struct bc
+       fb->fb.monspecs.dclkmax = 100000000;
+       bcm2708_fb_set_bitfields(&fb->fb.var);
+-      init_waitqueue_head(&fb->dma_waitq);
+       /*
+        * Allocate colourmap.
+        */
+-
+       fb_set_var(&fb->fb, &fb->fb.var);
++
+       ret = bcm2708_fb_set_par(&fb->fb);
++
+       if (ret)
+               return ret;
+-      print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
+-                  fbwidth, fbheight, fbdepth, fbswap);
+-
+       ret = register_framebuffer(&fb->fb);
+-      print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
++
+       if (ret == 0)
+               goto out;
+-      print_debug("BCM2708FB: cannot register framebuffer (%d)\n", ret);
++      dev_warn(fb->fb.dev, "Unable to register framebuffer (%d)\n", ret);
+ out:
+       return ret;
+ }
+@@ -869,10 +1073,18 @@ static int bcm2708_fb_probe(struct platf
+ {
+       struct device_node *fw_np;
+       struct rpi_firmware *fw;
+-      struct bcm2708_fb *fb;
+-      int ret;
++      int ret, i;
++      u32 num_displays;
++      struct bcm2708_fb_dev *fbdev;
++      struct { u32 base, length; } gpu_mem;
++
++      fbdev = devm_kzalloc(&dev->dev, sizeof(*fbdev), GFP_KERNEL);
++
++      if (!fbdev)
++              return -ENOMEM;
+       fw_np = of_parse_phandle(dev->dev.of_node, "firmware", 0);
++
+ /* Remove comment when booting without Device Tree is no longer supported
+  *    if (!fw_np) {
+  *            dev_err(&dev->dev, "Missing firmware node\n");
+@@ -880,90 +1092,154 @@ static int bcm2708_fb_probe(struct platf
+  *    }
+  */
+       fw = rpi_firmware_get(fw_np);
++      fbdev->fw = fw;
++
+       if (!fw)
+               return -EPROBE_DEFER;
+-      fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+-      if (!fb) {
+-              ret = -ENOMEM;
+-              goto free_region;
++      ret = rpi_firmware_property(fw,
++                                  RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
++                                  &num_displays, sizeof(u32));
++
++      /* If we fail to get the number of displays, or it returns 0, then
++       * assume old firmware that doesn't have the mailbox call, so just
++       * set one display
++       */
++      if (ret || num_displays == 0) {
++              num_displays = 1;
++              dev_err(&dev->dev,
++                      "Unable to determine number of FB's. Assuming 1\n");
++              ret = 0;
++      } else {
++              fbdev->firmware_supports_multifb = 1;
+       }
+-      fb->fw = fw;
+-      bcm2708_fb_debugfs_init(fb);
++      if (num_displays > MAX_FRAMEBUFFERS) {
++              dev_warn(&dev->dev,
++                       "More displays reported from firmware than supported in driver (%u vs %u)",
++                       num_displays, MAX_FRAMEBUFFERS);
++              num_displays = MAX_FRAMEBUFFERS;
++      }
+-      fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
+-                                           &fb->cb_handle, GFP_KERNEL);
+-      if (!fb->cb_base) {
++      dev_info(&dev->dev, "FB found %d display(s)\n", num_displays);
++
++      /* Set up the DMA information. Note we have just one set of DMA
++       * parameters to work with all the FB's so requires synchronising when
++       * being used
++       */
++
++      mutex_init(&fbdev->dma_mutex);
++
++      fbdev->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
++                                              &fbdev->cb_handle,
++                                              GFP_KERNEL);
++      if (!fbdev->cb_base) {
+               dev_err(&dev->dev, "cannot allocate DMA CBs\n");
+               ret = -ENOMEM;
+               goto free_fb;
+       }
+-      pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
+-
+       ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
+-                               &fb->dma_chan_base, &fb->dma_irq);
++                               &fbdev->dma_chan_base,
++                               &fbdev->dma_irq);
+       if (ret < 0) {
+-              dev_err(&dev->dev, "couldn't allocate a DMA channel\n");
++              dev_err(&dev->dev, "Couldn't allocate a DMA channel\n");
+               goto free_cb;
+       }
+-      fb->dma_chan = ret;
++      fbdev->dma_chan = ret;
+-      ret = request_irq(fb->dma_irq, bcm2708_fb_dma_irq,
+-                        0, "bcm2708_fb dma", fb);
++      ret = request_irq(fbdev->dma_irq, bcm2708_fb_dma_irq,
++                        0, "bcm2708_fb DMA", fbdev);
+       if (ret) {
+-              pr_err("%s: failed to request DMA irq\n", __func__);
++              dev_err(&dev->dev,
++                      "Failed to request DMA irq\n");
+               goto free_dma_chan;
+       }
+-      pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
++      rpi_firmware_property(fbdev->fw,
++                            RPI_FIRMWARE_GET_VC_MEMORY,
++                            &gpu_mem, sizeof(gpu_mem));
++
++      for (i = 0; i < num_displays; i++) {
++              struct bcm2708_fb *fb = &fbdev->displays[i];
++
++              fb->display_settings.display_num = i;
++              fb->dev = dev;
++              fb->fb.device = &dev->dev;
++              fb->fbdev = fbdev;
++
++              fb->gpu.base = gpu_mem.base;
++              fb->gpu.length = gpu_mem.length;
++
++              if (fbdev->firmware_supports_multifb) {
++                      ret = rpi_firmware_property(fw,
++                                                  RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS,
++                                                  &fb->display_settings,
++                                                  GET_DISPLAY_SETTINGS_PAYLOAD_SIZE);
++              } else {
++                      memset(&fb->display_settings, 0,
++                             sizeof(fb->display_settings));
++              }
++
++              ret = bcm2708_fb_register(fb);
+-      fb->dev = dev;
+-      fb->fb.device = &dev->dev;
++              if (ret == 0) {
++                      bcm2708_fb_debugfs_init(fb);
+-      /* failure here isn't fatal, but we'll fail in vc_mem_copy if
+-       * fb->gpu is not valid
+-       */
+-      rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
+-                            sizeof(fb->gpu));
++                      fbdev->num_displays++;
+-      ret = bcm2708_fb_register(fb);
+-      if (ret == 0) {
+-              platform_set_drvdata(dev, fb);
+-              goto out;
++                      dev_info(&dev->dev,
++                               "Registered framebuffer for display %u, size %ux%u\n",
++                               fb->display_settings.display_num,
++                               fb->fb.var.xres,
++                               fb->fb.var.yres);
++              } else {
++                      // Use this to flag if this FB entry is in use.
++                      fb->fbdev = NULL;
++              }
++      }
++
++      // Did we actually successfully create any FB's?
++      if (fbdev->num_displays) {
++              init_waitqueue_head(&fbdev->dma_waitq);
++              platform_set_drvdata(dev, fbdev);
++              return ret;
+       }
+ free_dma_chan:
+-      bcm_dma_chan_free(fb->dma_chan);
++      bcm_dma_chan_free(fbdev->dma_chan);
+ free_cb:
+-      dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
++      dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
++                            fbdev->cb_handle);
+ free_fb:
+-      kfree(fb);
+-free_region:
+       dev_err(&dev->dev, "probe failed, err %d\n", ret);
+-out:
++
+       return ret;
+ }
+ static int bcm2708_fb_remove(struct platform_device *dev)
+ {
+-      struct bcm2708_fb *fb = platform_get_drvdata(dev);
++      struct bcm2708_fb_dev *fbdev = platform_get_drvdata(dev);
++      int i;
+       platform_set_drvdata(dev, NULL);
+-      if (fb->fb.screen_base)
+-              iounmap(fb->fb.screen_base);
+-      unregister_framebuffer(&fb->fb);
+-
+-      dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
+-      bcm_dma_chan_free(fb->dma_chan);
+-
+-      bcm2708_fb_debugfs_deinit(fb);
++      for (i = 0; i < fbdev->num_displays; i++) {
++              if (fbdev->displays[i].fb.screen_base)
++                      iounmap(fbdev->displays[i].fb.screen_base);
++
++              if (fbdev->displays[i].fbdev) {
++                      unregister_framebuffer(&fbdev->displays[i].fb);
++                      bcm2708_fb_debugfs_deinit(&fbdev->displays[i]);
++              }
++      }
+-      free_irq(fb->dma_irq, fb);
++      dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
++                            fbdev->cb_handle);
++      bcm_dma_chan_free(fbdev->dma_chan);
++      free_irq(fbdev->dma_irq, fbdev);
+-      kfree(fb);
++      mutex_destroy(&fbdev->dma_mutex);
+       return 0;
+ }
+@@ -978,10 +1254,10 @@ static struct platform_driver bcm2708_fb
+       .probe = bcm2708_fb_probe,
+       .remove = bcm2708_fb_remove,
+       .driver = {
+-                 .name = DRIVER_NAME,
+-                 .owner = THIS_MODULE,
+-                 .of_match_table = bcm2708_fb_of_match_table,
+-                 },
++                .name = DRIVER_NAME,
++                .owner = THIS_MODULE,
++                .of_match_table = bcm2708_fb_of_match_table,
++                },
+ };
+ static int __init bcm2708_fb_init(void)
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -138,9 +138,11 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH =                  0x00048005,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER =            0x00048006,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE =             0x00048007,
++      RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH =                  0x00048008,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET =         0x00048009,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN =               0x0004800a,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE =                0x0004800b,
++
+       RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF =               0x0004801f,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF =            0x00048020,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC =                  0x0004800e,
+@@ -159,6 +161,8 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
+ };
++#define GET_DISPLAY_SETTINGS_PAYLOAD_SIZE 64
++
+ #if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
+ int rpi_firmware_property(struct rpi_firmware *fw,
+                         u32 tag, void *data, size_t len);
diff --git a/target/linux/brcm2708/patches-4.19/950-0555-staging-vcsm-cma-Drop-logging-level-on-messages-in-v.patch b/target/linux/brcm2708/patches-4.19/950-0555-staging-vcsm-cma-Drop-logging-level-on-messages-in-v.patch
deleted file mode 100644 (file)
index 320552e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From c38256621d4dffbbc0c19737d724724f04b0df9a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 16 May 2019 15:17:19 +0100
-Subject: [PATCH] staging: vcsm-cma: Drop logging level on messages in
- vc_sm_release_resource
-
-They weren't errors but were logged as such.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -301,14 +301,13 @@ static void vc_sm_release_resource(struc
-       if (buffer->vc_handle) {
-               /* We've sent the unmap request but not had the response. */
--              pr_err("[%s]: Waiting for VPU unmap response on %p\n",
--                     __func__, buffer);
-+              pr_debug("[%s]: Waiting for VPU unmap response on %p\n",
-+                       __func__, buffer);
-               goto defer;
-       }
-       if (buffer->in_use) {
-               /* dmabuf still in use - we await the release */
--              pr_err("[%s]: buffer %p is still in use\n",
--                     __func__, buffer);
-+              pr_debug("[%s]: buffer %p is still in use\n", __func__, buffer);
-               goto defer;
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0556-ARM-dts-bcm283x-Move-BCM2835-6-7-specific-to-bcm2835.patch b/target/linux/brcm2708/patches-4.19/950-0556-ARM-dts-bcm283x-Move-BCM2835-6-7-specific-to-bcm2835.patch
new file mode 100644 (file)
index 0000000..e3ee39a
--- /dev/null
@@ -0,0 +1,189 @@
+From 545c00748a070340e9669740e45afc2672e1fcb6 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 19 May 2019 12:26:21 +0200
+Subject: [PATCH] ARM: dts: bcm283x: Move BCM2835/6/7 specific to
+ bcm2835-common.dtsi
+
+We want all common BCM2835/6/7/8 functions in bcm283x.dtsi and all
+BCM2835/6/7 specific in the new bcm2835-common.dtsi.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2835-common.dtsi | 53 +++++++++++++++++++++++++++
+ arch/arm/boot/dts/bcm2835.dtsi        |  1 +
+ arch/arm/boot/dts/bcm2836.dtsi        |  1 +
+ arch/arm/boot/dts/bcm2837.dtsi        |  1 +
+ arch/arm/boot/dts/bcm283x.dtsi        | 43 +---------------------
+ 5 files changed, 57 insertions(+), 42 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2835-common.dtsi
+
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2835-common.dtsi
+@@ -0,0 +1,53 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/* This include file covers the common peripherals and configuration between
++ * bcm2835, bcm2836 and bcm2837 implementations.
++ */
++
++/ {
++      soc {
++              timer@7e003000 {
++                      compatible = "brcm,bcm2835-system-timer";
++                      reg = <0x7e003000 0x1000>;
++                      interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
++                      /* This could be a reference to BCM2835_CLOCK_TIMER,
++                       * but we don't have the driver using the common clock
++                       * support yet.
++                       */
++                      clock-frequency = <1000000>;
++              };
++
++              intc: interrupt-controller@7e00b200 {
++                      compatible = "brcm,bcm2835-armctrl-ic";
++                      reg = <0x7e00b200 0x200>;
++                      interrupt-controller;
++                      #interrupt-cells = <2>;
++              };
++
++              thermal: thermal@7e212000 {
++                      compatible = "brcm,bcm2835-thermal";
++                      reg = <0x7e212000 0x8>;
++                      clocks = <&clocks BCM2835_CLOCK_TSENS>;
++                      #thermal-sensor-cells = <0>;
++                      status = "disabled";
++              };
++
++              v3d: v3d@7ec00000 {
++                      compatible = "brcm,bcm2835-v3d";
++                      reg = <0x7ec00000 0x1000>;
++                      interrupts = <1 10>;
++              };
++      };
++};
++
++&gpio {
++      i2c_slave_gpio18: i2c_slave_gpio18 {
++              brcm,pins = <18 19 20 21>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      jtag_gpio4: jtag_gpio4 {
++              brcm,pins = <4 5 6 12 13>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++};
+--- a/arch/arm/boot/dts/bcm2835.dtsi
++++ b/arch/arm/boot/dts/bcm2835.dtsi
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include "bcm283x.dtsi"
++#include "bcm2835-common.dtsi"
+ / {
+       compatible = "brcm,bcm2835";
+--- a/arch/arm/boot/dts/bcm2836.dtsi
++++ b/arch/arm/boot/dts/bcm2836.dtsi
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include "bcm283x.dtsi"
++#include "bcm2835-common.dtsi"
+ / {
+       compatible = "brcm,bcm2836";
+--- a/arch/arm/boot/dts/bcm2837.dtsi
++++ b/arch/arm/boot/dts/bcm2837.dtsi
+@@ -1,4 +1,5 @@
+ #include "bcm283x.dtsi"
++#include "bcm2835-common.dtsi"
+ / {
+       compatible = "brcm,bcm2837";
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -55,17 +55,6 @@
+               #address-cells = <1>;
+               #size-cells = <1>;
+-              timer@7e003000 {
+-                      compatible = "brcm,bcm2835-system-timer";
+-                      reg = <0x7e003000 0x1000>;
+-                      interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
+-                      /* This could be a reference to BCM2835_CLOCK_TIMER,
+-                       * but we don't have the driver using the common clock
+-                       * support yet.
+-                       */
+-                      clock-frequency = <1000000>;
+-              };
+-
+               txp@7e004000 {
+                       compatible = "brcm,bcm2835-txp";
+                       reg = <0x7e004000 0x20>;
+@@ -113,13 +102,6 @@
+                       brcm,dma-channel-mask = <0x7f35>;
+               };
+-              intc: interrupt-controller@7e00b200 {
+-                      compatible = "brcm,bcm2835-armctrl-ic";
+-                      reg = <0x7e00b200 0x200>;
+-                      interrupt-controller;
+-                      #interrupt-cells = <2>;
+-              };
+-
+               watchdog@7e100000 {
+                       compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
+                       #power-domain-cells = <1>;
+@@ -183,8 +165,7 @@
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+-                      /* Defines pin muxing groups according to
+-                       * BCM2835-ARM-Peripherals.pdf page 102.
++                      /* Defines common pin muxing groups
+                        *
+                        * While each pin can have its mux selected
+                        * for various functions individually, some
+@@ -262,15 +243,7 @@
+                               brcm,pins = <44 45>;
+                               brcm,function = <BCM2835_FSEL_ALT2>;
+                       };
+-                      i2c_slave_gpio18: i2c_slave_gpio18 {
+-                              brcm,pins = <18 19 20 21>;
+-                              brcm,function = <BCM2835_FSEL_ALT3>;
+-                      };
+-                      jtag_gpio4: jtag_gpio4 {
+-                              brcm,pins = <4 5 6 12 13>;
+-                              brcm,function = <BCM2835_FSEL_ALT5>;
+-                      };
+                       jtag_gpio22: jtag_gpio22 {
+                               brcm,pins = <22 23 24 25 26 27>;
+                               brcm,function = <BCM2835_FSEL_ALT4>;
+@@ -487,14 +460,6 @@
+               };
+-              thermal: thermal@7e212000 {
+-                      compatible = "brcm,bcm2835-thermal";
+-                      reg = <0x7e212000 0x8>;
+-                      clocks = <&clocks BCM2835_CLOCK_TSENS>;
+-                      #thermal-sensor-cells = <0>;
+-                      status = "disabled";
+-              };
+-
+               aux: aux@7e215000 {
+                       compatible = "brcm,bcm2835-aux";
+                       #clock-cells = <1>;
+@@ -660,12 +625,6 @@
+                       phy-names = "usb2-phy";
+               };
+-              v3d: v3d@7ec00000 {
+-                      compatible = "brcm,bcm2835-v3d";
+-                      reg = <0x7ec00000 0x1000>;
+-                      interrupts = <1 10>;
+-              };
+-
+               vc4: gpu {
+                       compatible = "brcm,bcm2835-vc4";
+               };
diff --git a/target/linux/brcm2708/patches-4.19/950-0556-staging-vcsm-cma-Fixup-the-alloc-code-handling-of-ke.patch b/target/linux/brcm2708/patches-4.19/950-0556-staging-vcsm-cma-Fixup-the-alloc-code-handling-of-ke.patch
deleted file mode 100644 (file)
index 5e5c6bc..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From 52f881e3afa89bb1ca9e8b037f7600bcc97626e8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 22 May 2019 15:40:37 +0100
-Subject: [PATCH] staging: vcsm-cma: Fixup the alloc code handling of
- kernel_id
-
-The allocation code had been copied in from an old branch prior
-to having added the IDR for 64bit support. It was therefore pushing
-a pointer into the kernel_id field instead of an IDR handle, the
-lookup therefore failed, and we never released the buffer.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -1206,7 +1206,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-       import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-       import.size = aligned_size;
--      import.kernel_id = (uint32_t)buffer;
-+      import.kernel_id = get_kernel_id(buffer);
-       /* Wrap it into a videocore buffer. */
-       status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-@@ -1231,6 +1231,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-       buffer->size = import.size;
-       buffer->dma_addr = import.addr;
-       buffer->vpu_state = VPU_MAPPED;
-+      buffer->kernel_id = import.kernel_id;
-       //buffer->res_cached = ioparam->cached;
-       fd = dma_buf_fd(dmabuf, O_CLOEXEC);
diff --git a/target/linux/brcm2708/patches-4.19/950-0557-ARM-dts-Add-bcm2711-rpi-4-b.dts-and-components.patch b/target/linux/brcm2708/patches-4.19/950-0557-ARM-dts-Add-bcm2711-rpi-4-b.dts-and-components.patch
new file mode 100644 (file)
index 0000000..16980a8
--- /dev/null
@@ -0,0 +1,1129 @@
+From ff78cbcd8d7d656a5f43abd2c744e610b8c6c740 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 13:54:21 +0100
+Subject: [PATCH] ARM: dts: Add bcm2711-rpi-4-b.dts and components
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile            |   1 +
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 320 ++++++++++++
+ arch/arm/boot/dts/bcm2711.dtsi        |  50 ++
+ arch/arm/boot/dts/bcm2838.dtsi        | 724 ++++++++++++++++++++++++++
+ 4 files changed, 1095 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+ create mode 100644 arch/arm/boot/dts/bcm2711.dtsi
+ create mode 100644 arch/arm/boot/dts/bcm2838.dtsi
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2708-rpi-zero-w.dtb \
+       bcm2709-rpi-2-b.dtb \
+       bcm2710-rpi-3-b.dtb \
++      bcm2711-rpi-4-b.dtb \
+       bcm2710-rpi-3-b-plus.dtb \
+       bcm2710-rpi-cm3.dtb
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -0,0 +1,320 @@
++/dts-v1/;
++
++#include "bcm2711.dtsi"
++
++/ {
++      compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
++      model = "Raspberry Pi 4 Model B";
++      #address-cells = <2>;
++      #size-cells = <1>;
++
++      memory {
++              device_type = "memory";
++              reg = <0x0 0x0 0x0>;
++      };
++
++      chosen {
++              bootargs = "8250.nr_uarts=1 cma=64M";
++      };
++
++      aliases {
++              serial0 = &uart1;
++              serial1 = &uart0;
++              mmc0 = &emmc2;
++              mmc1 = &mmcnr;
++              mmc2 = &sdhost;
++              /delete-property/ ethernet;
++              /delete-property/ intc;
++              ethernet0 = &genet;
++      };
++};
++
++&soc {
++      virtgpio: virtgpio {
++              compatible = "brcm,bcm2835-virtgpio";
++              gpio-controller;
++              #gpio-cells = <2>;
++              firmware = <&firmware>;
++              status = "okay";
++      };
++};
++
++&mmcnr {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdio_pins>;
++      bus-width = <4>;
++      status = "okay";
++};
++
++&firmware {
++      expgpio: expgpio {
++              compatible = "raspberrypi,firmware-gpio";
++              gpio-controller;
++              #gpio-cells = <2>;
++              status = "okay";
++      };
++};
++
++&uart0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart0_pins &bt_pins>;
++      status = "okay";
++};
++
++&uart1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart1_pins>;
++      status = "okay";
++};
++
++&spi0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
++      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
++
++      spidev0: spidev@0{
++              compatible = "spidev";
++              reg = <0>;      /* CE0 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++
++      spidev1: spidev@1{
++              compatible = "spidev";
++              reg = <1>;      /* CE1 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++};
++
++// =============================================
++// Board specific stuff here
++
++/ {
++
++      sd_io_1v8_reg: sd_io_1v8_reg {
++              status = "okay";
++              compatible = "regulator-gpio";
++              vin-supply = <&vdd_5v0_reg>;
++              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>;
++      };
++};
++
++&sdhost {
++      status = "disabled";
++};
++
++&emmc2 {
++      status = "okay";
++      broken-cd;
++      vqmmc-supply = <&sd_io_1v8_reg>;
++};
++
++&leds {
++      act_led: act {
++              label = "led0";
++              linux,default-trigger = "mmc0";
++              gpios = <&gpio 42 0>;
++      };
++
++      pwr_led: pwr {
++              label = "led1";
++              linux,default-trigger = "input";
++              gpios = <&expgpio 2 0>;
++      };
++};
++
++&audio {
++      pinctrl-names = "default";
++      pinctrl-0 = <&audio_pins>;
++};
++
++&sdhost_gpio48 {
++      brcm,pins = <22 23 24 25 26 27>;
++      brcm,function = <BCM2835_FSEL_ALT0>;
++};
++
++&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>;
++      };
++
++      i2c1_pins: i2c1 {
++              brcm,pins = <2 3>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++      };
++
++      i2c3_pins: i2c3 {
++              brcm,pins = <4 5>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++
++      i2c4_pins: i2c4 {
++              brcm,pins = <8 9>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++
++      i2c5_pins: i2c5 {
++              brcm,pins = <12 13>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++
++      i2c6_pins: i2c6 {
++              brcm,pins = <22 23>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++
++      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>;
++      };
++
++      audio_pins: audio_pins {
++              brcm,pins = <40 41>;
++              brcm,function = <4>;
++      };
++};
++
++&i2c0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c0_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c1_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c2 {
++      clock-frequency = <100000>;
++};
++
++&i2s {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2s_pins>;
++};
++
++/ {
++      __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";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -0,0 +1,50 @@
++#include "bcm2838.dtsi"
++#include "bcm270x.dtsi"
++#include "bcm2708-rpi.dtsi"
++
++/ {
++      soc {
++              /delete-node/ mailbox@7e00b840;
++              /delete-node/ v3d@7ec00000;
++      };
++
++      __overrides__ {
++              arm_freq;
++      };
++};
++
++&dma {
++      brcm,dma-channel-mask = <0x7ef5>;
++};
++
++&txp {
++      interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&firmwarekms {
++      interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&smi {
++      interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&mmc {
++      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&mmcnr {
++      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&usb {
++      reg = <0x7e980000 0x10000>,
++            <0x7e00b200 0x200>;
++      interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
++                   <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&gpio {
++      interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
++                   <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -0,0 +1,724 @@
++// SPDX-License-Identifier: GPL-2.0
++#include "bcm283x.dtsi"
++
++#include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/soc/bcm2835-pm.h>
++
++/ {
++      compatible = "brcm,bcm2838", "brcm,bcm2837";
++
++      interrupt-parent = <&gicv2>;
++
++      soc {
++              ranges = <0x7e000000  0x0 0xfe000000  0x01800000>,
++                       <0x7c000000  0x0 0xfc000000  0x02000000>,
++                       <0x40000000  0x0 0xff800000  0x00800000>;
++              /* Emulate a contiguous 30-bit address range for DMA */
++              dma-ranges = <0xc0000000  0x0 0x00000000  0x3c000000>;
++
++              /delete-node/ mailbox@7e00b840;
++              /delete-node/ interrupt-controller@7e00f300;
++
++              local_intc: local_intc@40000000 {
++                      compatible = "brcm,bcm2836-l1-intc";
++                      reg = <0x40000000 0x100>;
++              };
++
++              gicv2: gic400@40041000 {
++                      interrupt-controller;
++                      #interrupt-cells = <3>;
++                      compatible = "arm,gic-400";
++                      reg =   <0x40041000 0x1000>,
++                              <0x40042000 0x2000>,
++                              <0x40046000 0x2000>,
++                              <0x40048000 0x2000>;
++              };
++
++              thermal: thermal@7d5d2200 {
++                      compatible = "brcm,avs-tmon-bcm2838";
++                      reg = <0x7d5d2200 0x2c>;
++                      interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
++                      interrupt-names = "tmon";
++                      clocks = <&clocks BCM2835_CLOCK_TSENS>;
++                      #thermal-sensor-cells = <0>;
++                      status = "okay";
++              };
++
++              pm: watchdog@7e100000 {
++                      reg = <0x7e100000 0x114>,
++                            <0x7e00a000 0x24>,
++                            <0x7ec11000 0x20>;
++              };
++
++              rng@7e104000 {
++                      interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              uart2: serial@7e201400 {
++                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++                      reg = <0x7e201400 0x200>;
++                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_UART>,
++                               <&clocks BCM2835_CLOCK_VPU>;
++                      clock-names = "uartclk", "apb_pclk";
++                      arm,primecell-periphid = <0x00241011>;
++                      status = "disabled";
++              };
++
++              uart3: serial@7e201600 {
++                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++                      reg = <0x7e201600 0x200>;
++                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_UART>,
++                               <&clocks BCM2835_CLOCK_VPU>;
++                      clock-names = "uartclk", "apb_pclk";
++                      arm,primecell-periphid = <0x00241011>;
++                      status = "disabled";
++              };
++
++              uart4: serial@7e201800 {
++                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++                      reg = <0x7e201800 0x200>;
++                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_UART>,
++                               <&clocks BCM2835_CLOCK_VPU>;
++                      clock-names = "uartclk", "apb_pclk";
++                      arm,primecell-periphid = <0x00241011>;
++                      status = "disabled";
++              };
++
++              uart5: serial@7e201a00 {
++                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++                      reg = <0x7e201a00 0x200>;
++                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_UART>,
++                               <&clocks BCM2835_CLOCK_VPU>;
++                      clock-names = "uartclk", "apb_pclk";
++                      arm,primecell-periphid = <0x00241011>;
++                      status = "disabled";
++              };
++
++              spi@7e204000 {
++                      reg = <0x7e204000 0x0200>;
++                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              spi3: spi@7e204600 {
++                      compatible = "brcm,bcm2835-spi";
++                      reg = <0x7e204600 0x0200>;
++                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              spi4: spi@7e204800 {
++                      compatible = "brcm,bcm2835-spi";
++                      reg = <0x7e204800 0x0200>;
++                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              spi5: spi@7e204a00 {
++                      compatible = "brcm,bcm2835-spi";
++                      reg = <0x7e204a00 0x0200>;
++                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              spi6: spi@7e204c00 {
++                      compatible = "brcm,bcm2835-spi";
++                      reg = <0x7e204c00 0x0200>;
++                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              i2c3: i2c@7e205600 {
++                      compatible = "brcm,bcm2835-i2c";
++                      reg = <0x7e205600 0x200>;
++                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              i2c4: i2c@7e205800 {
++                      compatible = "brcm,bcm2835-i2c";
++                      reg = <0x7e205800 0x200>;
++                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              i2c5: i2c@7e205a00 {
++                      compatible = "brcm,bcm2835-i2c";
++                      reg = <0x7e205a00 0x200>;
++                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              i2c6: i2c@7e205c00 {
++                      compatible = "brcm,bcm2835-i2c";
++                      reg = <0x7e205c00 0x200>;
++                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++
++              pixelvalve@7e206000 {
++                      interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              pixelvalve@7e207000 {
++                      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              emmc2: emmc2@7e340000 {
++                      compatible = "brcm,bcm2711-emmc2";
++                      status = "okay";
++                      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2838_CLOCK_EMMC2>;
++                      reg = <0x7e340000 0x100>;
++              };
++
++              hvs@7e400000 {
++                      interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              pixelvalve@7e807000 {
++                      interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
++              };
++      };
++
++      arm-pmu {
++              /*
++               * N.B. the A72 PMU support only exists in arch/arm64, hence
++               * the fallback to the A53 version.
++               */
++              compatible = "arm,cortex-a72-pmu", "arm,cortex-a53-pmu";
++              interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
++                      <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
++                      <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
++                      <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
++      };
++
++      timer {
++              compatible = "arm,armv7-timer";
++              interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>;
++              arm,cpu-registers-not-fw-configured;
++              always-on;
++      };
++
++      cpus: cpus {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
++
++              cpu0: cpu@0 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a72";
++                      reg = <0>;
++                      enable-method = "spin-table";
++                      cpu-release-addr = <0x0 0x000000d8>;
++              };
++
++              cpu1: cpu@1 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a72";
++                      reg = <1>;
++                      enable-method = "spin-table";
++                      cpu-release-addr = <0x0 0x000000e0>;
++              };
++
++              cpu2: cpu@2 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a72";
++                      reg = <2>;
++                      enable-method = "spin-table";
++                      cpu-release-addr = <0x0 0x000000e8>;
++              };
++
++              cpu3: cpu@3 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a72";
++                      reg = <3>;
++                      enable-method = "spin-table";
++                      cpu-release-addr = <0x0 0x000000f0>;
++              };
++      };
++
++      v3dbus {
++              compatible = "simple-bus";
++              #address-cells = <1>;
++              #size-cells = <1>;
++              ranges = <0x7c500000  0x0 0xfc500000  0x03300000>,
++                       <0x40000000  0x0 0xff800000  0x00800000>;
++              dma-ranges = <0x00000000  0x0 0x00000000  0x3c000000>;
++
++              v3d: v3d@7ec04000 {
++                      compatible = "brcm,2711-v3d";
++                      reg =
++                          <0x7ec00000 0x4000>,
++                          <0x7ec04000 0x4000>;
++                      reg-names = "hub", "core0";
++
++                      power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
++                      resets = <&pm BCM2835_RESET_V3D>;
++                      clocks = <&clocks BCM2835_CLOCK_V3D>;
++                      interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "okay";
++              };
++      };
++
++      scb: scb {
++              compatible = "simple-bus";
++              #address-cells = <2>;
++              #size-cells = <1>;
++
++              ranges = <0x0 0x7c000000  0x0 0xfc000000  0x03800000>,
++                       <0x0 0x40000000  0x0 0xff800000  0x00800000>,
++                       <0x6 0x00000000  0x6 0x00000000  0x40000000>,
++                       <0x0 0x00000000  0x0 0x00000000  0xfc000000>;
++              dma-ranges = <0x0 0x00000000  0x0 0x00000000  0xfc000000>;
++
++              pcie_0: pcie@7d500000 {
++                      reg = <0x0 0x7d500000 0x9310>,
++                            <0x0 0x7e00f300 0x20>;
++                      msi-controller;
++                      msi-parent = <&pcie_0>;
++                      #address-cells = <3>;
++                      #interrupt-cells = <1>;
++                      #size-cells = <2>;
++                      bus-range = <0x0 0x01>;
++                      compatible = "brcm,bcm7211-pcie", "brcm,bcm7445-pcie",
++                                   "brcm,pci-plat-dev";
++                      max-link-speed = <2>;
++                      tot-num-pcie = <1>;
++                      linux,pci-domain = <0>;
++                      interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
++                                   <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
++                      interrupt-names = "pcie", "msi";
++                      interrupt-map-mask = <0x0 0x0 0x0 0x7>;
++                      interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143
++                                              IRQ_TYPE_LEVEL_HIGH
++                                       0 0 0 2 &gicv2 GIC_SPI 144
++                                              IRQ_TYPE_LEVEL_HIGH
++                                       0 0 0 3 &gicv2 GIC_SPI 145
++                                              IRQ_TYPE_LEVEL_HIGH
++                                       0 0 0 4 &gicv2 GIC_SPI 146
++                                              IRQ_TYPE_LEVEL_HIGH>;
++
++                      /* Map outbound accesses from scb:0x6_00000000-03ffffff
++                       * to pci:0x0_f8000000-fbffffff
++                       */
++                      ranges = <0x02000000 0x0 0xf8000000  0x6 0x00000000
++                                0x0 0x04000000>;
++                      /* Map inbound accesses from pci:0x0_00000000..ffffffff
++                       * to scb:0x0_00000000-ffffffff
++                       */
++                      dma-ranges = <0x02000000 0x0 0x00000000  0x0 0x00000000
++                                    0x1 0x00000000>;
++                      status = "okay";
++              };
++
++              genet: genet@7d580000 {
++                      compatible = "brcm,genet-v5";
++                      reg = <0x0 0x7d580000 0x10000>;
++                      status = "okay";
++                      #address-cells = <0x1>;
++                      #size-cells = <0x1>;
++                      interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
++                                   <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
++                      phy-handle = <&phy1>;
++                      phy-mode = "rgmii";
++                      mdio@e14 {
++                              #address-cells = <0x0>;
++                              #size-cells = <0x1>;
++                              compatible = "brcm,genet-mdio-v5";
++                              reg = <0xe14 0x8>;
++                              reg-names = "mdio";
++                              phy1: genet-phy@0 {
++                                      compatible =
++                                              "ethernet-phy-ieee802.3-c22";
++                                      /* No interrupts - use PHY_POLL */
++                                      max-speed = <1000>;
++                                      reg = <0x1>;
++                              };
++                      };
++              };
++
++              xhci: xhci@7e9c0000 {
++                      compatible = "generic-xhci";
++                      status = "disabled";
++                      reg = <0x0 0x7e9c0000 0x100000>;
++                      interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              vchiq: mailbox@7e00b840 {
++                      compatible = "brcm,bcm2838-vchiq";
++                      reg = <0 0x7e00b840 0x3c>;
++                      interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              hevc-decoder@7eb00000 {
++                      compatible = "raspberrypi,argon-hevc-decoder";
++                      reg = <0x0 0x7eb00000 0x10000>;
++                      status = "okay";
++              };
++
++              argon-local-intc@7eb10000 {
++                      compatible = "raspberrypi,argon-local-intc";
++                      reg = <0x0 0x7eb10000 0x1000>;
++                      status = "okay";
++                      interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              h264-decoder@7eb20000 {
++                      compatible = "raspberrypi,argon-h264-decoder";
++                      reg = <0x0 0x7eb20000 0x10000>;
++                      status = "okay";
++              };
++
++              vp9-decoder@7eb30000 {
++                      compatible = "raspberrypi,argon-vp9-decoder";
++                      reg = <0x0 0x7eb30000 0x10000>;
++                      status = "okay";
++              };
++      };
++};
++
++&clk_osc {
++      clock-frequency = <54000000>;
++};
++
++&clocks {
++      compatible = "brcm,bcm2838-cprman";
++};
++
++&cpu_thermal {
++      coefficients = <(-487)  410040>;
++};
++
++&dsi0 {
++      interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&dsi1 {
++      interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&gpio {
++      gpclk0_gpio49: gpclk0_gpio49 {
++              brcm,pins = <49>;
++              brcm,function = <BCM2835_FSEL_ALT1>;
++              brcm,pull = <BCM2835_PUD_OFF>;
++      };
++      gpclk1_gpio50: gpclk1_gpio50 {
++              brcm,pins = <50>;
++              brcm,function = <BCM2835_FSEL_ALT1>;
++              brcm,pull = <BCM2835_PUD_OFF>;
++      };
++      gpclk2_gpio51: gpclk2_gpio51 {
++              brcm,pins = <51>;
++              brcm,function = <BCM2835_FSEL_ALT1>;
++              brcm,pull = <BCM2835_PUD_OFF>;
++      };
++
++      i2c0_gpio46: i2c0_gpio46 {
++              brcm,pins = <46 47>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++      };
++      i2c1_gpio46: i2c1_gpio46 {
++              brcm,pins = <46 47>;
++              brcm,function = <BCM2835_FSEL_ALT1>;
++      };
++      i2c3_gpio2: i2c3_gpio2 {
++              brcm,pins = <2 3>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c3_gpio4: i2c3_gpio4 {
++              brcm,pins = <4 5>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c4_gpio6: i2c4_gpio6 {
++              brcm,pins = <6 7>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c4_gpio8: i2c4_gpio8 {
++              brcm,pins = <8 9>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c5_gpio10: i2c5_gpio10 {
++              brcm,pins = <10 11>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c5_gpio12: i2c5_gpio12 {
++              brcm,pins = <12 13>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c6_gpio0: i2c6_gpio0 {
++              brcm,pins = <0 1>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c6_gpio22: i2c6_gpio22 {
++              brcm,pins = <22 23>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      i2c_slave_gpio8: i2c_slave_gpio8 {
++              brcm,pins = <8 9 10 11>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      jtag_gpio48: jtag_gpio48 {
++              brcm,pins = <48 49 50 51 52 53>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++      };
++
++      mii_gpio28: mii_gpio28 {
++              brcm,pins = <28 29 30 31>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++      };
++      mii_gpio36: mii_gpio36 {
++              brcm,pins = <36 37 38 39>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++
++      pcm_gpio50: pcm_gpio50 {
++              brcm,pins = <50 51 52 53>;
++              brcm,function = <BCM2835_FSEL_ALT2>;
++      };
++
++      pwm0_gpio52: pwm0_gpio52 {
++              brcm,pins = <52>;
++              brcm,function = <BCM2835_FSEL_ALT1>;
++              brcm,pull = <BCM2835_PUD_OFF>;
++      };
++      pwm1_gpio53: pwm1_gpio53 {
++              brcm,pins = <53>;
++              brcm,function = <BCM2835_FSEL_ALT1>;
++              brcm,pull = <BCM2835_PUD_OFF>;
++      };
++
++      /* The following group consists of:
++         *  RGMII_START_STOP
++         *  RGMII_RX_OK
++         */
++      rgmii_gpio35: rgmii_gpio35 {
++              brcm,pins = <35 36>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++      };
++      rgmii_irq_gpio34: rgmii_irq_gpio34 {
++              brcm,pins = <34>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      rgmii_irq_gpio39: rgmii_irq_gpio39 {
++              brcm,pins = <39>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++      };
++      rgmii_mdio_gpio28: rgmii_mdio_gpio28 {
++              brcm,pins = <28 29>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      rgmii_mdio_gpio37: rgmii_mdio_gpio37 {
++              brcm,pins = <37 38>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++      };
++
++      spi0_gpio46: spi0_gpio46 {
++              brcm,pins = <46 47 48 49>;
++              brcm,function = <BCM2835_FSEL_ALT2>;
++      };
++      spi2_gpio46: spi2_gpio46 {
++              brcm,pins = <46 47 48 49 50>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++      };
++      spi3_gpio0: spi3_gpio0 {
++              brcm,pins = <0 1 2 3>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++      spi4_gpio4: spi4_gpio4 {
++              brcm,pins = <4 5 6 7>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++      spi5_gpio12: spi5_gpio12 {
++              brcm,pins = <12 13 14 15>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++      spi6_gpio18: spi6_gpio18 {
++              brcm,pins = <18 19 20 21>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      uart2_gpio0: uart2_gpio0 {
++              brcm,pins = <0 1>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++      };
++      uart2_ctsrts_gpio2: uart2_ctsrts_gpio2 {
++              brcm,pins = <2 3>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++      };
++      uart3_gpio4: uart3_gpio4 {
++              brcm,pins = <4 5>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++      };
++      uart3_ctsrts_gpio6: uart3_ctsrts_gpio6 {
++              brcm,pins = <6 7>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++      };
++      uart4_gpio8: uart4_gpio8 {
++              brcm,pins = <8 9>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++      };
++      uart4_ctsrts_gpio10: uart4_ctsrts_gpio10 {
++              brcm,pins = <10 11>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++      };
++      uart5_gpio12: uart5_gpio12 {
++              brcm,pins = <12 13>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++      };
++      uart5_ctsrts_gpio14: uart5_ctsrts_gpio14 {
++              brcm,pins = <14 15>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++      };
++};
++
++&vec {
++      interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&usb {
++      interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&hdmi {
++      interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
++                   <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&uart1 {
++      interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&spi1 {
++      interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&spi2 {
++      interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&csi0 {
++      interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&csi1 {
++      interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&sdhci {
++      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&i2c0 {
++      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&i2c1 {
++      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&i2c2 {
++      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&gpio {
++      interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
++                   <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
++                   <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
++                   <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&mailbox {
++      interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&rng {
++      compatible = "brcm,bcm2838-rng200";
++};
++
++&sdhost {
++      interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&uart0 {
++      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&dma {
++      interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
++              <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
++              <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
++              <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
++              <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
++              <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
++              <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
++              <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  7 */
++              <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  8 */
++              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  9 */
++              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
++              /* DMA4 - 40 bit DMA engines */
++              <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4    11 */
++              <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4    12 */
++              <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4    13 */
++              <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4    14 */
++      interrupt-names = "dma0",
++                        "dma1",
++                        "dma2",
++                        "dma3",
++                        "dma4",
++                        "dma5",
++                        "dma6",
++                        "dma7",
++                        "dma8",
++                        "dma9",
++                        "dma10",
++                        "dma11",
++                        "dma12",
++                        "dma13",
++                        "dma14";
++      brcm,dma-channel-mask = <0x7ef5>;
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0557-Pulled-in-the-multi-frame-buffer-support-from-the-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0557-Pulled-in-the-multi-frame-buffer-support-from-the-Pi.patch
deleted file mode 100644 (file)
index 883d947..0000000
+++ /dev/null
@@ -1,925 +0,0 @@
-From 3e33fb46eb8791ba39fe4781f278487bcc2c3356 Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Thu, 14 Mar 2019 13:27:54 +0000
-Subject: [PATCH] Pulled in the multi frame buffer support from the Pi3
- repo
-
----
- drivers/video/fbdev/bcm2708_fb.c           | 580 +++++++++++++++------
- include/soc/bcm2835/raspberrypi-firmware.h |   4 +
- 2 files changed, 432 insertions(+), 152 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -2,6 +2,7 @@
-  *  linux/drivers/video/bcm2708_fb.c
-  *
-  * Copyright (C) 2010 Broadcom
-+ * Copyright (C) 2018 Raspberry Pi (Trading) Ltd
-  *
-  * This file is subject to the terms and conditions of the GNU General Public
-  * License.  See the file COPYING in the main directory of this archive
-@@ -13,6 +14,7 @@
-  * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
-  *
-  */
-+
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
-@@ -36,6 +38,7 @@
- #include <linux/dma-mapping.h>
- #include <linux/cred.h>
- #include <soc/bcm2835/raspberrypi-firmware.h>
-+#include <linux/mutex.h>
- //#define BCM2708_FB_DEBUG
- #define MODULE_NAME "bcm2708_fb"
-@@ -82,62 +85,139 @@ struct bcm2708_fb_stats {
-       u32 dma_irqs;
- };
-+struct vc4_display_settings_t {
-+      u32 display_num;
-+      u32 width;
-+      u32 height;
-+      u32 pitch;
-+      u32 depth;
-+      u32 virtual_width;
-+      u32 virtual_height;
-+      u32 virtual_width_offset;
-+      u32 virtual_height_offset;
-+      unsigned long fb_bus_address;
-+};
-+
-+struct bcm2708_fb_dev;
-+
- struct bcm2708_fb {
-       struct fb_info fb;
-       struct platform_device *dev;
--      struct rpi_firmware *fw;
-       u32 cmap[16];
-       u32 gpu_cmap[256];
-+      struct dentry *debugfs_dir;
-+      struct dentry *debugfs_subdir;
-+      unsigned long fb_bus_address;
-+      struct { u32 base, length; } gpu;
-+      struct vc4_display_settings_t display_settings;
-+      struct debugfs_regset32 screeninfo_regset;
-+      struct bcm2708_fb_dev *fbdev;
-+      unsigned int image_size;
-+      dma_addr_t dma_addr;
-+      void *cpuaddr;
-+};
-+
-+#define MAX_FRAMEBUFFERS 3
-+
-+struct bcm2708_fb_dev {
-+      int firmware_supports_multifb;
-+      /* Protects the DMA system from multiple FB access */
-+      struct mutex dma_mutex;
-       int dma_chan;
-       int dma_irq;
-       void __iomem *dma_chan_base;
--      void *cb_base;          /* DMA control blocks */
--      dma_addr_t cb_handle;
--      struct dentry *debugfs_dir;
-       wait_queue_head_t dma_waitq;
--      struct bcm2708_fb_stats stats;
--      unsigned long fb_bus_address;
--      struct { u32 base, length; } gpu;
-+      bool disable_arm_alloc;
-+      struct bcm2708_fb_stats dma_stats;
-+      void *cb_base;  /* DMA control blocks */
-+      dma_addr_t cb_handle;
-+      int instance_count;
-+      int num_displays;
-+      struct rpi_firmware *fw;
-+      struct bcm2708_fb displays[MAX_FRAMEBUFFERS];
- };
- #define to_bcm2708(info)      container_of(info, struct bcm2708_fb, fb)
- static void bcm2708_fb_debugfs_deinit(struct bcm2708_fb *fb)
- {
--      debugfs_remove_recursive(fb->debugfs_dir);
--      fb->debugfs_dir = NULL;
-+      debugfs_remove_recursive(fb->debugfs_subdir);
-+      fb->debugfs_subdir = NULL;
-+
-+      fb->fbdev->instance_count--;
-+
-+      if (!fb->fbdev->instance_count) {
-+              debugfs_remove_recursive(fb->debugfs_dir);
-+              fb->debugfs_dir = NULL;
-+      }
- }
- static int bcm2708_fb_debugfs_init(struct bcm2708_fb *fb)
- {
-+      char buf[3];
-+      struct bcm2708_fb_dev *fbdev = fb->fbdev;
-+
-       static struct debugfs_reg32 stats_registers[] = {
--              {
--                      "dma_copies",
--                      offsetof(struct bcm2708_fb_stats, dma_copies)
--              },
--              {
--                      "dma_irqs",
--                      offsetof(struct bcm2708_fb_stats, dma_irqs)
--              },
-+      {"dma_copies", offsetof(struct bcm2708_fb_stats, dma_copies)},
-+      {"dma_irqs",   offsetof(struct bcm2708_fb_stats, dma_irqs)},
-       };
--      fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
-+      static struct debugfs_reg32 screeninfo[] = {
-+      {"width",        offsetof(struct fb_var_screeninfo, xres)},
-+      {"height",       offsetof(struct fb_var_screeninfo, yres)},
-+      {"bpp",          offsetof(struct fb_var_screeninfo, bits_per_pixel)},
-+      {"xres_virtual", offsetof(struct fb_var_screeninfo, xres_virtual)},
-+      {"yres_virtual", offsetof(struct fb_var_screeninfo, yres_virtual)},
-+      {"xoffset",      offsetof(struct fb_var_screeninfo, xoffset)},
-+      {"yoffset",      offsetof(struct fb_var_screeninfo, yoffset)},
-+      };
-+
-+      fb->debugfs_dir = debugfs_lookup(DRIVER_NAME, NULL);
-+
-+      if (!fb->debugfs_dir)
-+              fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
-+
-       if (!fb->debugfs_dir) {
--              pr_warn("%s: could not create debugfs entry\n",
--                      __func__);
-+              dev_warn(fb->fb.dev, "%s: could not create debugfs folder\n",
-+                       __func__);
-+              return -EFAULT;
-+      }
-+
-+      snprintf(buf, sizeof(buf), "%u", fb->display_settings.display_num);
-+
-+      fb->debugfs_subdir = debugfs_create_dir(buf, fb->debugfs_dir);
-+
-+      if (!fb->debugfs_subdir) {
-+              dev_warn(fb->fb.dev, "%s: could not create debugfs entry %u\n",
-+                       __func__, fb->display_settings.display_num);
-               return -EFAULT;
-       }
--      fb->stats.regset.regs = stats_registers;
--      fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
--      fb->stats.regset.base = &fb->stats;
--
--      if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
--                                   &fb->stats.regset)) {
--              pr_warn("%s: could not create statistics registers\n",
--                      __func__);
-+      fbdev->dma_stats.regset.regs = stats_registers;
-+      fbdev->dma_stats.regset.nregs = ARRAY_SIZE(stats_registers);
-+      fbdev->dma_stats.regset.base = &fbdev->dma_stats;
-+
-+      if (!debugfs_create_regset32("dma_stats", 0444, fb->debugfs_subdir,
-+                                   &fbdev->dma_stats.regset)) {
-+              dev_warn(fb->fb.dev, "%s: could not create statistics registers\n",
-+                       __func__);
-+              goto fail;
-+      }
-+
-+      fb->screeninfo_regset.regs = screeninfo;
-+      fb->screeninfo_regset.nregs = ARRAY_SIZE(screeninfo);
-+      fb->screeninfo_regset.base = &fb->fb.var;
-+
-+      if (!debugfs_create_regset32("screeninfo", 0444, fb->debugfs_subdir,
-+                                   &fb->screeninfo_regset)) {
-+              dev_warn(fb->fb.dev,
-+                       "%s: could not create dimensions registers\n",
-+                       __func__);
-               goto fail;
-       }
-+
-+      fbdev->instance_count++;
-+
-       return 0;
- fail:
-@@ -145,6 +225,20 @@ fail:
-       return -EFAULT;
- }
-+static void set_display_num(struct bcm2708_fb *fb)
-+{
-+      if (fb && fb->fbdev && fb->fbdev->firmware_supports_multifb) {
-+              u32 tmp = fb->display_settings.display_num;
-+
-+              if (rpi_firmware_property(fb->fbdev->fw,
-+                                        RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM,
-+                                        &tmp,
-+                                        sizeof(tmp)))
-+                      dev_warn_once(fb->fb.dev,
-+                                    "Set display number call failed. Old GPU firmware?");
-+      }
-+}
-+
- static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var)
- {
-       int ret = 0;
-@@ -222,11 +316,11 @@ static int bcm2708_fb_check_var(struct f
-                               struct fb_info *info)
- {
-       /* info input, var output */
--      print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
-+      print_debug("%s(%p) %ux%u (%ux%u), %ul, %u\n",
-                   __func__, info, info->var.xres, info->var.yres,
-                   info->var.xres_virtual, info->var.yres_virtual,
--                  (int)info->screen_size, info->var.bits_per_pixel);
--      print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
-+                  info->screen_size, info->var.bits_per_pixel);
-+      print_debug("%s(%p) %ux%u (%ux%u), %u\n", __func__, var, var->xres,
-                   var->yres, var->xres_virtual, var->yres_virtual,
-                   var->bits_per_pixel);
-@@ -283,23 +377,96 @@ static int bcm2708_fb_set_par(struct fb_
-                       .xoffset = info->var.xoffset,
-                       .yoffset = info->var.yoffset,
-               .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
--                      .base = 0,
--                      .screen_size = 0,
--              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
--                      .pitch = 0,
-+                      /* base and screen_size will be initialised later */
-+              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-+                      /* pitch will be initialised later */
-       };
--      int ret;
-+      int ret, image_size;
-+
--      print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
-+      print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
-+                  info,
-                   info->var.xres, info->var.yres, info->var.xres_virtual,
-                   info->var.yres_virtual, (int)info->screen_size,
--                  info->var.bits_per_pixel);
-+                  info->var.bits_per_pixel, value);
-+
-+      /* Need to set the display number to act on first
-+       * Cannot do it in the tag list because on older firmware the call
-+       * will fail and stop the rest of the list being executed.
-+       * We can ignore this call failing as the default at other end is 0
-+       */
-+      set_display_num(fb);
-+
-+      /* Try allocating our own buffer. We can specify all the parameters */
-+      image_size = ((info->var.xres * info->var.yres) *
-+                    info->var.bits_per_pixel) >> 3;
-+
-+      if (!fb->fbdev->disable_arm_alloc &&
-+          (image_size != fb->image_size || !fb->dma_addr)) {
-+              if (fb->dma_addr) {
-+                      dma_free_coherent(info->device, fb->image_size,
-+                                        fb->cpuaddr, fb->dma_addr);
-+                      fb->image_size = 0;
-+                      fb->cpuaddr = NULL;
-+                      fb->dma_addr = 0;
-+              }
-+
-+              fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
-+                                               &fb->dma_addr, GFP_KERNEL);
-+
-+              if (!fb->cpuaddr) {
-+                      fb->dma_addr = 0;
-+                      fb->fbdev->disable_arm_alloc = true;
-+              } else {
-+                      fb->image_size = image_size;
-+              }
-+      }
-+
-+      if (fb->cpuaddr) {
-+              fbinfo.base = fb->dma_addr;
-+              fbinfo.screen_size = image_size;
-+              fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
-+
-+              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-+                                               sizeof(fbinfo));
-+              if (ret || fbinfo.base != fb->dma_addr) {
-+                      /* Firmware either failed, or assigned a different base
-+                       * address (ie it doesn't support being passed an FB
-+                       * allocation).
-+                       * Destroy the allocation, and don't try again.
-+                       */
-+                      dma_free_coherent(info->device, fb->image_size,
-+                                        fb->cpuaddr, fb->dma_addr);
-+                      fb->image_size = 0;
-+                      fb->cpuaddr = NULL;
-+                      fb->dma_addr = 0;
-+                      fb->fbdev->disable_arm_alloc = true;
-+              }
-+      } else {
-+              /* Our allocation failed - drop into the old scheme of
-+               * allocation by the VPU.
-+               */
-+              ret = -ENOMEM;
-+      }
--      ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
-       if (ret) {
--              dev_err(info->device,
--                      "Failed to allocate GPU framebuffer (%d)\n", ret);
--              return ret;
-+              /* Old scheme:
-+               * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
-+               * - GET_PITCH instead of SET_PITCH.
-+               */
-+              fbinfo.base = 0;
-+              fbinfo.screen_size = 0;
-+              fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
-+              fbinfo.pitch = 0;
-+
-+              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-+                                               sizeof(fbinfo));
-+              if (ret) {
-+                      dev_err(info->device,
-+                              "Failed to allocate GPU framebuffer (%d)\n",
-+                              ret);
-+                      return ret;
-+              }
-       }
-       if (info->var.bits_per_pixel <= 8)
-@@ -314,9 +481,17 @@ static int bcm2708_fb_set_par(struct fb_
-       fb->fb.fix.smem_start = fbinfo.base;
-       fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
-       fb->fb.screen_size = fbinfo.screen_size;
--      if (fb->fb.screen_base)
--              iounmap(fb->fb.screen_base);
--      fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
-+
-+      if (!fb->dma_addr) {
-+              if (fb->fb.screen_base)
-+                      iounmap(fb->fb.screen_base);
-+
-+              fb->fb.screen_base = ioremap_wc(fbinfo.base,
-+                                              fb->fb.screen_size);
-+      } else {
-+              fb->fb.screen_base = fb->cpuaddr;
-+      }
-+
-       if (!fb->fb.screen_base) {
-               /* the console may currently be locked */
-               console_trylock();
-@@ -374,7 +549,10 @@ static int bcm2708_fb_setcolreg(unsigned
-                       packet->length = regno + 1;
-                       memcpy(packet->cmap, fb->gpu_cmap,
-                              sizeof(packet->cmap));
--                      ret = rpi_firmware_property(fb->fw,
-+
-+                      set_display_num(fb);
-+
-+                      ret = rpi_firmware_property(fb->fbdev->fw,
-                                                   RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
-                                                   packet,
-                                                   (2 + packet->length) * sizeof(u32));
-@@ -413,8 +591,11 @@ static int bcm2708_fb_blank(int blank_mo
-               return -EINVAL;
-       }
--      ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-+      set_display_num(fb);
-+
-+      ret = rpi_firmware_property(fb->fbdev->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-                                   &value, sizeof(value));
-+
-       if (ret)
-               dev_err(info->device, "%s(%d) failed: %d\n", __func__,
-                       blank_mode, ret);
-@@ -431,7 +612,7 @@ static int bcm2708_fb_pan_display(struct
-       info->var.yoffset = var->yoffset;
-       result = bcm2708_fb_set_par(info);
-       if (result != 0)
--              pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
-+              pr_err("%s(%u,%u) returns=%d\n", __func__, var->xoffset,
-                      var->yoffset, result);
-       return result;
- }
-@@ -439,8 +620,9 @@ static int bcm2708_fb_pan_display(struct
- static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src,
-                      int size)
- {
--      int burst_size = (fb->dma_chan == 0) ? 8 : 2;
--      struct bcm2708_dma_cb *cb = fb->cb_base;
-+      struct bcm2708_fb_dev *fbdev = fb->fbdev;
-+      struct bcm2708_dma_cb *cb = fbdev->cb_base;
-+      int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
-       cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
-                  BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
-@@ -453,21 +635,27 @@ static void dma_memcpy(struct bcm2708_fb
-       cb->pad[1] = 0;
-       cb->next = 0;
-+      // Not sure what to do if this gets a signal whilst waiting
-+      if (mutex_lock_interruptible(&fbdev->dma_mutex))
-+              return;
-+
-       if (size < dma_busy_wait_threshold) {
--              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
--              bcm_dma_wait_idle(fb->dma_chan_base);
-+              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+              bcm_dma_wait_idle(fbdev->dma_chan_base);
-       } else {
--              void __iomem *dma_chan = fb->dma_chan_base;
-+              void __iomem *local_dma_chan = fbdev->dma_chan_base;
-               cb->info |= BCM2708_DMA_INT_EN;
--              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
--              while (bcm_dma_is_busy(dma_chan)) {
--                      wait_event_interruptible(fb->dma_waitq,
--                                               !bcm_dma_is_busy(dma_chan));
-+              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+              while (bcm_dma_is_busy(local_dma_chan)) {
-+                      wait_event_interruptible(fbdev->dma_waitq,
-+                                               !bcm_dma_is_busy(local_dma_chan));
-               }
--              fb->stats.dma_irqs++;
-+              fbdev->dma_stats.dma_irqs++;
-       }
--      fb->stats.dma_copies++;
-+      fbdev->dma_stats.dma_copies++;
-+
-+      mutex_unlock(&fbdev->dma_mutex);
- }
- /* address with no aliases */
-@@ -542,10 +730,13 @@ static int bcm2708_ioctl(struct fb_info
-       switch (cmd) {
-       case FBIO_WAITFORVSYNC:
--              ret = rpi_firmware_property(fb->fw,
-+              set_display_num(fb);
-+
-+              ret = rpi_firmware_property(fb->fbdev->fw,
-                                           RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC,
-                                           &dummy, sizeof(dummy));
-               break;
-+
-       case FBIODMACOPY:
-       {
-               struct fb_dmacopy ioparam;
-@@ -615,23 +806,22 @@ static int bcm2708_compat_ioctl(struct f
- static void bcm2708_fb_fillrect(struct fb_info *info,
-                               const struct fb_fillrect *rect)
- {
--      /* (is called) print_debug("bcm2708_fb_fillrect\n"); */
-       cfb_fillrect(info, rect);
- }
- /* A helper function for configuring dma control block */
- static void set_dma_cb(struct bcm2708_dma_cb *cb,
--                     int        burst_size,
--                     dma_addr_t dst,
--                     int        dst_stride,
--                     dma_addr_t src,
--                     int        src_stride,
--                     int        w,
--                     int        h)
-+              int        burst_size,
-+              dma_addr_t dst,
-+              int        dst_stride,
-+              dma_addr_t src,
-+              int        src_stride,
-+              int        w,
-+              int        h)
- {
-       cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
--                 BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
--                 BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
-+              BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
-+              BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
-       cb->dst = dst;
-       cb->src = src;
-       /*
-@@ -649,15 +839,19 @@ static void bcm2708_fb_copyarea(struct f
-                               const struct fb_copyarea *region)
- {
-       struct bcm2708_fb *fb = to_bcm2708(info);
--      struct bcm2708_dma_cb *cb = fb->cb_base;
-+      struct bcm2708_fb_dev *fbdev = fb->fbdev;
-+      struct bcm2708_dma_cb *cb = fbdev->cb_base;
-       int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
-       /* Channel 0 supports larger bursts and is a bit faster */
--      int burst_size = (fb->dma_chan == 0) ? 8 : 2;
-+      int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
-       int pixels = region->width * region->height;
--      /* Fallback to cfb_copyarea() if we don't like something */
--      if (bytes_per_pixel > 4 ||
-+      /* If DMA is currently in use (ie being used on another FB), then
-+       * rather than wait for it to finish, just use the cfb_copyarea
-+       */
-+      if (!mutex_trylock(&fbdev->dma_mutex) ||
-+          bytes_per_pixel > 4 ||
-           info->var.xres * info->var.yres > 1920 * 1200 ||
-           region->width <= 0 || region->width > info->var.xres ||
-           region->height <= 0 || region->height > info->var.yres ||
-@@ -684,8 +878,8 @@ static void bcm2708_fb_copyarea(struct f
-                * 1920x1200 resolution at 32bpp pixel depth.
-                */
-               int y;
--              dma_addr_t control_block_pa = fb->cb_handle;
--              dma_addr_t scratchbuf = fb->cb_handle + 16 * 1024;
-+              dma_addr_t control_block_pa = fbdev->cb_handle;
-+              dma_addr_t scratchbuf = fbdev->cb_handle + 16 * 1024;
-               int scanline_size = bytes_per_pixel * region->width;
-               int scanlines_per_cb = (64 * 1024 - 16 * 1024) / scanline_size;
-@@ -735,10 +929,10 @@ static void bcm2708_fb_copyarea(struct f
-               }
-               set_dma_cb(cb, burst_size,
-                          fb->fb_bus_address + dy * fb->fb.fix.line_length +
--                                                 bytes_per_pixel * region->dx,
-+                         bytes_per_pixel * region->dx,
-                          stride,
-                          fb->fb_bus_address + sy * fb->fb.fix.line_length +
--                                                 bytes_per_pixel * region->sx,
-+                         bytes_per_pixel * region->sx,
-                          stride,
-                          region->width * bytes_per_pixel,
-                          region->height);
-@@ -748,32 +942,33 @@ static void bcm2708_fb_copyarea(struct f
-       cb->next = 0;
-       if (pixels < dma_busy_wait_threshold) {
--              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
--              bcm_dma_wait_idle(fb->dma_chan_base);
-+              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+              bcm_dma_wait_idle(fbdev->dma_chan_base);
-       } else {
--              void __iomem *dma_chan = fb->dma_chan_base;
-+              void __iomem *local_dma_chan = fbdev->dma_chan_base;
-               cb->info |= BCM2708_DMA_INT_EN;
--              bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
--              while (bcm_dma_is_busy(dma_chan)) {
--                      wait_event_interruptible(fb->dma_waitq,
--                                               !bcm_dma_is_busy(dma_chan));
-+              bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+              while (bcm_dma_is_busy(local_dma_chan)) {
-+                      wait_event_interruptible(fbdev->dma_waitq,
-+                                               !bcm_dma_is_busy(local_dma_chan));
-               }
--              fb->stats.dma_irqs++;
-+              fbdev->dma_stats.dma_irqs++;
-       }
--      fb->stats.dma_copies++;
-+      fbdev->dma_stats.dma_copies++;
-+
-+      mutex_unlock(&fbdev->dma_mutex);
- }
- static void bcm2708_fb_imageblit(struct fb_info *info,
-                                const struct fb_image *image)
- {
--      /* (is called) print_debug("bcm2708_fb_imageblit\n"); */
-       cfb_imageblit(info, image);
- }
- static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt)
- {
--      struct bcm2708_fb *fb = cxt;
-+      struct bcm2708_fb_dev *fbdev = cxt;
-       /* FIXME: should read status register to check if this is
-        * actually interrupting us or not, in case this interrupt
-@@ -783,9 +978,9 @@ static irqreturn_t bcm2708_fb_dma_irq(in
-        */
-       /* acknowledge the interrupt */
--      writel(BCM2708_DMA_INT, fb->dma_chan_base + BCM2708_DMA_CS);
-+      writel(BCM2708_DMA_INT, fbdev->dma_chan_base + BCM2708_DMA_CS);
--      wake_up(&fb->dma_waitq);
-+      wake_up(&fbdev->dma_waitq);
-       return IRQ_HANDLED;
- }
-@@ -821,11 +1016,23 @@ static int bcm2708_fb_register(struct bc
-       fb->fb.fix.ywrapstep = 0;
-       fb->fb.fix.accel = FB_ACCEL_NONE;
--      fb->fb.var.xres = fbwidth;
--      fb->fb.var.yres = fbheight;
--      fb->fb.var.xres_virtual = fbwidth;
--      fb->fb.var.yres_virtual = fbheight;
--      fb->fb.var.bits_per_pixel = fbdepth;
-+      /* If we have data from the VC4 on FB's, use that, otherwise use the
-+       * module parameters
-+       */
-+      if (fb->display_settings.width) {
-+              fb->fb.var.xres = fb->display_settings.width;
-+              fb->fb.var.yres = fb->display_settings.height;
-+              fb->fb.var.xres_virtual = fb->fb.var.xres;
-+              fb->fb.var.yres_virtual = fb->fb.var.yres;
-+              fb->fb.var.bits_per_pixel = fb->display_settings.depth;
-+      } else {
-+              fb->fb.var.xres = fbwidth;
-+              fb->fb.var.yres = fbheight;
-+              fb->fb.var.xres_virtual = fbwidth;
-+              fb->fb.var.yres_virtual = fbheight;
-+              fb->fb.var.bits_per_pixel = fbdepth;
-+      }
-+
-       fb->fb.var.vmode = FB_VMODE_NONINTERLACED;
-       fb->fb.var.activate = FB_ACTIVATE_NOW;
-       fb->fb.var.nonstd = 0;
-@@ -841,26 +1048,23 @@ static int bcm2708_fb_register(struct bc
-       fb->fb.monspecs.dclkmax = 100000000;
-       bcm2708_fb_set_bitfields(&fb->fb.var);
--      init_waitqueue_head(&fb->dma_waitq);
-       /*
-        * Allocate colourmap.
-        */
--
-       fb_set_var(&fb->fb, &fb->fb.var);
-+
-       ret = bcm2708_fb_set_par(&fb->fb);
-+
-       if (ret)
-               return ret;
--      print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
--                  fbwidth, fbheight, fbdepth, fbswap);
--
-       ret = register_framebuffer(&fb->fb);
--      print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
-+
-       if (ret == 0)
-               goto out;
--      print_debug("BCM2708FB: cannot register framebuffer (%d)\n", ret);
-+      dev_warn(fb->fb.dev, "Unable to register framebuffer (%d)\n", ret);
- out:
-       return ret;
- }
-@@ -869,10 +1073,18 @@ static int bcm2708_fb_probe(struct platf
- {
-       struct device_node *fw_np;
-       struct rpi_firmware *fw;
--      struct bcm2708_fb *fb;
--      int ret;
-+      int ret, i;
-+      u32 num_displays;
-+      struct bcm2708_fb_dev *fbdev;
-+      struct { u32 base, length; } gpu_mem;
-+
-+      fbdev = devm_kzalloc(&dev->dev, sizeof(*fbdev), GFP_KERNEL);
-+
-+      if (!fbdev)
-+              return -ENOMEM;
-       fw_np = of_parse_phandle(dev->dev.of_node, "firmware", 0);
-+
- /* Remove comment when booting without Device Tree is no longer supported
-  *    if (!fw_np) {
-  *            dev_err(&dev->dev, "Missing firmware node\n");
-@@ -880,90 +1092,154 @@ static int bcm2708_fb_probe(struct platf
-  *    }
-  */
-       fw = rpi_firmware_get(fw_np);
-+      fbdev->fw = fw;
-+
-       if (!fw)
-               return -EPROBE_DEFER;
--      fb = kzalloc(sizeof(*fb), GFP_KERNEL);
--      if (!fb) {
--              ret = -ENOMEM;
--              goto free_region;
-+      ret = rpi_firmware_property(fw,
-+                                  RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
-+                                  &num_displays, sizeof(u32));
-+
-+      /* If we fail to get the number of displays, or it returns 0, then
-+       * assume old firmware that doesn't have the mailbox call, so just
-+       * set one display
-+       */
-+      if (ret || num_displays == 0) {
-+              num_displays = 1;
-+              dev_err(&dev->dev,
-+                      "Unable to determine number of FB's. Assuming 1\n");
-+              ret = 0;
-+      } else {
-+              fbdev->firmware_supports_multifb = 1;
-       }
--      fb->fw = fw;
--      bcm2708_fb_debugfs_init(fb);
-+      if (num_displays > MAX_FRAMEBUFFERS) {
-+              dev_warn(&dev->dev,
-+                       "More displays reported from firmware than supported in driver (%u vs %u)",
-+                       num_displays, MAX_FRAMEBUFFERS);
-+              num_displays = MAX_FRAMEBUFFERS;
-+      }
--      fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
--                                           &fb->cb_handle, GFP_KERNEL);
--      if (!fb->cb_base) {
-+      dev_info(&dev->dev, "FB found %d display(s)\n", num_displays);
-+
-+      /* Set up the DMA information. Note we have just one set of DMA
-+       * parameters to work with all the FB's so requires synchronising when
-+       * being used
-+       */
-+
-+      mutex_init(&fbdev->dma_mutex);
-+
-+      fbdev->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
-+                                              &fbdev->cb_handle,
-+                                              GFP_KERNEL);
-+      if (!fbdev->cb_base) {
-               dev_err(&dev->dev, "cannot allocate DMA CBs\n");
-               ret = -ENOMEM;
-               goto free_fb;
-       }
--      pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
--
-       ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
--                               &fb->dma_chan_base, &fb->dma_irq);
-+                               &fbdev->dma_chan_base,
-+                               &fbdev->dma_irq);
-       if (ret < 0) {
--              dev_err(&dev->dev, "couldn't allocate a DMA channel\n");
-+              dev_err(&dev->dev, "Couldn't allocate a DMA channel\n");
-               goto free_cb;
-       }
--      fb->dma_chan = ret;
-+      fbdev->dma_chan = ret;
--      ret = request_irq(fb->dma_irq, bcm2708_fb_dma_irq,
--                        0, "bcm2708_fb dma", fb);
-+      ret = request_irq(fbdev->dma_irq, bcm2708_fb_dma_irq,
-+                        0, "bcm2708_fb DMA", fbdev);
-       if (ret) {
--              pr_err("%s: failed to request DMA irq\n", __func__);
-+              dev_err(&dev->dev,
-+                      "Failed to request DMA irq\n");
-               goto free_dma_chan;
-       }
--      pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
-+      rpi_firmware_property(fbdev->fw,
-+                            RPI_FIRMWARE_GET_VC_MEMORY,
-+                            &gpu_mem, sizeof(gpu_mem));
-+
-+      for (i = 0; i < num_displays; i++) {
-+              struct bcm2708_fb *fb = &fbdev->displays[i];
-+
-+              fb->display_settings.display_num = i;
-+              fb->dev = dev;
-+              fb->fb.device = &dev->dev;
-+              fb->fbdev = fbdev;
-+
-+              fb->gpu.base = gpu_mem.base;
-+              fb->gpu.length = gpu_mem.length;
-+
-+              if (fbdev->firmware_supports_multifb) {
-+                      ret = rpi_firmware_property(fw,
-+                                                  RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS,
-+                                                  &fb->display_settings,
-+                                                  GET_DISPLAY_SETTINGS_PAYLOAD_SIZE);
-+              } else {
-+                      memset(&fb->display_settings, 0,
-+                             sizeof(fb->display_settings));
-+              }
-+
-+              ret = bcm2708_fb_register(fb);
--      fb->dev = dev;
--      fb->fb.device = &dev->dev;
-+              if (ret == 0) {
-+                      bcm2708_fb_debugfs_init(fb);
--      /* failure here isn't fatal, but we'll fail in vc_mem_copy if
--       * fb->gpu is not valid
--       */
--      rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
--                            sizeof(fb->gpu));
-+                      fbdev->num_displays++;
--      ret = bcm2708_fb_register(fb);
--      if (ret == 0) {
--              platform_set_drvdata(dev, fb);
--              goto out;
-+                      dev_info(&dev->dev,
-+                               "Registered framebuffer for display %u, size %ux%u\n",
-+                               fb->display_settings.display_num,
-+                               fb->fb.var.xres,
-+                               fb->fb.var.yres);
-+              } else {
-+                      // Use this to flag if this FB entry is in use.
-+                      fb->fbdev = NULL;
-+              }
-+      }
-+
-+      // Did we actually successfully create any FB's?
-+      if (fbdev->num_displays) {
-+              init_waitqueue_head(&fbdev->dma_waitq);
-+              platform_set_drvdata(dev, fbdev);
-+              return ret;
-       }
- free_dma_chan:
--      bcm_dma_chan_free(fb->dma_chan);
-+      bcm_dma_chan_free(fbdev->dma_chan);
- free_cb:
--      dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
-+      dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
-+                            fbdev->cb_handle);
- free_fb:
--      kfree(fb);
--free_region:
-       dev_err(&dev->dev, "probe failed, err %d\n", ret);
--out:
-+
-       return ret;
- }
- static int bcm2708_fb_remove(struct platform_device *dev)
- {
--      struct bcm2708_fb *fb = platform_get_drvdata(dev);
-+      struct bcm2708_fb_dev *fbdev = platform_get_drvdata(dev);
-+      int i;
-       platform_set_drvdata(dev, NULL);
--      if (fb->fb.screen_base)
--              iounmap(fb->fb.screen_base);
--      unregister_framebuffer(&fb->fb);
--
--      dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
--      bcm_dma_chan_free(fb->dma_chan);
--
--      bcm2708_fb_debugfs_deinit(fb);
-+      for (i = 0; i < fbdev->num_displays; i++) {
-+              if (fbdev->displays[i].fb.screen_base)
-+                      iounmap(fbdev->displays[i].fb.screen_base);
-+
-+              if (fbdev->displays[i].fbdev) {
-+                      unregister_framebuffer(&fbdev->displays[i].fb);
-+                      bcm2708_fb_debugfs_deinit(&fbdev->displays[i]);
-+              }
-+      }
--      free_irq(fb->dma_irq, fb);
-+      dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
-+                            fbdev->cb_handle);
-+      bcm_dma_chan_free(fbdev->dma_chan);
-+      free_irq(fbdev->dma_irq, fbdev);
--      kfree(fb);
-+      mutex_destroy(&fbdev->dma_mutex);
-       return 0;
- }
-@@ -978,10 +1254,10 @@ static struct platform_driver bcm2708_fb
-       .probe = bcm2708_fb_probe,
-       .remove = bcm2708_fb_remove,
-       .driver = {
--                 .name = DRIVER_NAME,
--                 .owner = THIS_MODULE,
--                 .of_match_table = bcm2708_fb_of_match_table,
--                 },
-+                .name = DRIVER_NAME,
-+                .owner = THIS_MODULE,
-+                .of_match_table = bcm2708_fb_of_match_table,
-+                },
- };
- static int __init bcm2708_fb_init(void)
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -138,9 +138,11 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH =                  0x00048005,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER =            0x00048006,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE =             0x00048007,
-+      RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH =                  0x00048008,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET =         0x00048009,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN =               0x0004800a,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE =                0x0004800b,
-+
-       RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF =               0x0004801f,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF =            0x00048020,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC =                  0x0004800e,
-@@ -159,6 +161,8 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
- };
-+#define GET_DISPLAY_SETTINGS_PAYLOAD_SIZE 64
-+
- #if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
- int rpi_firmware_property(struct rpi_firmware *fw,
-                         u32 tag, void *data, size_t len);
diff --git a/target/linux/brcm2708/patches-4.19/950-0558-ARM-dts-bcm283x-Move-BCM2835-6-7-specific-to-bcm2835.patch b/target/linux/brcm2708/patches-4.19/950-0558-ARM-dts-bcm283x-Move-BCM2835-6-7-specific-to-bcm2835.patch
deleted file mode 100644 (file)
index e3ee39a..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-From 545c00748a070340e9669740e45afc2672e1fcb6 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sun, 19 May 2019 12:26:21 +0200
-Subject: [PATCH] ARM: dts: bcm283x: Move BCM2835/6/7 specific to
- bcm2835-common.dtsi
-
-We want all common BCM2835/6/7/8 functions in bcm283x.dtsi and all
-BCM2835/6/7 specific in the new bcm2835-common.dtsi.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm2835-common.dtsi | 53 +++++++++++++++++++++++++++
- arch/arm/boot/dts/bcm2835.dtsi        |  1 +
- arch/arm/boot/dts/bcm2836.dtsi        |  1 +
- arch/arm/boot/dts/bcm2837.dtsi        |  1 +
- arch/arm/boot/dts/bcm283x.dtsi        | 43 +---------------------
- 5 files changed, 57 insertions(+), 42 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2835-common.dtsi
-
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2835-common.dtsi
-@@ -0,0 +1,53 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+/* This include file covers the common peripherals and configuration between
-+ * bcm2835, bcm2836 and bcm2837 implementations.
-+ */
-+
-+/ {
-+      soc {
-+              timer@7e003000 {
-+                      compatible = "brcm,bcm2835-system-timer";
-+                      reg = <0x7e003000 0x1000>;
-+                      interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
-+                      /* This could be a reference to BCM2835_CLOCK_TIMER,
-+                       * but we don't have the driver using the common clock
-+                       * support yet.
-+                       */
-+                      clock-frequency = <1000000>;
-+              };
-+
-+              intc: interrupt-controller@7e00b200 {
-+                      compatible = "brcm,bcm2835-armctrl-ic";
-+                      reg = <0x7e00b200 0x200>;
-+                      interrupt-controller;
-+                      #interrupt-cells = <2>;
-+              };
-+
-+              thermal: thermal@7e212000 {
-+                      compatible = "brcm,bcm2835-thermal";
-+                      reg = <0x7e212000 0x8>;
-+                      clocks = <&clocks BCM2835_CLOCK_TSENS>;
-+                      #thermal-sensor-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              v3d: v3d@7ec00000 {
-+                      compatible = "brcm,bcm2835-v3d";
-+                      reg = <0x7ec00000 0x1000>;
-+                      interrupts = <1 10>;
-+              };
-+      };
-+};
-+
-+&gpio {
-+      i2c_slave_gpio18: i2c_slave_gpio18 {
-+              brcm,pins = <18 19 20 21>;
-+              brcm,function = <BCM2835_FSEL_ALT3>;
-+      };
-+
-+      jtag_gpio4: jtag_gpio4 {
-+              brcm,pins = <4 5 6 12 13>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+};
---- a/arch/arm/boot/dts/bcm2835.dtsi
-+++ b/arch/arm/boot/dts/bcm2835.dtsi
-@@ -1,5 +1,6 @@
- // SPDX-License-Identifier: GPL-2.0
- #include "bcm283x.dtsi"
-+#include "bcm2835-common.dtsi"
- / {
-       compatible = "brcm,bcm2835";
---- a/arch/arm/boot/dts/bcm2836.dtsi
-+++ b/arch/arm/boot/dts/bcm2836.dtsi
-@@ -1,5 +1,6 @@
- // SPDX-License-Identifier: GPL-2.0
- #include "bcm283x.dtsi"
-+#include "bcm2835-common.dtsi"
- / {
-       compatible = "brcm,bcm2836";
---- a/arch/arm/boot/dts/bcm2837.dtsi
-+++ b/arch/arm/boot/dts/bcm2837.dtsi
-@@ -1,4 +1,5 @@
- #include "bcm283x.dtsi"
-+#include "bcm2835-common.dtsi"
- / {
-       compatible = "brcm,bcm2837";
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -55,17 +55,6 @@
-               #address-cells = <1>;
-               #size-cells = <1>;
--              timer@7e003000 {
--                      compatible = "brcm,bcm2835-system-timer";
--                      reg = <0x7e003000 0x1000>;
--                      interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
--                      /* This could be a reference to BCM2835_CLOCK_TIMER,
--                       * but we don't have the driver using the common clock
--                       * support yet.
--                       */
--                      clock-frequency = <1000000>;
--              };
--
-               txp@7e004000 {
-                       compatible = "brcm,bcm2835-txp";
-                       reg = <0x7e004000 0x20>;
-@@ -113,13 +102,6 @@
-                       brcm,dma-channel-mask = <0x7f35>;
-               };
--              intc: interrupt-controller@7e00b200 {
--                      compatible = "brcm,bcm2835-armctrl-ic";
--                      reg = <0x7e00b200 0x200>;
--                      interrupt-controller;
--                      #interrupt-cells = <2>;
--              };
--
-               watchdog@7e100000 {
-                       compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
-                       #power-domain-cells = <1>;
-@@ -183,8 +165,7 @@
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
--                      /* Defines pin muxing groups according to
--                       * BCM2835-ARM-Peripherals.pdf page 102.
-+                      /* Defines common pin muxing groups
-                        *
-                        * While each pin can have its mux selected
-                        * for various functions individually, some
-@@ -262,15 +243,7 @@
-                               brcm,pins = <44 45>;
-                               brcm,function = <BCM2835_FSEL_ALT2>;
-                       };
--                      i2c_slave_gpio18: i2c_slave_gpio18 {
--                              brcm,pins = <18 19 20 21>;
--                              brcm,function = <BCM2835_FSEL_ALT3>;
--                      };
--                      jtag_gpio4: jtag_gpio4 {
--                              brcm,pins = <4 5 6 12 13>;
--                              brcm,function = <BCM2835_FSEL_ALT5>;
--                      };
-                       jtag_gpio22: jtag_gpio22 {
-                               brcm,pins = <22 23 24 25 26 27>;
-                               brcm,function = <BCM2835_FSEL_ALT4>;
-@@ -487,14 +460,6 @@
-               };
--              thermal: thermal@7e212000 {
--                      compatible = "brcm,bcm2835-thermal";
--                      reg = <0x7e212000 0x8>;
--                      clocks = <&clocks BCM2835_CLOCK_TSENS>;
--                      #thermal-sensor-cells = <0>;
--                      status = "disabled";
--              };
--
-               aux: aux@7e215000 {
-                       compatible = "brcm,bcm2835-aux";
-                       #clock-cells = <1>;
-@@ -660,12 +625,6 @@
-                       phy-names = "usb2-phy";
-               };
--              v3d: v3d@7ec00000 {
--                      compatible = "brcm,bcm2835-v3d";
--                      reg = <0x7ec00000 0x1000>;
--                      interrupts = <1 10>;
--              };
--
-               vc4: gpu {
-                       compatible = "brcm,bcm2835-vc4";
-               };
diff --git a/target/linux/brcm2708/patches-4.19/950-0558-overlays-Add-i2c3-6-and-uart2-5-overlays.patch b/target/linux/brcm2708/patches-4.19/950-0558-overlays-Add-i2c3-6-and-uart2-5-overlays.patch
new file mode 100644 (file)
index 0000000..d1d8f72
--- /dev/null
@@ -0,0 +1,359 @@
+From 13be2bbd1a22f1b4d9fd260d80b561698f623ac1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 30 May 2019 16:44:24 +0100
+Subject: [PATCH] overlays: Add i2c3-6 and uart2-5 overlays
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile          |  8 +++
+ arch/arm/boot/dts/overlays/README            | 52 ++++++++++++++++++++
+ arch/arm/boot/dts/overlays/i2c3-overlay.dts  | 27 ++++++++++
+ arch/arm/boot/dts/overlays/i2c4-overlay.dts  | 27 ++++++++++
+ arch/arm/boot/dts/overlays/i2c5-overlay.dts  | 27 ++++++++++
+ arch/arm/boot/dts/overlays/i2c6-overlay.dts  | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart2-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart3-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart4-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart5-overlay.dts | 27 ++++++++++
+ 10 files changed, 276 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/i2c3-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c4-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c5-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c6-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart2-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart3-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart4-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart5-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -65,6 +65,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       i2c-sensor.dtbo \
+       i2c0-bcm2708.dtbo \
+       i2c1-bcm2708.dtbo \
++      i2c3.dtbo \
++      i2c4.dtbo \
++      i2c5.dtbo \
++      i2c6.dtbo \
+       i2s-gpio28-31.dtbo \
+       ilitek251x.dtbo \
+       iqaudio-codec.dtbo \
+@@ -149,6 +153,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       tpm-slb9670.dtbo \
+       uart0.dtbo \
+       uart1.dtbo \
++      uart2.dtbo \
++      uart3.dtbo \
++      uart4.dtbo \
++      uart5.dtbo \
+       udrc.dtbo \
+       upstream.dtbo \
+       vc4-fkms-v3d.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1137,6 +1137,34 @@ Params: sda1_pin                GPIO pin
+                                 "yes")
++Name:   i2c3
++Info:   Enable the i2c3 bus
++Load:   dtoverlay=i2c3,<param>
++Params: pins_2_3                Use GPIOs 2 and 3
++        pins_4_5                Use GPIOs 4 and 5 (default)
++
++
++Name:   i2c4
++Info:   Enable the i2c4 bus
++Load:   dtoverlay=i2c4,<param>
++Params: pins_6_7                Use GPIOs 6 and 7
++        pins_8_9                Use GPIOs 8 and 9 (default)
++
++
++Name:   i2c5
++Info:   Enable the i2c5 bus
++Load:   dtoverlay=i2c5,<param>
++Params: pins_10_11              Use GPIOs 10 and 11
++        pins_12_13              Use GPIOs 12 and 13 (default)
++
++
++Name:   i2c6
++Info:   Enable the i2c6 bus
++Load:   dtoverlay=i2c6,<param>
++Params: pins_0_1                Use GPIOs 0 and 1
++        pins_22_23              Use GPIOs 22 and 23 (default)
++
++
+ Name:   i2s-gpio28-31
+ Info:   move I2S function block to GPIO 28 to 31
+ Load:   dtoverlay=i2s-gpio28-31
+@@ -2199,6 +2227,30 @@ Params: txd1_pin                GPIO pin
+         rxd1_pin                GPIO pin for RXD1 (15, 33 or 41 - default 15)
++Name:   uart2
++Info:   Enable uart 2 on GPIOs 0-3
++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
++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
++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
++Load:   dtoverlay=uart5,<param>
++Params: ctsrts                  Enable CTS/RTS on GPIOs 14-15 (default off)
++
++
+ Name:   udrc
+ Info:   Configures the NW Digital Radio UDRC Hat
+ Load:   dtoverlay=udrc,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&i2c3>;
++              __overlay__ {
++                      status = "okay";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c3_pins>;
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c3_pins>;
++              __dormant__ {
++                      brcm,pins = <2 3>;
++              };
++      };
++
++      __overrides__ {
++              pins_2_3 = <0>,"=1";
++              pins_4_5 = <0>,"!1";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&i2c4>;
++              __overlay__ {
++                      status = "okay";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c4_pins>;
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c4_pins>;
++              __dormant__ {
++                      brcm,pins = <6 7>;
++              };
++      };
++
++      __overrides__ {
++              pins_6_7 = <0>,"=1";
++              pins_8_9 = <0>,"!1";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&i2c5>;
++              __overlay__ {
++                      status = "okay";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c5_pins>;
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c5_pins>;
++              __dormant__ {
++                      brcm,pins = <10 11>;
++              };
++      };
++
++      __overrides__ {
++              pins_10_11 = <0>,"=1";
++              pins_12_13 = <0>,"!1";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&i2c6>;
++              __overlay__ {
++                      status = "okay";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c6_pins>;
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c6_pins>;
++              __dormant__ {
++                      brcm,pins = <0 1>;
++              };
++      };
++
++      __overrides__ {
++              pins_0_1 = <0>,"=1";
++              pins_22_23 = <0>,"!1";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart2-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&uart2>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&uart2_pins>;
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&uart2_pins>;
++              __dormant__ {
++                      brcm,pins = <0 1 2 3>;
++                      brcm,pull = <0 2 2 0>;
++              };
++      };
++
++      __overrides__ {
++              ctsrts = <0>,"=1";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart3-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&uart3>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&uart3_pins>;
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&uart3_pins>;
++              __dormant__ {
++                      brcm,pins = <4 5 6 7>;
++                      brcm,pull = <0 2 2 0>;
++              };
++      };
++
++      __overrides__ {
++              ctsrts = <0>,"=1";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart4-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&uart4>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&uart4_pins>;
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&uart4_pins>;
++              __dormant__ {
++                      brcm,pins = <8 9 10 11>;
++                      brcm,pull = <0 2 2 0>;
++              };
++      };
++
++      __overrides__ {
++              ctsrts = <0>,"=1";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart5-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&uart5>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&uart5_pins>;
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&uart5_pins>;
++              __dormant__ {
++                      brcm,pins = <12 13 14 15>;
++                      brcm,pull = <0 2 2 0>;
++              };
++      };
++
++      __overrides__ {
++              ctsrts = <0>,"=1";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0559-ARM-dts-Add-bcm2711-rpi-4-b.dts-and-components.patch b/target/linux/brcm2708/patches-4.19/950-0559-ARM-dts-Add-bcm2711-rpi-4-b.dts-and-components.patch
deleted file mode 100644 (file)
index 16980a8..0000000
+++ /dev/null
@@ -1,1129 +0,0 @@
-From ff78cbcd8d7d656a5f43abd2c744e610b8c6c740 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 May 2019 13:54:21 +0100
-Subject: [PATCH] ARM: dts: Add bcm2711-rpi-4-b.dts and components
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile            |   1 +
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 320 ++++++++++++
- arch/arm/boot/dts/bcm2711.dtsi        |  50 ++
- arch/arm/boot/dts/bcm2838.dtsi        | 724 ++++++++++++++++++++++++++
- 4 files changed, 1095 insertions(+)
- create mode 100644 arch/arm/boot/dts/bcm2711-rpi-4-b.dts
- create mode 100644 arch/arm/boot/dts/bcm2711.dtsi
- create mode 100644 arch/arm/boot/dts/bcm2838.dtsi
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
-       bcm2708-rpi-zero-w.dtb \
-       bcm2709-rpi-2-b.dtb \
-       bcm2710-rpi-3-b.dtb \
-+      bcm2711-rpi-4-b.dtb \
-       bcm2710-rpi-3-b-plus.dtb \
-       bcm2710-rpi-cm3.dtb
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -0,0 +1,320 @@
-+/dts-v1/;
-+
-+#include "bcm2711.dtsi"
-+
-+/ {
-+      compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
-+      model = "Raspberry Pi 4 Model B";
-+      #address-cells = <2>;
-+      #size-cells = <1>;
-+
-+      memory {
-+              device_type = "memory";
-+              reg = <0x0 0x0 0x0>;
-+      };
-+
-+      chosen {
-+              bootargs = "8250.nr_uarts=1 cma=64M";
-+      };
-+
-+      aliases {
-+              serial0 = &uart1;
-+              serial1 = &uart0;
-+              mmc0 = &emmc2;
-+              mmc1 = &mmcnr;
-+              mmc2 = &sdhost;
-+              /delete-property/ ethernet;
-+              /delete-property/ intc;
-+              ethernet0 = &genet;
-+      };
-+};
-+
-+&soc {
-+      virtgpio: virtgpio {
-+              compatible = "brcm,bcm2835-virtgpio";
-+              gpio-controller;
-+              #gpio-cells = <2>;
-+              firmware = <&firmware>;
-+              status = "okay";
-+      };
-+};
-+
-+&mmcnr {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdio_pins>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
-+&firmware {
-+      expgpio: expgpio {
-+              compatible = "raspberrypi,firmware-gpio";
-+              gpio-controller;
-+              #gpio-cells = <2>;
-+              status = "okay";
-+      };
-+};
-+
-+&uart0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart0_pins &bt_pins>;
-+      status = "okay";
-+};
-+
-+&uart1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart1_pins>;
-+      status = "okay";
-+};
-+
-+&spi0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
-+      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
-+
-+      spidev0: spidev@0{
-+              compatible = "spidev";
-+              reg = <0>;      /* CE0 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+
-+      spidev1: spidev@1{
-+              compatible = "spidev";
-+              reg = <1>;      /* CE1 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+};
-+
-+// =============================================
-+// Board specific stuff here
-+
-+/ {
-+
-+      sd_io_1v8_reg: sd_io_1v8_reg {
-+              status = "okay";
-+              compatible = "regulator-gpio";
-+              vin-supply = <&vdd_5v0_reg>;
-+              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>;
-+      };
-+};
-+
-+&sdhost {
-+      status = "disabled";
-+};
-+
-+&emmc2 {
-+      status = "okay";
-+      broken-cd;
-+      vqmmc-supply = <&sd_io_1v8_reg>;
-+};
-+
-+&leds {
-+      act_led: act {
-+              label = "led0";
-+              linux,default-trigger = "mmc0";
-+              gpios = <&gpio 42 0>;
-+      };
-+
-+      pwr_led: pwr {
-+              label = "led1";
-+              linux,default-trigger = "input";
-+              gpios = <&expgpio 2 0>;
-+      };
-+};
-+
-+&audio {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&audio_pins>;
-+};
-+
-+&sdhost_gpio48 {
-+      brcm,pins = <22 23 24 25 26 27>;
-+      brcm,function = <BCM2835_FSEL_ALT0>;
-+};
-+
-+&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>;
-+      };
-+
-+      i2c1_pins: i2c1 {
-+              brcm,pins = <2 3>;
-+              brcm,function = <BCM2835_FSEL_ALT0>;
-+      };
-+
-+      i2c3_pins: i2c3 {
-+              brcm,pins = <4 5>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+
-+      i2c4_pins: i2c4 {
-+              brcm,pins = <8 9>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+
-+      i2c5_pins: i2c5 {
-+              brcm,pins = <12 13>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+
-+      i2c6_pins: i2c6 {
-+              brcm,pins = <22 23>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+
-+      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>;
-+      };
-+
-+      audio_pins: audio_pins {
-+              brcm,pins = <40 41>;
-+              brcm,function = <4>;
-+      };
-+};
-+
-+&i2c0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c0_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c1_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c2 {
-+      clock-frequency = <100000>;
-+};
-+
-+&i2s {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2s_pins>;
-+};
-+
-+/ {
-+      __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";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2711.dtsi
-@@ -0,0 +1,50 @@
-+#include "bcm2838.dtsi"
-+#include "bcm270x.dtsi"
-+#include "bcm2708-rpi.dtsi"
-+
-+/ {
-+      soc {
-+              /delete-node/ mailbox@7e00b840;
-+              /delete-node/ v3d@7ec00000;
-+      };
-+
-+      __overrides__ {
-+              arm_freq;
-+      };
-+};
-+
-+&dma {
-+      brcm,dma-channel-mask = <0x7ef5>;
-+};
-+
-+&txp {
-+      interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&firmwarekms {
-+      interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&smi {
-+      interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&mmc {
-+      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&mmcnr {
-+      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&usb {
-+      reg = <0x7e980000 0x10000>,
-+            <0x7e00b200 0x200>;
-+      interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
-+                   <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&gpio {
-+      interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
-+                   <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -0,0 +1,724 @@
-+// SPDX-License-Identifier: GPL-2.0
-+#include "bcm283x.dtsi"
-+
-+#include <dt-bindings/interrupt-controller/arm-gic.h>
-+#include <dt-bindings/soc/bcm2835-pm.h>
-+
-+/ {
-+      compatible = "brcm,bcm2838", "brcm,bcm2837";
-+
-+      interrupt-parent = <&gicv2>;
-+
-+      soc {
-+              ranges = <0x7e000000  0x0 0xfe000000  0x01800000>,
-+                       <0x7c000000  0x0 0xfc000000  0x02000000>,
-+                       <0x40000000  0x0 0xff800000  0x00800000>;
-+              /* Emulate a contiguous 30-bit address range for DMA */
-+              dma-ranges = <0xc0000000  0x0 0x00000000  0x3c000000>;
-+
-+              /delete-node/ mailbox@7e00b840;
-+              /delete-node/ interrupt-controller@7e00f300;
-+
-+              local_intc: local_intc@40000000 {
-+                      compatible = "brcm,bcm2836-l1-intc";
-+                      reg = <0x40000000 0x100>;
-+              };
-+
-+              gicv2: gic400@40041000 {
-+                      interrupt-controller;
-+                      #interrupt-cells = <3>;
-+                      compatible = "arm,gic-400";
-+                      reg =   <0x40041000 0x1000>,
-+                              <0x40042000 0x2000>,
-+                              <0x40046000 0x2000>,
-+                              <0x40048000 0x2000>;
-+              };
-+
-+              thermal: thermal@7d5d2200 {
-+                      compatible = "brcm,avs-tmon-bcm2838";
-+                      reg = <0x7d5d2200 0x2c>;
-+                      interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
-+                      interrupt-names = "tmon";
-+                      clocks = <&clocks BCM2835_CLOCK_TSENS>;
-+                      #thermal-sensor-cells = <0>;
-+                      status = "okay";
-+              };
-+
-+              pm: watchdog@7e100000 {
-+                      reg = <0x7e100000 0x114>,
-+                            <0x7e00a000 0x24>,
-+                            <0x7ec11000 0x20>;
-+              };
-+
-+              rng@7e104000 {
-+                      interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              uart2: serial@7e201400 {
-+                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+                      reg = <0x7e201400 0x200>;
-+                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_UART>,
-+                               <&clocks BCM2835_CLOCK_VPU>;
-+                      clock-names = "uartclk", "apb_pclk";
-+                      arm,primecell-periphid = <0x00241011>;
-+                      status = "disabled";
-+              };
-+
-+              uart3: serial@7e201600 {
-+                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+                      reg = <0x7e201600 0x200>;
-+                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_UART>,
-+                               <&clocks BCM2835_CLOCK_VPU>;
-+                      clock-names = "uartclk", "apb_pclk";
-+                      arm,primecell-periphid = <0x00241011>;
-+                      status = "disabled";
-+              };
-+
-+              uart4: serial@7e201800 {
-+                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+                      reg = <0x7e201800 0x200>;
-+                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_UART>,
-+                               <&clocks BCM2835_CLOCK_VPU>;
-+                      clock-names = "uartclk", "apb_pclk";
-+                      arm,primecell-periphid = <0x00241011>;
-+                      status = "disabled";
-+              };
-+
-+              uart5: serial@7e201a00 {
-+                      compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+                      reg = <0x7e201a00 0x200>;
-+                      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_UART>,
-+                               <&clocks BCM2835_CLOCK_VPU>;
-+                      clock-names = "uartclk", "apb_pclk";
-+                      arm,primecell-periphid = <0x00241011>;
-+                      status = "disabled";
-+              };
-+
-+              spi@7e204000 {
-+                      reg = <0x7e204000 0x0200>;
-+                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              spi3: spi@7e204600 {
-+                      compatible = "brcm,bcm2835-spi";
-+                      reg = <0x7e204600 0x0200>;
-+                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              spi4: spi@7e204800 {
-+                      compatible = "brcm,bcm2835-spi";
-+                      reg = <0x7e204800 0x0200>;
-+                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              spi5: spi@7e204a00 {
-+                      compatible = "brcm,bcm2835-spi";
-+                      reg = <0x7e204a00 0x0200>;
-+                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              spi6: spi@7e204c00 {
-+                      compatible = "brcm,bcm2835-spi";
-+                      reg = <0x7e204c00 0x0200>;
-+                      interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              i2c3: i2c@7e205600 {
-+                      compatible = "brcm,bcm2835-i2c";
-+                      reg = <0x7e205600 0x200>;
-+                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              i2c4: i2c@7e205800 {
-+                      compatible = "brcm,bcm2835-i2c";
-+                      reg = <0x7e205800 0x200>;
-+                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              i2c5: i2c@7e205a00 {
-+                      compatible = "brcm,bcm2835-i2c";
-+                      reg = <0x7e205a00 0x200>;
-+                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              i2c6: i2c@7e205c00 {
-+                      compatible = "brcm,bcm2835-i2c";
-+                      reg = <0x7e205c00 0x200>;
-+                      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              pixelvalve@7e206000 {
-+                      interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              pixelvalve@7e207000 {
-+                      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              emmc2: emmc2@7e340000 {
-+                      compatible = "brcm,bcm2711-emmc2";
-+                      status = "okay";
-+                      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+                      clocks = <&clocks BCM2838_CLOCK_EMMC2>;
-+                      reg = <0x7e340000 0x100>;
-+              };
-+
-+              hvs@7e400000 {
-+                      interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              pixelvalve@7e807000 {
-+                      interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+      };
-+
-+      arm-pmu {
-+              /*
-+               * N.B. the A72 PMU support only exists in arch/arm64, hence
-+               * the fallback to the A53 version.
-+               */
-+              compatible = "arm,cortex-a72-pmu", "arm,cortex-a53-pmu";
-+              interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
-+                      <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
-+                      <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
-+                      <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-+      };
-+
-+      timer {
-+              compatible = "arm,armv7-timer";
-+              interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
-+                                        IRQ_TYPE_LEVEL_LOW)>,
-+                           <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
-+                                        IRQ_TYPE_LEVEL_LOW)>,
-+                           <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
-+                                        IRQ_TYPE_LEVEL_LOW)>,
-+                           <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
-+                                        IRQ_TYPE_LEVEL_LOW)>;
-+              arm,cpu-registers-not-fw-configured;
-+              always-on;
-+      };
-+
-+      cpus: cpus {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
-+
-+              cpu0: cpu@0 {
-+                      device_type = "cpu";
-+                      compatible = "arm,cortex-a72";
-+                      reg = <0>;
-+                      enable-method = "spin-table";
-+                      cpu-release-addr = <0x0 0x000000d8>;
-+              };
-+
-+              cpu1: cpu@1 {
-+                      device_type = "cpu";
-+                      compatible = "arm,cortex-a72";
-+                      reg = <1>;
-+                      enable-method = "spin-table";
-+                      cpu-release-addr = <0x0 0x000000e0>;
-+              };
-+
-+              cpu2: cpu@2 {
-+                      device_type = "cpu";
-+                      compatible = "arm,cortex-a72";
-+                      reg = <2>;
-+                      enable-method = "spin-table";
-+                      cpu-release-addr = <0x0 0x000000e8>;
-+              };
-+
-+              cpu3: cpu@3 {
-+                      device_type = "cpu";
-+                      compatible = "arm,cortex-a72";
-+                      reg = <3>;
-+                      enable-method = "spin-table";
-+                      cpu-release-addr = <0x0 0x000000f0>;
-+              };
-+      };
-+
-+      v3dbus {
-+              compatible = "simple-bus";
-+              #address-cells = <1>;
-+              #size-cells = <1>;
-+              ranges = <0x7c500000  0x0 0xfc500000  0x03300000>,
-+                       <0x40000000  0x0 0xff800000  0x00800000>;
-+              dma-ranges = <0x00000000  0x0 0x00000000  0x3c000000>;
-+
-+              v3d: v3d@7ec04000 {
-+                      compatible = "brcm,2711-v3d";
-+                      reg =
-+                          <0x7ec00000 0x4000>,
-+                          <0x7ec04000 0x4000>;
-+                      reg-names = "hub", "core0";
-+
-+                      power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
-+                      resets = <&pm BCM2835_RESET_V3D>;
-+                      clocks = <&clocks BCM2835_CLOCK_V3D>;
-+                      interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      scb: scb {
-+              compatible = "simple-bus";
-+              #address-cells = <2>;
-+              #size-cells = <1>;
-+
-+              ranges = <0x0 0x7c000000  0x0 0xfc000000  0x03800000>,
-+                       <0x0 0x40000000  0x0 0xff800000  0x00800000>,
-+                       <0x6 0x00000000  0x6 0x00000000  0x40000000>,
-+                       <0x0 0x00000000  0x0 0x00000000  0xfc000000>;
-+              dma-ranges = <0x0 0x00000000  0x0 0x00000000  0xfc000000>;
-+
-+              pcie_0: pcie@7d500000 {
-+                      reg = <0x0 0x7d500000 0x9310>,
-+                            <0x0 0x7e00f300 0x20>;
-+                      msi-controller;
-+                      msi-parent = <&pcie_0>;
-+                      #address-cells = <3>;
-+                      #interrupt-cells = <1>;
-+                      #size-cells = <2>;
-+                      bus-range = <0x0 0x01>;
-+                      compatible = "brcm,bcm7211-pcie", "brcm,bcm7445-pcie",
-+                                   "brcm,pci-plat-dev";
-+                      max-link-speed = <2>;
-+                      tot-num-pcie = <1>;
-+                      linux,pci-domain = <0>;
-+                      interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
-+                                   <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
-+                      interrupt-names = "pcie", "msi";
-+                      interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-+                      interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143
-+                                              IRQ_TYPE_LEVEL_HIGH
-+                                       0 0 0 2 &gicv2 GIC_SPI 144
-+                                              IRQ_TYPE_LEVEL_HIGH
-+                                       0 0 0 3 &gicv2 GIC_SPI 145
-+                                              IRQ_TYPE_LEVEL_HIGH
-+                                       0 0 0 4 &gicv2 GIC_SPI 146
-+                                              IRQ_TYPE_LEVEL_HIGH>;
-+
-+                      /* Map outbound accesses from scb:0x6_00000000-03ffffff
-+                       * to pci:0x0_f8000000-fbffffff
-+                       */
-+                      ranges = <0x02000000 0x0 0xf8000000  0x6 0x00000000
-+                                0x0 0x04000000>;
-+                      /* Map inbound accesses from pci:0x0_00000000..ffffffff
-+                       * to scb:0x0_00000000-ffffffff
-+                       */
-+                      dma-ranges = <0x02000000 0x0 0x00000000  0x0 0x00000000
-+                                    0x1 0x00000000>;
-+                      status = "okay";
-+              };
-+
-+              genet: genet@7d580000 {
-+                      compatible = "brcm,genet-v5";
-+                      reg = <0x0 0x7d580000 0x10000>;
-+                      status = "okay";
-+                      #address-cells = <0x1>;
-+                      #size-cells = <0x1>;
-+                      interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
-+                                   <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
-+                      phy-handle = <&phy1>;
-+                      phy-mode = "rgmii";
-+                      mdio@e14 {
-+                              #address-cells = <0x0>;
-+                              #size-cells = <0x1>;
-+                              compatible = "brcm,genet-mdio-v5";
-+                              reg = <0xe14 0x8>;
-+                              reg-names = "mdio";
-+                              phy1: genet-phy@0 {
-+                                      compatible =
-+                                              "ethernet-phy-ieee802.3-c22";
-+                                      /* No interrupts - use PHY_POLL */
-+                                      max-speed = <1000>;
-+                                      reg = <0x1>;
-+                              };
-+                      };
-+              };
-+
-+              xhci: xhci@7e9c0000 {
-+                      compatible = "generic-xhci";
-+                      status = "disabled";
-+                      reg = <0x0 0x7e9c0000 0x100000>;
-+                      interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              vchiq: mailbox@7e00b840 {
-+                      compatible = "brcm,bcm2838-vchiq";
-+                      reg = <0 0x7e00b840 0x3c>;
-+                      interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              hevc-decoder@7eb00000 {
-+                      compatible = "raspberrypi,argon-hevc-decoder";
-+                      reg = <0x0 0x7eb00000 0x10000>;
-+                      status = "okay";
-+              };
-+
-+              argon-local-intc@7eb10000 {
-+                      compatible = "raspberrypi,argon-local-intc";
-+                      reg = <0x0 0x7eb10000 0x1000>;
-+                      status = "okay";
-+                      interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
-+              };
-+
-+              h264-decoder@7eb20000 {
-+                      compatible = "raspberrypi,argon-h264-decoder";
-+                      reg = <0x0 0x7eb20000 0x10000>;
-+                      status = "okay";
-+              };
-+
-+              vp9-decoder@7eb30000 {
-+                      compatible = "raspberrypi,argon-vp9-decoder";
-+                      reg = <0x0 0x7eb30000 0x10000>;
-+                      status = "okay";
-+              };
-+      };
-+};
-+
-+&clk_osc {
-+      clock-frequency = <54000000>;
-+};
-+
-+&clocks {
-+      compatible = "brcm,bcm2838-cprman";
-+};
-+
-+&cpu_thermal {
-+      coefficients = <(-487)  410040>;
-+};
-+
-+&dsi0 {
-+      interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&dsi1 {
-+      interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&gpio {
-+      gpclk0_gpio49: gpclk0_gpio49 {
-+              brcm,pins = <49>;
-+              brcm,function = <BCM2835_FSEL_ALT1>;
-+              brcm,pull = <BCM2835_PUD_OFF>;
-+      };
-+      gpclk1_gpio50: gpclk1_gpio50 {
-+              brcm,pins = <50>;
-+              brcm,function = <BCM2835_FSEL_ALT1>;
-+              brcm,pull = <BCM2835_PUD_OFF>;
-+      };
-+      gpclk2_gpio51: gpclk2_gpio51 {
-+              brcm,pins = <51>;
-+              brcm,function = <BCM2835_FSEL_ALT1>;
-+              brcm,pull = <BCM2835_PUD_OFF>;
-+      };
-+
-+      i2c0_gpio46: i2c0_gpio46 {
-+              brcm,pins = <46 47>;
-+              brcm,function = <BCM2835_FSEL_ALT0>;
-+      };
-+      i2c1_gpio46: i2c1_gpio46 {
-+              brcm,pins = <46 47>;
-+              brcm,function = <BCM2835_FSEL_ALT1>;
-+      };
-+      i2c3_gpio2: i2c3_gpio2 {
-+              brcm,pins = <2 3>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c3_gpio4: i2c3_gpio4 {
-+              brcm,pins = <4 5>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c4_gpio6: i2c4_gpio6 {
-+              brcm,pins = <6 7>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c4_gpio8: i2c4_gpio8 {
-+              brcm,pins = <8 9>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c5_gpio10: i2c5_gpio10 {
-+              brcm,pins = <10 11>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c5_gpio12: i2c5_gpio12 {
-+              brcm,pins = <12 13>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c6_gpio0: i2c6_gpio0 {
-+              brcm,pins = <0 1>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c6_gpio22: i2c6_gpio22 {
-+              brcm,pins = <22 23>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      i2c_slave_gpio8: i2c_slave_gpio8 {
-+              brcm,pins = <8 9 10 11>;
-+              brcm,function = <BCM2835_FSEL_ALT3>;
-+      };
-+
-+      jtag_gpio48: jtag_gpio48 {
-+              brcm,pins = <48 49 50 51 52 53>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+      };
-+
-+      mii_gpio28: mii_gpio28 {
-+              brcm,pins = <28 29 30 31>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+      };
-+      mii_gpio36: mii_gpio36 {
-+              brcm,pins = <36 37 38 39>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+
-+      pcm_gpio50: pcm_gpio50 {
-+              brcm,pins = <50 51 52 53>;
-+              brcm,function = <BCM2835_FSEL_ALT2>;
-+      };
-+
-+      pwm0_gpio52: pwm0_gpio52 {
-+              brcm,pins = <52>;
-+              brcm,function = <BCM2835_FSEL_ALT1>;
-+              brcm,pull = <BCM2835_PUD_OFF>;
-+      };
-+      pwm1_gpio53: pwm1_gpio53 {
-+              brcm,pins = <53>;
-+              brcm,function = <BCM2835_FSEL_ALT1>;
-+              brcm,pull = <BCM2835_PUD_OFF>;
-+      };
-+
-+      /* The following group consists of:
-+         *  RGMII_START_STOP
-+         *  RGMII_RX_OK
-+         */
-+      rgmii_gpio35: rgmii_gpio35 {
-+              brcm,pins = <35 36>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+      };
-+      rgmii_irq_gpio34: rgmii_irq_gpio34 {
-+              brcm,pins = <34>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      rgmii_irq_gpio39: rgmii_irq_gpio39 {
-+              brcm,pins = <39>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+      };
-+      rgmii_mdio_gpio28: rgmii_mdio_gpio28 {
-+              brcm,pins = <28 29>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      rgmii_mdio_gpio37: rgmii_mdio_gpio37 {
-+              brcm,pins = <37 38>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+      };
-+
-+      spi0_gpio46: spi0_gpio46 {
-+              brcm,pins = <46 47 48 49>;
-+              brcm,function = <BCM2835_FSEL_ALT2>;
-+      };
-+      spi2_gpio46: spi2_gpio46 {
-+              brcm,pins = <46 47 48 49 50>;
-+              brcm,function = <BCM2835_FSEL_ALT5>;
-+      };
-+      spi3_gpio0: spi3_gpio0 {
-+              brcm,pins = <0 1 2 3>;
-+              brcm,function = <BCM2835_FSEL_ALT3>;
-+      };
-+      spi4_gpio4: spi4_gpio4 {
-+              brcm,pins = <4 5 6 7>;
-+              brcm,function = <BCM2835_FSEL_ALT3>;
-+      };
-+      spi5_gpio12: spi5_gpio12 {
-+              brcm,pins = <12 13 14 15>;
-+              brcm,function = <BCM2835_FSEL_ALT3>;
-+      };
-+      spi6_gpio18: spi6_gpio18 {
-+              brcm,pins = <18 19 20 21>;
-+              brcm,function = <BCM2835_FSEL_ALT3>;
-+      };
-+
-+      uart2_gpio0: uart2_gpio0 {
-+              brcm,pins = <0 1>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+      };
-+      uart2_ctsrts_gpio2: uart2_ctsrts_gpio2 {
-+              brcm,pins = <2 3>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+      };
-+      uart3_gpio4: uart3_gpio4 {
-+              brcm,pins = <4 5>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+      };
-+      uart3_ctsrts_gpio6: uart3_ctsrts_gpio6 {
-+              brcm,pins = <6 7>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+      };
-+      uart4_gpio8: uart4_gpio8 {
-+              brcm,pins = <8 9>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+      };
-+      uart4_ctsrts_gpio10: uart4_ctsrts_gpio10 {
-+              brcm,pins = <10 11>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+      };
-+      uart5_gpio12: uart5_gpio12 {
-+              brcm,pins = <12 13>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+      };
-+      uart5_ctsrts_gpio14: uart5_ctsrts_gpio14 {
-+              brcm,pins = <14 15>;
-+              brcm,function = <BCM2835_FSEL_ALT4>;
-+              brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+      };
-+};
-+
-+&vec {
-+      interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&usb {
-+      interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&hdmi {
-+      interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
-+                   <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&uart1 {
-+      interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&spi1 {
-+      interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&spi2 {
-+      interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&csi0 {
-+      interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&csi1 {
-+      interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&sdhci {
-+      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&i2c0 {
-+      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&i2c1 {
-+      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&i2c2 {
-+      interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&gpio {
-+      interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
-+                   <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
-+                   <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
-+                   <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&mailbox {
-+      interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&rng {
-+      compatible = "brcm,bcm2838-rng200";
-+};
-+
-+&sdhost {
-+      interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&uart0 {
-+      interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&dma {
-+      interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
-+              <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
-+              <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
-+              <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
-+              <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
-+              <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
-+              <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
-+              <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  7 */
-+              <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  8 */
-+              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  9 */
-+              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
-+              /* DMA4 - 40 bit DMA engines */
-+              <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4    11 */
-+              <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4    12 */
-+              <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4    13 */
-+              <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4    14 */
-+      interrupt-names = "dma0",
-+                        "dma1",
-+                        "dma2",
-+                        "dma3",
-+                        "dma4",
-+                        "dma5",
-+                        "dma6",
-+                        "dma7",
-+                        "dma8",
-+                        "dma9",
-+                        "dma10",
-+                        "dma11",
-+                        "dma12",
-+                        "dma13",
-+                        "dma14";
-+      brcm,dma-channel-mask = <0x7ef5>;
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0559-spi-devicetree-add-overlays-for-spi-3-to-6.patch b/target/linux/brcm2708/patches-4.19/950-0559-spi-devicetree-add-overlays-for-spi-3-to-6.patch
new file mode 100644 (file)
index 0000000..27de73d
--- /dev/null
@@ -0,0 +1,581 @@
+From a4ea446a07d7ba010c3c32286a22dc89cffa1e54 Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Sun, 12 May 2019 16:17:08 +0000
+Subject: [PATCH] spi: devicetree: add overlays for spi 3 to 6
+
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   8 ++
+ arch/arm/boot/dts/overlays/README             | 104 ++++++++++++++++++
+ .../boot/dts/overlays/spi3-1cs-overlay.dts    |  44 ++++++++
+ .../boot/dts/overlays/spi3-2cs-overlay.dts    |  56 ++++++++++
+ .../boot/dts/overlays/spi4-1cs-overlay.dts    |  44 ++++++++
+ .../boot/dts/overlays/spi4-2cs-overlay.dts    |  56 ++++++++++
+ .../boot/dts/overlays/spi5-1cs-overlay.dts    |  44 ++++++++
+ .../boot/dts/overlays/spi5-2cs-overlay.dts    |  56 ++++++++++
+ .../boot/dts/overlays/spi6-1cs-overlay.dts    |  44 ++++++++
+ .../boot/dts/overlays/spi6-2cs-overlay.dts    |  56 ++++++++++
+ 10 files changed, 512 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -144,6 +144,14 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       spi2-1cs.dtbo \
+       spi2-2cs.dtbo \
+       spi2-3cs.dtbo \
++      spi3-1cs.dtbo \
++      spi3-2cs.dtbo \
++      spi4-1cs.dtbo \
++      spi4-2cs.dtbo \
++      spi5-1cs.dtbo \
++      spi5-2cs.dtbo \
++      spi6-1cs.dtbo \
++      spi6-2cs.dtbo \
+       ssd1306.dtbo \
+       superaudioboard.dtbo \
+       sx150x.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2085,6 +2085,110 @@ Params: cs0_pin                 GPIO pin
+                                 is 'okay' or enabled).
++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.
++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
++                                userspace device node /dev/spidev3.0 (default
++                                is 'on' or enabled).
++
++
++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.
++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).
++        cs0_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev3.0 (default
++                                is 'on' or enabled).
++        cs1_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev3.1 (default
++                                is 'on' or enabled).
++
++
++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.
++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
++                                userspace device node /dev/spidev4.0 (default
++                                is 'on' or enabled).
++
++
++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.
++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).
++        cs0_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev4.0 (default
++                                is 'on' or enabled).
++        cs1_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev4.1 (default
++                                is 'on' or enabled).
++
++
++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.
++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
++                                userspace device node /dev/spidev5.0 (default
++                                is 'on' or enabled).
++
++
++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.
++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).
++        cs0_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev5.0 (default
++                                is 'on' or enabled).
++        cs1_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev5.1 (default
++                                is 'on' or enabled).
++
++
++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.
++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
++                                userspace device node /dev/spidev6.0 (default
++                                is 'on' or enabled).
++
++
++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.
++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).
++        cs0_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev6.0 (default
++                                is 'on' or enabled).
++        cs1_spidev              Set to 'off' to prevent the creation of a
++                                userspace device node /dev/spidev6.1 (default
++                                is 'on' or enabled).
++
++
+ Name:   ssd1306
+ Info:   Overlay for activation of SSD1306 over I2C OLED display framebuffer.
+ Load:   dtoverlay=ssd1306,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi3_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <0>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi3>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
++                      cs-gpios = <&gpio 0 1>;
++                      status = "okay";
++
++                      spidev3_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs0_spidev = <&spidev3_0>,"status";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi3_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <0 24>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi3>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
++                      cs-gpios = <&gpio 0 1>, <&gpio 24 1>;
++                      status = "okay";
++
++                      spidev3_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++
++                      spidev3_1: spidev@1 {
++                              compatible = "spidev";
++                              reg = <1>;      /* CE1 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs1_pin  = <&frag0>,"brcm,pins:4",
++                         <&frag1>,"cs-gpios:16";
++              cs0_spidev = <&spidev3_0>,"status";
++              cs1_spidev = <&spidev3_1>,"status";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi4_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <4>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi4>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
++                      cs-gpios = <&gpio 4 1>;
++                      status = "okay";
++
++                      spidev4_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs0_spidev = <&spidev4_0>,"status";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi4_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <4 25>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi4>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
++                      cs-gpios = <&gpio 4 1>, <&gpio 25 1>;
++                      status = "okay";
++
++                      spidev4_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++
++                      spidev4_1: spidev@1 {
++                              compatible = "spidev";
++                              reg = <1>;      /* CE1 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs1_pin  = <&frag0>,"brcm,pins:4",
++                         <&frag1>,"cs-gpios:16";
++              cs0_spidev = <&spidev4_0>,"status";
++              cs1_spidev = <&spidev4_1>,"status";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi5_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <12>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi5>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
++                      cs-gpios = <&gpio 12 1>;
++                      status = "okay";
++
++                      spidev5_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs0_spidev = <&spidev5_0>,"status";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi5_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <12 26>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi5>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
++                      cs-gpios = <&gpio 12 1>, <&gpio 26 1>;
++                      status = "okay";
++
++                      spidev5_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++
++                      spidev5_1: spidev@1 {
++                              compatible = "spidev";
++                              reg = <1>;      /* CE1 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs1_pin  = <&frag0>,"brcm,pins:4",
++                         <&frag1>,"cs-gpios:16";
++              cs0_spidev = <&spidev5_0>,"status";
++              cs1_spidev = <&spidev5_1>,"status";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi6_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <18>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi6>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
++                      cs-gpios = <&gpio 18 1>;
++                      status = "okay";
++
++                      spidev6_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs0_spidev = <&spidev6_0>,"status";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2838";
++
++      fragment@0 {
++              target = <&spi6_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <18 27>;
++                      brcm,function = <1>; /* output */
++              };
++      };
++
++      fragment@1 {
++              target = <&spi6>;
++              frag1: __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
++                      cs-gpios = <&gpio 18 1>, <&gpio 27 1>;
++                      status = "okay";
++
++                      spidev6_0: spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;      /* CE0 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++
++                      spidev6_1: spidev@1 {
++                              compatible = "spidev";
++                              reg = <1>;      /* CE1 */
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs1_pin  = <&frag0>,"brcm,pins:4",
++                         <&frag1>,"cs-gpios:16";
++              cs0_spidev = <&spidev6_0>,"status";
++              cs1_spidev = <&spidev6_1>,"status";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0560-overlays-Add-i2c3-6-and-uart2-5-overlays.patch b/target/linux/brcm2708/patches-4.19/950-0560-overlays-Add-i2c3-6-and-uart2-5-overlays.patch
deleted file mode 100644 (file)
index d1d8f72..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-From 13be2bbd1a22f1b4d9fd260d80b561698f623ac1 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 30 May 2019 16:44:24 +0100
-Subject: [PATCH] overlays: Add i2c3-6 and uart2-5 overlays
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile          |  8 +++
- arch/arm/boot/dts/overlays/README            | 52 ++++++++++++++++++++
- arch/arm/boot/dts/overlays/i2c3-overlay.dts  | 27 ++++++++++
- arch/arm/boot/dts/overlays/i2c4-overlay.dts  | 27 ++++++++++
- arch/arm/boot/dts/overlays/i2c5-overlay.dts  | 27 ++++++++++
- arch/arm/boot/dts/overlays/i2c6-overlay.dts  | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart2-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart3-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart4-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart5-overlay.dts | 27 ++++++++++
- 10 files changed, 276 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/i2c3-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/i2c4-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/i2c5-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/i2c6-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart2-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart3-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart4-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart5-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -65,6 +65,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       i2c-sensor.dtbo \
-       i2c0-bcm2708.dtbo \
-       i2c1-bcm2708.dtbo \
-+      i2c3.dtbo \
-+      i2c4.dtbo \
-+      i2c5.dtbo \
-+      i2c6.dtbo \
-       i2s-gpio28-31.dtbo \
-       ilitek251x.dtbo \
-       iqaudio-codec.dtbo \
-@@ -149,6 +153,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       tpm-slb9670.dtbo \
-       uart0.dtbo \
-       uart1.dtbo \
-+      uart2.dtbo \
-+      uart3.dtbo \
-+      uart4.dtbo \
-+      uart5.dtbo \
-       udrc.dtbo \
-       upstream.dtbo \
-       vc4-fkms-v3d.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1137,6 +1137,34 @@ Params: sda1_pin                GPIO pin
-                                 "yes")
-+Name:   i2c3
-+Info:   Enable the i2c3 bus
-+Load:   dtoverlay=i2c3,<param>
-+Params: pins_2_3                Use GPIOs 2 and 3
-+        pins_4_5                Use GPIOs 4 and 5 (default)
-+
-+
-+Name:   i2c4
-+Info:   Enable the i2c4 bus
-+Load:   dtoverlay=i2c4,<param>
-+Params: pins_6_7                Use GPIOs 6 and 7
-+        pins_8_9                Use GPIOs 8 and 9 (default)
-+
-+
-+Name:   i2c5
-+Info:   Enable the i2c5 bus
-+Load:   dtoverlay=i2c5,<param>
-+Params: pins_10_11              Use GPIOs 10 and 11
-+        pins_12_13              Use GPIOs 12 and 13 (default)
-+
-+
-+Name:   i2c6
-+Info:   Enable the i2c6 bus
-+Load:   dtoverlay=i2c6,<param>
-+Params: pins_0_1                Use GPIOs 0 and 1
-+        pins_22_23              Use GPIOs 22 and 23 (default)
-+
-+
- Name:   i2s-gpio28-31
- Info:   move I2S function block to GPIO 28 to 31
- Load:   dtoverlay=i2s-gpio28-31
-@@ -2199,6 +2227,30 @@ Params: txd1_pin                GPIO pin
-         rxd1_pin                GPIO pin for RXD1 (15, 33 or 41 - default 15)
-+Name:   uart2
-+Info:   Enable uart 2 on GPIOs 0-3
-+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
-+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
-+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
-+Load:   dtoverlay=uart5,<param>
-+Params: ctsrts                  Enable CTS/RTS on GPIOs 14-15 (default off)
-+
-+
- Name:   udrc
- Info:   Configures the NW Digital Radio UDRC Hat
- Load:   dtoverlay=udrc,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&i2c3>;
-+              __overlay__ {
-+                      status = "okay";
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&i2c3_pins>;
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c3_pins>;
-+              __dormant__ {
-+                      brcm,pins = <2 3>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              pins_2_3 = <0>,"=1";
-+              pins_4_5 = <0>,"!1";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&i2c4>;
-+              __overlay__ {
-+                      status = "okay";
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&i2c4_pins>;
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c4_pins>;
-+              __dormant__ {
-+                      brcm,pins = <6 7>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              pins_6_7 = <0>,"=1";
-+              pins_8_9 = <0>,"!1";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&i2c5>;
-+              __overlay__ {
-+                      status = "okay";
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&i2c5_pins>;
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c5_pins>;
-+              __dormant__ {
-+                      brcm,pins = <10 11>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              pins_10_11 = <0>,"=1";
-+              pins_12_13 = <0>,"!1";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&i2c6>;
-+              __overlay__ {
-+                      status = "okay";
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&i2c6_pins>;
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c6_pins>;
-+              __dormant__ {
-+                      brcm,pins = <0 1>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              pins_0_1 = <0>,"=1";
-+              pins_22_23 = <0>,"!1";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart2-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&uart2>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&uart2_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&uart2_pins>;
-+              __dormant__ {
-+                      brcm,pins = <0 1 2 3>;
-+                      brcm,pull = <0 2 2 0>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              ctsrts = <0>,"=1";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart3-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&uart3>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&uart3_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&uart3_pins>;
-+              __dormant__ {
-+                      brcm,pins = <4 5 6 7>;
-+                      brcm,pull = <0 2 2 0>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              ctsrts = <0>,"=1";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart4-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&uart4>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&uart4_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&uart4_pins>;
-+              __dormant__ {
-+                      brcm,pins = <8 9 10 11>;
-+                      brcm,pull = <0 2 2 0>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              ctsrts = <0>,"=1";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart5-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&uart5>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&uart5_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&uart5_pins>;
-+              __dormant__ {
-+                      brcm,pins = <12 13 14 15>;
-+                      brcm,pull = <0 2 2 0>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              ctsrts = <0>,"=1";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0560-overlays-Add-the-spi-gpio40-45-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0560-overlays-Add-the-spi-gpio40-45-overlay.patch
new file mode 100644 (file)
index 0000000..26930ba
--- /dev/null
@@ -0,0 +1,80 @@
+From 726da40b8c272d181a41686195f91b914363167b Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Tue, 22 Jan 2019 10:49:41 +0000
+Subject: [PATCH] overlays: Add the spi-gpio40-45 overlay
+
+The 2711 B0 boot EEPROM is programmed via SPI0 on GPIO
+pins 40-43 CS0. Add a device tree overlay to optionally
+change the SPI0 pinmux from the external GPIO pins to
+the boot EEPROM pins.
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  6 ++++
+ .../dts/overlays/spi-gpio40-45-overlay.dts    | 36 +++++++++++++++++++
+ 3 files changed, 43 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       smi-dev.dtbo \
+       smi-nand.dtbo \
+       spi-gpio35-39.dtbo \
++      spi-gpio40-45.dtbo \
+       spi-rtc.dtbo \
+       spi0-cs.dtbo \
+       spi0-hw-cs.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1967,6 +1967,12 @@ Load:   dtoverlay=spi-gpio35-39
+ Params: <None>
++Name:   spi-gpio40-45
++Info:   Move SPI function block to GPIOs 40 to 45
++Load:   dtoverlay=spi-gpio40-45
++Params: <None>
++
++
+ Name:   spi-rtc
+ Info:   Adds support for a number of SPI Real Time Clock devices
+ Load:   dtoverlay=spi-rtc,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
+@@ -0,0 +1,36 @@
++/*
++ * Boot EEPROM overlay
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spi0>;
++              __overlay__ {
++                      cs-gpios = <&gpio 43 1>, <&gpio 44 1>, <&gpio 45 1>;
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&spi0_cs_pins>;
++              __overlay__ {
++                      brcm,pins = <45 44 43>;
++                      brcm,function = <1>; /* output */
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&spi0_pins>;
++              __overlay__ {
++                      brcm,pins = <40 41 42>;
++                      brcm,function = <3>; /* alt4 */
++                      status = "okay";
++              };
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0561-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch b/target/linux/brcm2708/patches-4.19/950-0561-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch
new file mode 100644 (file)
index 0000000..a38cc65
--- /dev/null
@@ -0,0 +1,44 @@
+From 0e8ed7a892a510383017cdddee7b772473f1f7c8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 4 Sep 2018 11:50:25 +0100
+Subject: [PATCH] config: Permit LPAE and PCIE_BRCMSTB on BCM2835
+
+---
+ arch/arm/mach-bcm/Kconfig      | 4 ++++
+ drivers/pci/controller/Kconfig | 4 ++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/mach-bcm/Kconfig
++++ b/arch/arm/mach-bcm/Kconfig
+@@ -161,6 +161,7 @@ config ARCH_BCM2835
+       select GPIOLIB
+       select ARM_AMBA
+       select ARM_ERRATA_411920 if ARCH_MULTI_V6
++      select ARM_GIC
+       select ARM_TIMER_SP804
+       select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
+       select TIMER_OF
+@@ -169,6 +170,9 @@ config ARCH_BCM2835
+       select PINCTRL
+       select PINCTRL_BCM2835
+       select MFD_SYSCON if ARCH_MULTI_V7
++      select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
++      select ZONE_DMA if ARM_LPAE
++      select MFD_CORE
+       help
+         This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
+         This SoC is used in the Raspberry Pi and Roku 2 devices.
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -280,9 +280,9 @@ config VMD
+ config PCIE_BRCMSTB
+       tristate "Broadcom Brcmstb PCIe platform host driver"
+-      depends on ARCH_BRCMSTB || BMIPS_GENERIC
++      depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM2835
+       depends on OF
+-      depends on SOC_BRCMSTB
++      depends on SOC_BRCMSTB || ARCH_BCM2835
+       default ARCH_BRCMSTB || BMIPS_GENERIC
+       help
+         Adds support for Broadcom Settop Box PCIe host controller.
diff --git a/target/linux/brcm2708/patches-4.19/950-0561-spi-devicetree-add-overlays-for-spi-3-to-6.patch b/target/linux/brcm2708/patches-4.19/950-0561-spi-devicetree-add-overlays-for-spi-3-to-6.patch
deleted file mode 100644 (file)
index 27de73d..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-From a4ea446a07d7ba010c3c32286a22dc89cffa1e54 Mon Sep 17 00:00:00 2001
-From: Martin Sperl <kernel@martin.sperl.org>
-Date: Sun, 12 May 2019 16:17:08 +0000
-Subject: [PATCH] spi: devicetree: add overlays for spi 3 to 6
-
-Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
----
- arch/arm/boot/dts/overlays/Makefile           |   8 ++
- arch/arm/boot/dts/overlays/README             | 104 ++++++++++++++++++
- .../boot/dts/overlays/spi3-1cs-overlay.dts    |  44 ++++++++
- .../boot/dts/overlays/spi3-2cs-overlay.dts    |  56 ++++++++++
- .../boot/dts/overlays/spi4-1cs-overlay.dts    |  44 ++++++++
- .../boot/dts/overlays/spi4-2cs-overlay.dts    |  56 ++++++++++
- .../boot/dts/overlays/spi5-1cs-overlay.dts    |  44 ++++++++
- .../boot/dts/overlays/spi5-2cs-overlay.dts    |  56 ++++++++++
- .../boot/dts/overlays/spi6-1cs-overlay.dts    |  44 ++++++++
- .../boot/dts/overlays/spi6-2cs-overlay.dts    |  56 ++++++++++
- 10 files changed, 512 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -144,6 +144,14 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       spi2-1cs.dtbo \
-       spi2-2cs.dtbo \
-       spi2-3cs.dtbo \
-+      spi3-1cs.dtbo \
-+      spi3-2cs.dtbo \
-+      spi4-1cs.dtbo \
-+      spi4-2cs.dtbo \
-+      spi5-1cs.dtbo \
-+      spi5-2cs.dtbo \
-+      spi6-1cs.dtbo \
-+      spi6-2cs.dtbo \
-       ssd1306.dtbo \
-       superaudioboard.dtbo \
-       sx150x.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2085,6 +2085,110 @@ Params: cs0_pin                 GPIO pin
-                                 is 'okay' or enabled).
-+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.
-+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
-+                                userspace device node /dev/spidev3.0 (default
-+                                is 'on' or enabled).
-+
-+
-+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.
-+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).
-+        cs0_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev3.0 (default
-+                                is 'on' or enabled).
-+        cs1_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev3.1 (default
-+                                is 'on' or enabled).
-+
-+
-+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.
-+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
-+                                userspace device node /dev/spidev4.0 (default
-+                                is 'on' or enabled).
-+
-+
-+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.
-+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).
-+        cs0_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev4.0 (default
-+                                is 'on' or enabled).
-+        cs1_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev4.1 (default
-+                                is 'on' or enabled).
-+
-+
-+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.
-+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
-+                                userspace device node /dev/spidev5.0 (default
-+                                is 'on' or enabled).
-+
-+
-+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.
-+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).
-+        cs0_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev5.0 (default
-+                                is 'on' or enabled).
-+        cs1_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev5.1 (default
-+                                is 'on' or enabled).
-+
-+
-+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.
-+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
-+                                userspace device node /dev/spidev6.0 (default
-+                                is 'on' or enabled).
-+
-+
-+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.
-+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).
-+        cs0_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev6.0 (default
-+                                is 'on' or enabled).
-+        cs1_spidev              Set to 'off' to prevent the creation of a
-+                                userspace device node /dev/spidev6.1 (default
-+                                is 'on' or enabled).
-+
-+
- Name:   ssd1306
- Info:   Overlay for activation of SSD1306 over I2C OLED display framebuffer.
- Load:   dtoverlay=ssd1306,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi3_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <0>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi3>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
-+                      cs-gpios = <&gpio 0 1>;
-+                      status = "okay";
-+
-+                      spidev3_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs0_spidev = <&spidev3_0>,"status";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi3_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <0 24>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi3>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
-+                      cs-gpios = <&gpio 0 1>, <&gpio 24 1>;
-+                      status = "okay";
-+
-+                      spidev3_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+
-+                      spidev3_1: spidev@1 {
-+                              compatible = "spidev";
-+                              reg = <1>;      /* CE1 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs1_pin  = <&frag0>,"brcm,pins:4",
-+                         <&frag1>,"cs-gpios:16";
-+              cs0_spidev = <&spidev3_0>,"status";
-+              cs1_spidev = <&spidev3_1>,"status";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi4_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <4>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi4>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
-+                      cs-gpios = <&gpio 4 1>;
-+                      status = "okay";
-+
-+                      spidev4_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs0_spidev = <&spidev4_0>,"status";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi4_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <4 25>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi4>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
-+                      cs-gpios = <&gpio 4 1>, <&gpio 25 1>;
-+                      status = "okay";
-+
-+                      spidev4_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+
-+                      spidev4_1: spidev@1 {
-+                              compatible = "spidev";
-+                              reg = <1>;      /* CE1 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs1_pin  = <&frag0>,"brcm,pins:4",
-+                         <&frag1>,"cs-gpios:16";
-+              cs0_spidev = <&spidev4_0>,"status";
-+              cs1_spidev = <&spidev4_1>,"status";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi5_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <12>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi5>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
-+                      cs-gpios = <&gpio 12 1>;
-+                      status = "okay";
-+
-+                      spidev5_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs0_spidev = <&spidev5_0>,"status";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi5_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <12 26>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi5>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
-+                      cs-gpios = <&gpio 12 1>, <&gpio 26 1>;
-+                      status = "okay";
-+
-+                      spidev5_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+
-+                      spidev5_1: spidev@1 {
-+                              compatible = "spidev";
-+                              reg = <1>;      /* CE1 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs1_pin  = <&frag0>,"brcm,pins:4",
-+                         <&frag1>,"cs-gpios:16";
-+              cs0_spidev = <&spidev5_0>,"status";
-+              cs1_spidev = <&spidev5_1>,"status";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi6_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <18>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi6>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
-+                      cs-gpios = <&gpio 18 1>;
-+                      status = "okay";
-+
-+                      spidev6_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs0_spidev = <&spidev6_0>,"status";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+      compatible = "brcm,bcm2838";
-+
-+      fragment@0 {
-+              target = <&spi6_cs_pins>;
-+              frag0: __overlay__ {
-+                      brcm,pins = <18 27>;
-+                      brcm,function = <1>; /* output */
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi6>;
-+              frag1: __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
-+                      cs-gpios = <&gpio 18 1>, <&gpio 27 1>;
-+                      status = "okay";
-+
-+                      spidev6_0: spidev@0 {
-+                              compatible = "spidev";
-+                              reg = <0>;      /* CE0 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+
-+                      spidev6_1: spidev@1 {
-+                              compatible = "spidev";
-+                              reg = <1>;      /* CE1 */
-+                              #address-cells = <1>;
-+                              #size-cells = <0>;
-+                              spi-max-frequency = <125000000>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              cs0_pin  = <&frag0>,"brcm,pins:0",
-+                         <&frag1>,"cs-gpios:4";
-+              cs1_pin  = <&frag0>,"brcm,pins:4",
-+                         <&frag1>,"cs-gpios:16";
-+              cs0_spidev = <&spidev6_0>,"status";
-+              cs1_spidev = <&spidev6_1>,"status";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0562-2711-Add-basic-64-bit-support.patch b/target/linux/brcm2708/patches-4.19/950-0562-2711-Add-basic-64-bit-support.patch
new file mode 100644 (file)
index 0000000..892914b
--- /dev/null
@@ -0,0 +1,33 @@
+From 0e7db01b8ce2c2fb5596e7a9b7104e9947e5c269 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 8 Mar 2019 21:12:39 +0000
+Subject: [PATCH] 2711: Add basic 64-bit support
+
+This commit adds initial support for 64-bit 2711 builds. However,
+it will only work as much as it does if the Pi4 RAM is limited to
+1GB - more than that and several things break (SD card, coherent
+allocations, etc.)
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm64/boot/dts/broadcom/Makefile         |    1 +
+ .../boot/dts/broadcom/bcm2711-rpi-4-b.dts     |    3 +
+ 3 files changed, 1295 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
+
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rp
+                             bcm2837-rpi-3-b-plus.dtb
+ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
++dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.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-4-b.dts
+@@ -0,0 +1,3 @@
++#define RPI364
++
++#include "../../../../arm/boot/dts/bcm2711-rpi-4-b.dts"
diff --git a/target/linux/brcm2708/patches-4.19/950-0562-overlays-Add-the-spi-gpio40-45-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0562-overlays-Add-the-spi-gpio40-45-overlay.patch
deleted file mode 100644 (file)
index 26930ba..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-From 726da40b8c272d181a41686195f91b914363167b Mon Sep 17 00:00:00 2001
-From: Tim Gover <tim.gover@raspberrypi.org>
-Date: Tue, 22 Jan 2019 10:49:41 +0000
-Subject: [PATCH] overlays: Add the spi-gpio40-45 overlay
-
-The 2711 B0 boot EEPROM is programmed via SPI0 on GPIO
-pins 40-43 CS0. Add a device tree overlay to optionally
-change the SPI0 pinmux from the external GPIO pins to
-the boot EEPROM pins.
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             |  6 ++++
- .../dts/overlays/spi-gpio40-45-overlay.dts    | 36 +++++++++++++++++++
- 3 files changed, 43 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       smi-dev.dtbo \
-       smi-nand.dtbo \
-       spi-gpio35-39.dtbo \
-+      spi-gpio40-45.dtbo \
-       spi-rtc.dtbo \
-       spi0-cs.dtbo \
-       spi0-hw-cs.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1967,6 +1967,12 @@ Load:   dtoverlay=spi-gpio35-39
- Params: <None>
-+Name:   spi-gpio40-45
-+Info:   Move SPI function block to GPIOs 40 to 45
-+Load:   dtoverlay=spi-gpio40-45
-+Params: <None>
-+
-+
- Name:   spi-rtc
- Info:   Adds support for a number of SPI Real Time Clock devices
- Load:   dtoverlay=spi-rtc,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
-@@ -0,0 +1,36 @@
-+/*
-+ * Boot EEPROM overlay
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&spi0>;
-+              __overlay__ {
-+                      cs-gpios = <&gpio 43 1>, <&gpio 44 1>, <&gpio 45 1>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spi0_cs_pins>;
-+              __overlay__ {
-+                      brcm,pins = <45 44 43>;
-+                      brcm,function = <1>; /* output */
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&spi0_pins>;
-+              __overlay__ {
-+                      brcm,pins = <40 41 42>;
-+                      brcm,function = <3>; /* alt4 */
-+                      status = "okay";
-+              };
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0563-ARM-dts-bcm283x-Correct-vchiq-compatible-string-2840.patch b/target/linux/brcm2708/patches-4.19/950-0563-ARM-dts-bcm283x-Correct-vchiq-compatible-string-2840.patch
new file mode 100644 (file)
index 0000000..29f3cdb
--- /dev/null
@@ -0,0 +1,76 @@
+From 91aa97cc3a193cfd29962e328f9d1da0d8e0aaff Mon Sep 17 00:00:00 2001
+From: 6by9 <6by9@users.noreply.github.com>
+Date: Wed, 30 Jan 2019 14:22:03 +0000
+Subject: [PATCH] ARM: dts: bcm283x: Correct vchiq compatible string
+ (#2840)
+
+commit 499770ede3f829e80539f46b59b5f460dc327aa6 upstream.
+
+To allow VCHIQ to determine the correct cache line size, use the new
+"brcm,bcm2836-vchiq" compatible string on BCM2836 and BCM2837.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ arch/arm/boot/dts/bcm2835-rpi.dtsi         | 2 +-
+ arch/arm/boot/dts/bcm2836-rpi-2-b.dts      | 2 +-
+ arch/arm/boot/dts/bcm2836-rpi.dtsi         | 6 ++++++
+ arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
+ arch/arm/boot/dts/bcm2837-rpi-3-b.dts      | 2 +-
+ 5 files changed, 10 insertions(+), 4 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2836-rpi.dtsi
+
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -30,7 +30,7 @@
+                       #power-domain-cells = <1>;
+               };
+-              mailbox@7e00b840 {
++              vchiq: mailbox@7e00b840 {
+                       compatible = "brcm,bcm2835-vchiq";
+                       reg = <0x7e00b840 0x3c>;
+                       interrupts = <0 2>;
+--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /dts-v1/;
+ #include "bcm2836.dtsi"
+-#include "bcm2835-rpi.dtsi"
++#include "bcm2836-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-usb-host.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2836-rpi.dtsi
+@@ -0,0 +1,6 @@
++// SPDX-License-Identifier: GPL-2.0
++#include "bcm2835-rpi.dtsi"
++
++&vchiq {
++      compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
++};
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /dts-v1/;
+ #include "bcm2837.dtsi"
+-#include "bcm2835-rpi.dtsi"
++#include "bcm2836-rpi.dtsi"
+ #include "bcm283x-rpi-lan7515.dtsi"
+ #include "bcm283x-rpi-usb-host.dtsi"
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /dts-v1/;
+ #include "bcm2837.dtsi"
+-#include "bcm2835-rpi.dtsi"
++#include "bcm2836-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-usb-host.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
diff --git a/target/linux/brcm2708/patches-4.19/950-0563-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch b/target/linux/brcm2708/patches-4.19/950-0563-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch
deleted file mode 100644 (file)
index a38cc65..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 0e8ed7a892a510383017cdddee7b772473f1f7c8 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 4 Sep 2018 11:50:25 +0100
-Subject: [PATCH] config: Permit LPAE and PCIE_BRCMSTB on BCM2835
-
----
- arch/arm/mach-bcm/Kconfig      | 4 ++++
- drivers/pci/controller/Kconfig | 4 ++--
- 2 files changed, 6 insertions(+), 2 deletions(-)
-
---- a/arch/arm/mach-bcm/Kconfig
-+++ b/arch/arm/mach-bcm/Kconfig
-@@ -161,6 +161,7 @@ config ARCH_BCM2835
-       select GPIOLIB
-       select ARM_AMBA
-       select ARM_ERRATA_411920 if ARCH_MULTI_V6
-+      select ARM_GIC
-       select ARM_TIMER_SP804
-       select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
-       select TIMER_OF
-@@ -169,6 +170,9 @@ config ARCH_BCM2835
-       select PINCTRL
-       select PINCTRL_BCM2835
-       select MFD_SYSCON if ARCH_MULTI_V7
-+      select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
-+      select ZONE_DMA if ARM_LPAE
-+      select MFD_CORE
-       help
-         This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
-         This SoC is used in the Raspberry Pi and Roku 2 devices.
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -280,9 +280,9 @@ config VMD
- config PCIE_BRCMSTB
-       tristate "Broadcom Brcmstb PCIe platform host driver"
--      depends on ARCH_BRCMSTB || BMIPS_GENERIC
-+      depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM2835
-       depends on OF
--      depends on SOC_BRCMSTB
-+      depends on SOC_BRCMSTB || ARCH_BCM2835
-       default ARCH_BRCMSTB || BMIPS_GENERIC
-       help
-         Adds support for Broadcom Settop Box PCIe host controller.
diff --git a/target/linux/brcm2708/patches-4.19/950-0564-2711-Add-basic-64-bit-support.patch b/target/linux/brcm2708/patches-4.19/950-0564-2711-Add-basic-64-bit-support.patch
deleted file mode 100644 (file)
index 892914b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 0e7db01b8ce2c2fb5596e7a9b7104e9947e5c269 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 8 Mar 2019 21:12:39 +0000
-Subject: [PATCH] 2711: Add basic 64-bit support
-
-This commit adds initial support for 64-bit 2711 builds. However,
-it will only work as much as it does if the Pi4 RAM is limited to
-1GB - more than that and several things break (SD card, coherent
-allocations, etc.)
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm64/boot/dts/broadcom/Makefile         |    1 +
- .../boot/dts/broadcom/bcm2711-rpi-4-b.dts     |    3 +
- 3 files changed, 1295 insertions(+)
- create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
-
---- a/arch/arm64/boot/dts/broadcom/Makefile
-+++ b/arch/arm64/boot/dts/broadcom/Makefile
-@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rp
-                             bcm2837-rpi-3-b-plus.dtb
- dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb
- dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
-+dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.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-4-b.dts
-@@ -0,0 +1,3 @@
-+#define RPI364
-+
-+#include "../../../../arm/boot/dts/bcm2711-rpi-4-b.dts"
diff --git a/target/linux/brcm2708/patches-4.19/950-0564-arm-dts-Change-downstream-vchiq-compatible-string.patch b/target/linux/brcm2708/patches-4.19/950-0564-arm-dts-Change-downstream-vchiq-compatible-string.patch
new file mode 100644 (file)
index 0000000..4fda05e
--- /dev/null
@@ -0,0 +1,59 @@
+From 00d8817ab207a9f60e94e87acf4f170155aecd48 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 6 Feb 2019 20:45:16 +0000
+Subject: [PATCH] arm: dts: Change downstream vchiq compatible string
+
+The new cache line size mechanism requires a different vchiq compatible
+string on BCM2836 and BCM2837, but the downstream dts files didn't
+inherit the upstream changes.
+
+See: https://github.com/raspberrypi/linux/issues/2643
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 2 +-
+ arch/arm/boot/dts/bcm2709-rpi.dtsi | 5 +++++
+ arch/arm/boot/dts/bcm2709.dtsi     | 2 +-
+ arch/arm/boot/dts/bcm2710.dtsi     | 2 +-
+ 4 files changed, 8 insertions(+), 3 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2709-rpi.dtsi
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -68,7 +68,7 @@
+                       status = "disabled";
+               };
+-              mailbox@7e00b840 {
++              vchiq: mailbox@7e00b840 {
+                       compatible = "brcm,bcm2835-vchiq";
+                       reg = <0x7e00b840 0x3c>;
+                       interrupts = <0 2>;
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2709-rpi.dtsi
+@@ -0,0 +1,5 @@
++#include "bcm2708-rpi.dtsi"
++
++&vchiq {
++      compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
++};
+--- a/arch/arm/boot/dts/bcm2709.dtsi
++++ b/arch/arm/boot/dts/bcm2709.dtsi
+@@ -1,6 +1,6 @@
+ #include "bcm2836.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
++#include "bcm2709-rpi.dtsi"
+ / {
+       soc {
+--- a/arch/arm/boot/dts/bcm2710.dtsi
++++ b/arch/arm/boot/dts/bcm2710.dtsi
+@@ -1,6 +1,6 @@
+ #include "bcm2837.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
++#include "bcm2709-rpi.dtsi"
+ / {
+       compatible = "brcm,bcm2837", "brcm,bcm2836";
diff --git a/target/linux/brcm2708/patches-4.19/950-0565-ARM-dts-bcm283x-Correct-vchiq-compatible-string-2840.patch b/target/linux/brcm2708/patches-4.19/950-0565-ARM-dts-bcm283x-Correct-vchiq-compatible-string-2840.patch
deleted file mode 100644 (file)
index 29f3cdb..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-From 91aa97cc3a193cfd29962e328f9d1da0d8e0aaff Mon Sep 17 00:00:00 2001
-From: 6by9 <6by9@users.noreply.github.com>
-Date: Wed, 30 Jan 2019 14:22:03 +0000
-Subject: [PATCH] ARM: dts: bcm283x: Correct vchiq compatible string
- (#2840)
-
-commit 499770ede3f829e80539f46b59b5f460dc327aa6 upstream.
-
-To allow VCHIQ to determine the correct cache line size, use the new
-"brcm,bcm2836-vchiq" compatible string on BCM2836 and BCM2837.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- arch/arm/boot/dts/bcm2835-rpi.dtsi         | 2 +-
- arch/arm/boot/dts/bcm2836-rpi-2-b.dts      | 2 +-
- arch/arm/boot/dts/bcm2836-rpi.dtsi         | 6 ++++++
- arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
- arch/arm/boot/dts/bcm2837-rpi-3-b.dts      | 2 +-
- 5 files changed, 10 insertions(+), 4 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2836-rpi.dtsi
-
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -30,7 +30,7 @@
-                       #power-domain-cells = <1>;
-               };
--              mailbox@7e00b840 {
-+              vchiq: mailbox@7e00b840 {
-                       compatible = "brcm,bcm2835-vchiq";
-                       reg = <0x7e00b840 0x3c>;
-                       interrupts = <0 2>;
---- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-@@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /dts-v1/;
- #include "bcm2836.dtsi"
--#include "bcm2835-rpi.dtsi"
-+#include "bcm2836-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-usb-host.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2836-rpi.dtsi
-@@ -0,0 +1,6 @@
-+// SPDX-License-Identifier: GPL-2.0
-+#include "bcm2835-rpi.dtsi"
-+
-+&vchiq {
-+      compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
-+};
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-@@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /dts-v1/;
- #include "bcm2837.dtsi"
--#include "bcm2835-rpi.dtsi"
-+#include "bcm2836-rpi.dtsi"
- #include "bcm283x-rpi-lan7515.dtsi"
- #include "bcm283x-rpi-usb-host.dtsi"
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-@@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /dts-v1/;
- #include "bcm2837.dtsi"
--#include "bcm2835-rpi.dtsi"
-+#include "bcm2836-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-usb-host.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
diff --git a/target/linux/brcm2708/patches-4.19/950-0565-bcm2835-dma-Add-proper-40-bit-DMA-support.patch b/target/linux/brcm2708/patches-4.19/950-0565-bcm2835-dma-Add-proper-40-bit-DMA-support.patch
new file mode 100644 (file)
index 0000000..7ca14c8
--- /dev/null
@@ -0,0 +1,1018 @@
+From 621fb1606217c3e72feda69255ae6cb6a7ccfec2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 4 Apr 2019 13:33:47 +0100
+Subject: [PATCH] bcm2835-dma: Add proper 40-bit DMA support
+
+The 40-bit additions are not fully tested, but it should be
+capable of supporting both 40-bit memcpy on BCM2711 and regular
+Lite channels on BCM2835.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi               |  33 +-
+ drivers/dma/bcm2835-dma.c                    | 426 ++++++++++++++-----
+ drivers/pci/controller/pcie-brcmstb-bounce.c |  30 +-
+ drivers/pci/controller/pcie-brcmstb-bounce.h |  21 +-
+ drivers/pci/controller/pcie-brcmstb.c        |  23 +-
+ 5 files changed, 395 insertions(+), 138 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -372,6 +372,23 @@
+                       };
+               };
++              dma40: dma@7e007b00 {
++                      compatible = "brcm,bcm2838-dma";
++                      reg = <0x0 0x7e007b00 0x400>;
++                      interrupts =
++                              <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
++                              <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
++                              <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
++                              <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
++                      interrupt-names = "dma11",
++                              "dma12",
++                              "dma13",
++                              "dma14";
++                      #dma-cells = <1>;
++                      brcm,dma-channel-mask = <0x7000>;
++              };
++              /* DMA4 - 40 bit DMA engines */
++
+               xhci: xhci@7e9c0000 {
+                       compatible = "generic-xhci";
+                       status = "disabled";
+@@ -689,6 +706,7 @@
+ };
+ &dma {
++      reg = <0x7e007000 0xb00>;
+       interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+               <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+               <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+@@ -699,12 +717,7 @@
+               <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  7 */
+               <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  8 */
+               <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  9 */
+-              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
+-              /* DMA4 - 40 bit DMA engines */
+-              <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4    11 */
+-              <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4    12 */
+-              <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4    13 */
+-              <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4    14 */
++              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; /* dmalite 10 */
+       interrupt-names = "dma0",
+                         "dma1",
+                         "dma2",
+@@ -715,10 +728,6 @@
+                         "dma7",
+                         "dma8",
+                         "dma9",
+-                        "dma10",
+-                        "dma11",
+-                        "dma12",
+-                        "dma13",
+-                        "dma14";
+-      brcm,dma-channel-mask = <0x7ef5>;
++                        "dma10";
++      brcm,dma-channel-mask = <0x01f5>;
+ };
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -50,12 +50,18 @@
+ #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
+ #define BCM2835_DMA_CHAN_NAME_SIZE 8
+ #define BCM2835_DMA_BULK_MASK  BIT(0)
++#define BCM2838_DMA_MEMCPY_CHAN 14
++
++struct bcm2835_dma_cfg_data {
++      u32     chan_40bit_mask;
++};
+ struct bcm2835_dmadev {
+       struct dma_device ddev;
+       spinlock_t lock;
+       void __iomem *base;
+       struct device_dma_parameters dma_parms;
++      const struct bcm2835_dma_cfg_data *cfg_data;
+ };
+ struct bcm2835_dma_cb {
+@@ -100,6 +106,7 @@ struct bcm2835_chan {
+       unsigned int irq_flags;
+       bool is_lite_channel;
++      bool is_40bit_channel;
+ };
+ struct bcm2835_desc {
+@@ -189,7 +196,8 @@ struct bcm2835_desc {
+ #define BCM2835_DMA_DATA_TYPE_S128    16
+ /* Valid only for channels 0 - 14, 15 has its own base address */
+-#define BCM2835_DMA_CHAN(n)   ((n) << 8) /* Base address */
++#define BCM2835_DMA_CHAN_SIZE 0x100
++#define BCM2835_DMA_CHAN(n)   ((n) * BCM2835_DMA_CHAN_SIZE) /* Base address */
+ #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
+ /* the max dma length for different channels */
+@@ -200,7 +208,7 @@ struct bcm2835_desc {
+ #define BCM2838_DMA40_CS      0x00
+ #define BCM2838_DMA40_CB      0x04
+ #define BCM2838_DMA40_DEBUG   0x0c
+-#define BCM2858_DMA40_TI      0x10
++#define BCM2838_DMA40_TI      0x10
+ #define BCM2838_DMA40_SRC     0x14
+ #define BCM2838_DMA40_SRCI    0x18
+ #define BCM2838_DMA40_DEST    0x1c
+@@ -209,32 +217,97 @@ struct bcm2835_desc {
+ #define BCM2838_DMA40_NEXT_CB 0x28
+ #define BCM2838_DMA40_DEBUG2  0x2c
+-#define BCM2838_DMA40_CS_ACTIVE       BIT(0)
+-#define BCM2838_DMA40_CS_END  BIT(1)
++#define BCM2838_DMA40_ACTIVE          BIT(0)
++#define BCM2838_DMA40_END             BIT(1)
++#define BCM2838_DMA40_INT             BIT(2)
++#define BCM2838_DMA40_DREQ            BIT(3)  /* DREQ state */
++#define BCM2838_DMA40_RD_PAUSED               BIT(4)  /* Reading is paused */
++#define BCM2838_DMA40_WR_PAUSED               BIT(5)  /* Writing is paused */
++#define BCM2838_DMA40_DREQ_PAUSED     BIT(6)  /* Is paused by DREQ flow control */
++#define BCM2838_DMA40_WAITING_FOR_WRITES BIT(7)  /* Waiting for last write */
++#define BCM2838_DMA40_ERR             BIT(10)
++#define BCM2838_DMA40_QOS(x)          (((x) & 0x1f) << 16)
++#define BCM2838_DMA40_PANIC_QOS(x)    (((x) & 0x1f) << 20)
++#define BCM2838_DMA40_WAIT_FOR_WRITES BIT(28)
++#define BCM2838_DMA40_DISDEBUG                BIT(29)
++#define BCM2838_DMA40_ABORT           BIT(30)
++#define BCM2838_DMA40_HALT            BIT(31)
++#define BCM2838_DMA40_CS_FLAGS(x) (x & (BCM2838_DMA40_QOS(15) | \
++                                      BCM2838_DMA40_PANIC_QOS(15) | \
++                                      BCM2838_DMA40_WAIT_FOR_WRITES | \
++                                      BCM2838_DMA40_DISDEBUG))
++
++/* Transfer information bits */
++#define BCM2838_DMA40_INTEN           BIT(0)
++#define BCM2838_DMA40_TDMODE          BIT(1) /* 2D-Mode */
++#define BCM2838_DMA40_WAIT_RESP               BIT(2) /* wait for AXI write to be acked */
++#define BCM2838_DMA40_WAIT_RD_RESP    BIT(3) /* wait for AXI read to complete */
++#define BCM2838_DMA40_PER_MAP(x)      ((x & 31) << 9) /* REQ source */
++#define BCM2838_DMA40_S_DREQ          BIT(14) /* enable SREQ for source */
++#define BCM2838_DMA40_D_DREQ          BIT(15) /* enable DREQ for destination */
++#define BCM2838_DMA40_S_WAIT(x)               ((x & 0xff) << 16) /* add DMA read-wait cycles */
++#define BCM2838_DMA40_D_WAIT(x)               ((x & 0xff) << 24) /* add DMA write-wait cycles */
+-#define BCM2838_DMA40_CS_QOS(x)       (((x) & 0x1f) << 16)
+-#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
+-#define BCM2838_DMA40_CS_WRITE_WAIT   BIT(28)
++/* debug register bits */
++#define BCM2838_DMA40_DEBUG_WRITE_ERR         BIT(0)
++#define BCM2838_DMA40_DEBUG_FIFO_ERR          BIT(1)
++#define BCM2838_DMA40_DEBUG_READ_ERR          BIT(2)
++#define BCM2838_DMA40_DEBUG_READ_CB_ERR               BIT(3)
++#define BCM2838_DMA40_DEBUG_IN_ON_ERR         BIT(8)
++#define BCM2838_DMA40_DEBUG_ABORT_ON_ERR      BIT(9)
++#define BCM2838_DMA40_DEBUG_HALT_ON_ERR               BIT(10)
++#define BCM2838_DMA40_DEBUG_DISABLE_CLK_GATE  BIT(11)
++#define BCM2838_DMA40_DEBUG_RSTATE_SHIFT      14
++#define BCM2838_DMA40_DEBUG_RSTATE_BITS               4
++#define BCM2838_DMA40_DEBUG_WSTATE_SHIFT      18
++#define BCM2838_DMA40_DEBUG_WSTATE_BITS               4
++#define BCM2838_DMA40_DEBUG_RESET             BIT(23)
++#define BCM2838_DMA40_DEBUG_ID_SHIFT          24
++#define BCM2838_DMA40_DEBUG_ID_BITS           4
++#define BCM2838_DMA40_DEBUG_VERSION_SHIFT     28
++#define BCM2838_DMA40_DEBUG_VERSION_BITS      4
++
++/* Valid only for channels 0 - 3 (11 - 14) */
++#define BCM2838_DMA40_CHAN(n) (((n) + 11) << 8) /* Base address */
++#define BCM2838_DMA40_CHANIO(base, n) ((base) + BCM2838_DMA_CHAN(n))
+-#define BCM2838_DMA40_BURST_LEN(x)    ((((x) - 1) & 0xf) << 8)
+-#define BCM2838_DMA40_INC             BIT(12)
+-#define BCM2838_DMA40_SIZE_128        (2 << 13)
++/* the max dma length for different channels */
++#define MAX_DMA40_LEN SZ_1G
+-#define BCM2838_DMA40_MEMCPY_QOS \
+-      (BCM2838_DMA40_CS_QOS(0x0) | \
+-       BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
+-       BCM2838_DMA40_CS_WRITE_WAIT)
++#define BCM2838_DMA40_BURST_LEN(x)    ((min(x,16) - 1) << 8)
++#define BCM2838_DMA40_INC             BIT(12)
++#define BCM2838_DMA40_SIZE_32         (0 << 13)
++#define BCM2838_DMA40_SIZE_64         (1 << 13)
++#define BCM2838_DMA40_SIZE_128                (2 << 13)
++#define BCM2838_DMA40_SIZE_256                (3 << 13)
++#define BCM2838_DMA40_IGNORE          BIT(15)
++#define BCM2838_DMA40_STRIDE(x)               ((x) << 16) /* For 2D mode */
++
++#define BCM2838_DMA40_MEMCPY_FLAGS \
++      (BCM2838_DMA40_QOS(0) | \
++       BCM2838_DMA40_PANIC_QOS(0) | \
++       BCM2838_DMA40_WAIT_FOR_WRITES | \
++       BCM2838_DMA40_DISDEBUG)
+ #define BCM2838_DMA40_MEMCPY_XFER_INFO \
+       (BCM2838_DMA40_SIZE_128 | \
+        BCM2838_DMA40_INC | \
+        BCM2838_DMA40_BURST_LEN(16))
++struct bcm2835_dmadev *memcpy_parent;
+ static void __iomem *memcpy_chan;
+ static struct bcm2838_dma40_scb *memcpy_scb;
+ static dma_addr_t memcpy_scb_dma;
+ DEFINE_SPINLOCK(memcpy_lock);
++static const struct bcm2835_dma_cfg_data bcm2835_dma_cfg = {
++      .chan_40bit_mask = 0,
++};
++
++static const struct bcm2835_dma_cfg_data bcm2838_dma_cfg = {
++      .chan_40bit_mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
++};
++
+ static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
+ {
+       /* lite and normal channels have different max frame length */
+@@ -264,6 +337,32 @@ static inline struct bcm2835_desc *to_bc
+       return container_of(t, struct bcm2835_desc, vd.tx);
+ }
++static inline uint32_t to_bcm2838_ti(uint32_t info)
++{
++      return ((info & BCM2835_DMA_INT_EN) ? BCM2838_DMA40_INTEN : 0) |
++              ((info & BCM2835_DMA_WAIT_RESP) ? BCM2838_DMA40_WAIT_RESP : 0) |
++              ((info & BCM2835_DMA_S_DREQ) ?
++               (BCM2838_DMA40_S_DREQ | BCM2838_DMA40_WAIT_RD_RESP) : 0) |
++              ((info & BCM2835_DMA_D_DREQ) ? BCM2838_DMA40_D_DREQ : 0) |
++              BCM2838_DMA40_PER_MAP((info >> 16) & 0x1f);
++}
++
++static inline uint32_t to_bcm2838_srci(uint32_t info)
++{
++      return ((info & BCM2835_DMA_S_INC) ? BCM2838_DMA40_INC : 0);
++}
++
++static inline uint32_t to_bcm2838_dsti(uint32_t info)
++{
++      return ((info & BCM2835_DMA_D_INC) ? BCM2838_DMA40_INC : 0);
++}
++
++static inline uint32_t to_bcm2838_cbaddr(dma_addr_t addr)
++{
++      BUG_ON(addr & 0x1f);
++      return (addr >> 5);
++}
++
+ static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
+ {
+       size_t i;
+@@ -282,45 +381,53 @@ static void bcm2835_dma_desc_free(struct
+ }
+ static void bcm2835_dma_create_cb_set_length(
+-      struct bcm2835_chan *chan,
++      struct bcm2835_chan *c,
+       struct bcm2835_dma_cb *control_block,
+       size_t len,
+       size_t period_len,
+       size_t *total_len,
+       u32 finalextrainfo)
+ {
+-      size_t max_len = bcm2835_dma_max_frame_length(chan);
++      size_t max_len = bcm2835_dma_max_frame_length(c);
++      uint32_t cb_len;
+       /* set the length taking lite-channel limitations into account */
+-      control_block->length = min_t(u32, len, max_len);
++      cb_len = min_t(u32, len, max_len);
+-      /* finished if we have no period_length */
+-      if (!period_len)
+-              return;
++      if (period_len) {
++              /*
++               * period_len means: that we need to generate
++               * transfers that are terminating at every
++               * multiple of period_len - this is typically
++               * used to set the interrupt flag in info
++               * which is required during cyclic transfers
++               */
+-      /*
+-       * period_len means: that we need to generate
+-       * transfers that are terminating at every
+-       * multiple of period_len - this is typically
+-       * used to set the interrupt flag in info
+-       * which is required during cyclic transfers
+-       */
++              /* have we filled in period_length yet? */
++              if (*total_len + cb_len < period_len) {
++                      /* update number of bytes in this period so far */
++                      *total_len += cb_len;
++              } else {
++                      /* calculate the length that remains to reach period_len */
++                      cb_len = period_len - *total_len;
+-      /* have we filled in period_length yet? */
+-      if (*total_len + control_block->length < period_len) {
+-              /* update number of bytes in this period so far */
+-              *total_len += control_block->length;
+-              return;
++                      /* reset total_length for next period */
++                      *total_len = 0;
++              }
+       }
+-      /* calculate the length that remains to reach period_length */
+-      control_block->length = period_len - *total_len;
+-
+-      /* reset total_length for next period */
+-      *total_len = 0;
+-
+-      /* add extrainfo bits in info */
+-      control_block->info |= finalextrainfo;
++      if (c->is_40bit_channel) {
++              struct bcm2838_dma40_scb *scb =
++                      (struct bcm2838_dma40_scb *)control_block;
++
++              scb->len = cb_len;
++              /* add extrainfo bits to ti */
++              scb->ti |= to_bcm2838_ti(finalextrainfo);
++      } else {
++              control_block->length = cb_len;
++              /* add extrainfo bits to info */
++              control_block->info |= finalextrainfo;
++      }
+ }
+ static inline size_t bcm2835_dma_count_frames_for_sg(
+@@ -343,7 +450,7 @@ static inline size_t bcm2835_dma_count_f
+ /**
+  * bcm2835_dma_create_cb_chain - create a control block and fills data in
+  *
+- * @chan:           the @dma_chan for which we run this
++ * @c:              the @bcm2835_chan for which we run this
+  * @direction:      the direction in which we transfer
+  * @cyclic:         it is a cyclic transfer
+  * @info:           the default info bits to apply per controlblock
+@@ -361,12 +468,11 @@ static inline size_t bcm2835_dma_count_f
+  * @gfp:            the GFP flag to use for allocation
+  */
+ static struct bcm2835_desc *bcm2835_dma_create_cb_chain(
+-      struct dma_chan *chan, enum dma_transfer_direction direction,
++      struct bcm2835_chan *c, enum dma_transfer_direction direction,
+       bool cyclic, u32 info, u32 finalextrainfo, size_t frames,
+       dma_addr_t src, dma_addr_t dst, size_t buf_len,
+       size_t period_len, gfp_t gfp)
+ {
+-      struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+       size_t len = buf_len, total_len;
+       size_t frame;
+       struct bcm2835_desc *d;
+@@ -399,11 +505,23 @@ static struct bcm2835_desc *bcm2835_dma_
+               /* fill in the control block */
+               control_block = cb_entry->cb;
+-              control_block->info = info;
+-              control_block->src = src;
+-              control_block->dst = dst;
+-              control_block->stride = 0;
+-              control_block->next = 0;
++              if (c->is_40bit_channel) {
++                      struct bcm2838_dma40_scb *scb =
++                              (struct bcm2838_dma40_scb *)control_block;
++                      scb->ti = to_bcm2838_ti(info);
++                      scb->src = lower_32_bits(src);
++                      scb->srci= upper_32_bits(src) | to_bcm2838_srci(info);
++                      scb->dst = lower_32_bits(dst);
++                      scb->dsti = upper_32_bits(dst) | to_bcm2838_dsti(info);
++                      scb->next_cb = 0;
++              } else {
++                      control_block->info = info;
++                      control_block->src = src;
++                      control_block->dst = dst;
++                      control_block->stride = 0;
++                      control_block->next = 0;
++              }
++
+               /* set up length in control_block if requested */
+               if (buf_len) {
+                       /* calculate length honoring period_length */
+@@ -417,7 +535,10 @@ static struct bcm2835_desc *bcm2835_dma_
+               }
+               /* link this the last controlblock */
+-              if (frame)
++              if (frame && c->is_40bit_channel)
++                      d->cb_list[frame - 1].cb->next =
++                              to_bcm2838_cbaddr(cb_entry->paddr);
++              if (frame && !c->is_40bit_channel)
+                       d->cb_list[frame - 1].cb->next = cb_entry->paddr;
+               /* update src and dst and length */
+@@ -431,7 +552,14 @@ static struct bcm2835_desc *bcm2835_dma_
+       }
+       /* the last frame requires extra flags */
+-      d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
++      if (c->is_40bit_channel) {
++              struct bcm2838_dma40_scb *scb =
++                      (struct bcm2838_dma40_scb *)d->cb_list[d->frames-1].cb;
++
++              scb->ti |= to_bcm2838_ti(finalextrainfo);
++      } else {
++              d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
++      }
+       /* detect a size missmatch */
+       if (buf_len && (d->size != buf_len))
+@@ -445,28 +573,51 @@ error_cb:
+ }
+ static void bcm2835_dma_fill_cb_chain_with_sg(
+-      struct dma_chan *chan,
++      struct bcm2835_chan *c,
+       enum dma_transfer_direction direction,
+       struct bcm2835_cb_entry *cb,
+       struct scatterlist *sgl,
+       unsigned int sg_len)
+ {
+-      struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+       size_t len, max_len;
+       unsigned int i;
+       dma_addr_t addr;
+       struct scatterlist *sgent;
++      pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
++
+       max_len = bcm2835_dma_max_frame_length(c);
+       for_each_sg(sgl, sgent, sg_len, i) {
+-              for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent);
+-                   len > 0;
+-                   addr += cb->cb->length, len -= cb->cb->length, cb++) {
+-                      if (direction == DMA_DEV_TO_MEM)
+-                              cb->cb->dst = addr;
+-                      else
+-                              cb->cb->src = addr;
+-                      cb->cb->length = min(len, max_len);
++              if (c->is_40bit_channel) {
++                      struct bcm2838_dma40_scb *scb =
++                              (struct bcm2838_dma40_scb *)cb->cb;
++                      for (addr = sg_dma_address(sgent),
++                                   len = sg_dma_len(sgent);
++                           len > 0;
++                           addr += scb->len, len -= scb->len, scb++) {
++                              if (direction == DMA_DEV_TO_MEM) {
++                                      scb->dst = lower_32_bits(addr);
++                                      scb->dsti = upper_32_bits(addr) | BCM2838_DMA40_INC;
++                              } else {
++                                      scb->src = lower_32_bits(addr);
++                                      scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
++                              }
++                              scb->len = min(len, max_len);
++                              pr_err("  %llx, %x\n", (u64)addr, scb->len);
++                      }
++              } else {
++                      for (addr = sg_dma_address(sgent),
++                                   len = sg_dma_len(sgent);
++                           len > 0;
++                           addr += cb->cb->length, len -= cb->cb->length,
++                           cb++) {
++                              if (direction == DMA_DEV_TO_MEM)
++                                      cb->cb->dst = addr;
++                              else
++                                      cb->cb->src = addr;
++                              cb->cb->length = min(len, max_len);
++                              pr_err("  %llx, %x\n", (u64)addr, cb->cb->length);
++                      }
+               }
+       }
+ }
+@@ -475,6 +626,10 @@ static int bcm2835_dma_abort(struct bcm2
+ {
+       void __iomem *chan_base = c->chan_base;
+       long int timeout = 10000;
++      u32 wait_mask = BCM2835_DMA_WAITING_FOR_WRITES;
++
++      if (c->is_40bit_channel)
++              wait_mask = BCM2838_DMA40_WAITING_FOR_WRITES;
+       /*
+        * A zero control block address means the channel is idle.
+@@ -487,8 +642,7 @@ static int bcm2835_dma_abort(struct bcm2
+       writel(0, chan_base + BCM2835_DMA_CS);
+       /* Wait for any current AXI transfer to complete */
+-      while ((readl(chan_base + BCM2835_DMA_CS) &
+-              BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
++      while ((readl(chan_base + BCM2835_DMA_CS) & wait_mask) && --timeout)
+               cpu_relax();
+       /* Peripheral might be stuck and fail to signal AXI write responses */
+@@ -505,6 +659,7 @@ static void bcm2835_dma_start_desc(struc
+       struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
+       struct bcm2835_desc *d;
++      pr_err("dma_start_desc(%px)\n", vd);
+       if (!vd) {
+               c->desc = NULL;
+               return;
+@@ -514,9 +669,16 @@ static void bcm2835_dma_start_desc(struc
+       c->desc = d = to_bcm2835_dma_desc(&vd->tx);
+-      writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
+-      writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
+-             c->chan_base + BCM2835_DMA_CS);
++      if (c->is_40bit_channel) {
++              writel(to_bcm2838_cbaddr(d->cb_list[0].paddr),
++                     c->chan_base + BCM2838_DMA40_CB);
++              writel(BCM2838_DMA40_ACTIVE | BCM2838_DMA40_CS_FLAGS(c->dreq),
++                     c->chan_base + BCM2838_DMA40_CS);
++      } else {
++              writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
++              writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
++                     c->chan_base + BCM2835_DMA_CS);
++      }
+ }
+ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
+@@ -544,7 +706,8 @@ static irqreturn_t bcm2835_dma_callback(
+        * will remain idle despite the ACTIVE flag being set.
+        */
+       writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
+-             BCM2835_DMA_CS_FLAGS(c->dreq),
++             (c->is_40bit_channel ? BCM2838_DMA40_CS_FLAGS(c->dreq) :
++              BCM2835_DMA_CS_FLAGS(c->dreq)),
+              c->chan_base + BCM2835_DMA_CS);
+       d = c->desc;
+@@ -643,9 +806,17 @@ static enum dma_status bcm2835_dma_tx_st
+               struct bcm2835_desc *d = c->desc;
+               dma_addr_t pos;
+-              if (d->dir == DMA_MEM_TO_DEV)
++              if (d->dir == DMA_MEM_TO_DEV && c->is_40bit_channel)
++                      pos = readl(c->chan_base + BCM2838_DMA40_SRC) +
++                              ((readl(c->chan_base + BCM2838_DMA40_SRCI) &
++                                0xff) << 8);
++              else if (d->dir == DMA_MEM_TO_DEV && !c->is_40bit_channel)
+                       pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD);
+-              else if (d->dir == DMA_DEV_TO_MEM)
++              else if (d->dir == DMA_DEV_TO_MEM && c->is_40bit_channel)
++                      pos = readl(c->chan_base + BCM2838_DMA40_DEST) +
++                              ((readl(c->chan_base + BCM2838_DMA40_DESTI) &
++                                0xff) << 8);
++              else if (d->dir == DMA_DEV_TO_MEM && !c->is_40bit_channel)
+                       pos = readl(c->chan_base + BCM2835_DMA_DEST_AD);
+               else
+                       pos = 0;
+@@ -691,7 +862,7 @@ static struct dma_async_tx_descriptor *b
+       frames = bcm2835_dma_frames_for_length(len, max_len);
+       /* allocate the CB chain - this also fills in the pointers */
+-      d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false,
++      d = bcm2835_dma_create_cb_chain(c, DMA_MEM_TO_MEM, false,
+                                       info, extra, frames,
+                                       src, dst, len, 0, GFP_KERNEL);
+       if (!d)
+@@ -726,11 +897,21 @@ static struct dma_async_tx_descriptor *b
+               if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+                       return NULL;
+               src = c->cfg.src_addr;
++              /*
++               * One would think it ought to be possible to get the physical
++               * to dma address mapping information from the dma-ranges DT
++               * property, but I've not found a way yet that doesn't involve
++               * open-coding the whole thing.
++               */
++              if (c->is_40bit_channel)
++                  src |= 0x400000000ull;
+               info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
+       } else {
+               if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+                       return NULL;
+               dst = c->cfg.dst_addr;
++              if (c->is_40bit_channel)
++                  dst |= 0x400000000ull;
+               info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
+       }
+@@ -738,7 +919,7 @@ static struct dma_async_tx_descriptor *b
+       frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len);
+       /* allocate the CB chain */
+-      d = bcm2835_dma_create_cb_chain(chan, direction, false,
++      d = bcm2835_dma_create_cb_chain(c, direction, false,
+                                       info, extra,
+                                       frames, src, dst, 0, 0,
+                                       GFP_KERNEL);
+@@ -746,7 +927,7 @@ static struct dma_async_tx_descriptor *b
+               return NULL;
+       /* fill in frames with scatterlist pointers */
+-      bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list,
++      bcm2835_dma_fill_cb_chain_with_sg(c, direction, d->cb_list,
+                                         sgl, sg_len);
+       return vchan_tx_prep(&c->vc, &d->vd, flags);
+@@ -815,7 +996,7 @@ static struct dma_async_tx_descriptor *b
+        * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine
+        * implementation calls prep_dma_cyclic with interrupts disabled.
+        */
+-      d = bcm2835_dma_create_cb_chain(chan, direction, true,
++      d = bcm2835_dma_create_cb_chain(c, direction, true,
+                                       info, extra,
+                                       frames, src, dst, buf_len,
+                                       period_len, GFP_NOWAIT);
+@@ -823,7 +1004,8 @@ static struct dma_async_tx_descriptor *b
+               return NULL;
+       /* wrap around into a loop */
+-      d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr;
++      d->cb_list[d->frames - 1].cb->next = c->is_40bit_channel ?
++              to_bcm2838_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr;
+       return vchan_tx_prep(&c->vc, &d->vd, flags);
+ }
+@@ -899,9 +1081,11 @@ static int bcm2835_dma_chan_init(struct
+       c->irq_number = irq;
+       c->irq_flags = irq_flags;
+-      /* check in DEBUG register if this is a LITE channel */
+-      if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
+-              BCM2835_DMA_DEBUG_LITE)
++      /* check for 40bit and lite channels */
++      if (d->cfg_data->chan_40bit_mask & BIT(chan_id))
++              c->is_40bit_channel = true;
++      else if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
++               BCM2835_DMA_DEBUG_LITE)
+               c->is_lite_channel = true;
+       return 0;
+@@ -918,18 +1102,16 @@ static void bcm2835_dma_free(struct bcm2
+       }
+ }
+-int bcm2838_dma40_memcpy_init(struct device *dev)
++int bcm2838_dma40_memcpy_init(void)
+ {
+-      if (memcpy_scb)
+-              return 0;
++      if (!memcpy_parent)
++              return -EPROBE_DEFER;
+-      memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
+-                                      &memcpy_scb_dma, GFP_KERNEL);
++      if (!memcpy_chan)
++              return -EINVAL;
+-      if (!memcpy_scb) {
+-              pr_err("bcm2838_dma40_memcpy_init failed!\n");
++      if (!memcpy_scb)
+               return -ENOMEM;
+-      }
+       return 0;
+ }
+@@ -956,20 +1138,22 @@ void bcm2838_dma40_memcpy(dma_addr_t dst
+       scb->next_cb = 0;
+       writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
+-      writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
++      writel(BCM2838_DMA40_MEMCPY_FLAGS + BCM2838_DMA40_ACTIVE,
+              memcpy_chan + BCM2838_DMA40_CS);
++
+       /* Poll for completion */
+-      while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
++      while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_END))
+               cpu_relax();
+-      writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
++      writel(BCM2838_DMA40_END, memcpy_chan + BCM2838_DMA40_CS);
+       spin_unlock_irqrestore(&memcpy_lock, flags);
+ }
+ EXPORT_SYMBOL(bcm2838_dma40_memcpy);
+ static const struct of_device_id bcm2835_dma_of_match[] = {
+-      { .compatible = "brcm,bcm2835-dma", },
++      { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_cfg },
++      { .compatible = "brcm,bcm2838-dma", .data = &bcm2838_dma_cfg },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
+@@ -1001,6 +1185,8 @@ 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;
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+@@ -1022,9 +1208,13 @@ static int bcm2835_dma_probe(struct plat
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+-      rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK);
+-      if (rc)
+-              dev_err(&pdev->dev, "Failed to initialize the legacy API\n");
++
++      /* The set of channels can be split across multiple instances. */
++      chan_start = ((u32)base / BCM2835_DMA_CHAN_SIZE) & 0xf;
++      base -= BCM2835_DMA_CHAN(chan_start);
++      chan_count = resource_size(res) / BCM2835_DMA_CHAN_SIZE;
++      chan_end = min(chan_start + chan_count,
++                       BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1);
+       od->base = base;
+@@ -1054,6 +1244,14 @@ static int bcm2835_dma_probe(struct plat
+       platform_set_drvdata(pdev, od);
++      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;
++      }
++
++      od->cfg_data = of_id->data;
++
+       /* Request DMA channel mask from device tree */
+       if (of_property_read_u32(pdev->dev.of_node,
+                       "brcm,dma-channel-mask",
+@@ -1063,18 +1261,34 @@ static int bcm2835_dma_probe(struct plat
+               goto err_no_dma;
+       }
+-      /* Channel 0 is used by the legacy API */
+-      chans_available &= ~BCM2835_DMA_BULK_MASK;
++      /* One channel is reserved for the legacy API */
++      if (chans_available & BCM2835_DMA_BULK_MASK) {
++              rc = bcm_dmaman_probe(pdev, base,
++                                    chans_available & BCM2835_DMA_BULK_MASK);
++              if (rc)
++                      dev_err(&pdev->dev,
++                              "Failed to initialize the legacy API\n");
++
++              chans_available &= ~BCM2835_DMA_BULK_MASK;
++      }
+-      /* We can't use channels 11-13 yet */
+-      chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
++      /* And possibly one for the 40-bit DMA memcpy API */
++      if (chans_available & od->cfg_data->chan_40bit_mask &
++          BIT(BCM2838_DMA_MEMCPY_CHAN)) {
++              memcpy_parent = od;
++              memcpy_chan = BCM2835_DMA_CHANIO(base, BCM2838_DMA_MEMCPY_CHAN);
++              memcpy_scb = dma_alloc_coherent(memcpy_parent->ddev.dev,
++                                              sizeof(*memcpy_scb),
++                                              &memcpy_scb_dma, GFP_KERNEL);
++              if (!memcpy_scb)
++                      dev_warn(&pdev->dev,
++                               "Failed to allocated memcpy scb\n");
+-      /* Grab channel 14 for the 40-bit DMA memcpy */
+-      chans_available &= ~BIT(14);
+-      memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
++              chans_available &= ~BIT(BCM2838_DMA_MEMCPY_CHAN);
++      }
+       /* get irqs for each channel that we support */
+-      for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
++      for (i = chan_start; i < chan_end; i++) {
+               /* skip masked out channels */
+               if (!(chans_available & (1 << i))) {
+                       irq[i] = -1;
+@@ -1097,13 +1311,17 @@ static int bcm2835_dma_probe(struct plat
+               irq[i] = platform_get_irq(pdev, i < 11 ? i : 11);
+       }
++      chan_count = 0;
++
+       /* get irqs for each channel */
+-      for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
++      for (i = chan_start; i < chan_end; i++) {
+               /* skip channels without irq */
+               if (irq[i] < 0)
+                       continue;
+               /* check if there are other channels that also use this irq */
++              /* FIXME: This will fail if interrupts are shared across
++                 instances */
+               irq_flags = 0;
+               for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
+                       if ((i != j) && (irq[j] == irq[i])) {
+@@ -1115,9 +1333,10 @@ static int bcm2835_dma_probe(struct plat
+               rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags);
+               if (rc)
+                       goto err_no_dma;
++              chan_count++;
+       }
+-      dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);
++      dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", chan_count);
+       /* Device-tree DMA controller registration */
+       rc = of_dma_controller_register(pdev->dev.of_node,
+@@ -1149,6 +1368,13 @@ static int bcm2835_dma_remove(struct pla
+       bcm_dmaman_remove(pdev);
+       dma_async_device_unregister(&od->ddev);
++      if (memcpy_parent == od) {
++              dma_free_coherent(&pdev->dev, sizeof(*memcpy_scb), memcpy_scb,
++                                memcpy_scb_dma);
++              memcpy_parent = NULL;
++              memcpy_scb = NULL;
++              memcpy_chan = NULL;
++      }
+       bcm2835_dma_free(od);
+       return 0;
+--- a/drivers/pci/controller/pcie-brcmstb-bounce.c
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
+@@ -91,7 +91,7 @@ struct dmabounce_device_info {
+ static struct dmabounce_device_info *g_dmabounce_device_info;
+-extern int bcm2838_dma40_memcpy_init(struct device *dev);
++extern int bcm2838_dma40_memcpy_init(void);
+ extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
+ #ifdef STATS
+@@ -471,9 +471,9 @@ static const struct dma_map_ops dmabounc
+       .mapping_error          = dmabounce_mapping_error,
+ };
+-int brcm_pcie_bounce_register_dev(struct device *dev,
+-                                unsigned long buffer_size,
+-                                dma_addr_t threshold)
++int brcm_pcie_bounce_init(struct device *dev,
++                        unsigned long buffer_size,
++                        dma_addr_t threshold)
+ {
+       struct dmabounce_device_info *device_info;
+       int ret;
+@@ -482,9 +482,9 @@ int brcm_pcie_bounce_register_dev(struct
+       if (g_dmabounce_device_info)
+               return -EBUSY;
+-      ret = bcm2838_dma40_memcpy_init(dev);
++      ret = bcm2838_dma40_memcpy_init();
+       if (ret)
+-          return ret;
++              return ret;
+       device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
+       if (!device_info) {
+@@ -515,9 +515,8 @@ int brcm_pcie_bounce_register_dev(struct
+                device_create_file(dev, &dev_attr_dmabounce_stats));
+       g_dmabounce_device_info = device_info;
+-      set_dma_ops(dev, &dmabounce_ops);
+-      dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
++      dev_info(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
+                buffer_size / 1024, &threshold);
+       return 0;
+@@ -526,14 +525,13 @@ int brcm_pcie_bounce_register_dev(struct
+       kfree(device_info);
+       return ret;
+ }
+-EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
++EXPORT_SYMBOL(brcm_pcie_bounce_init);
+-void brcm_pcie_bounce_unregister_dev(struct device *dev)
++void brcm_pcie_bounce_uninit(struct device *dev)
+ {
+       struct dmabounce_device_info *device_info = g_dmabounce_device_info;
+       g_dmabounce_device_info = NULL;
+-      set_dma_ops(dev, NULL);
+       if (!device_info) {
+               dev_warn(dev,
+@@ -554,10 +552,16 @@ void brcm_pcie_bounce_unregister_dev(str
+                        device_remove_file(dev, &dev_attr_dmabounce_stats));
+       kfree(device_info);
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
++
++int brcm_pcie_bounce_register_dev(struct device *dev)
++{
++      set_dma_ops(dev, &dmabounce_ops);
+-      dev_info(dev, "dmabounce: device unregistered\n");
++      return 0;
+ }
+-EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
++EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
+ MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
+ MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
+--- a/drivers/pci/controller/pcie-brcmstb-bounce.h
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
+@@ -8,21 +8,26 @@
+ #ifdef CONFIG_ARM
+-int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
+-                                dma_addr_t threshold);
+-
+-int brcm_pcie_bounce_unregister_dev(struct device *dev);
++int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
++                        dma_addr_t threshold);
++int brcm_pcie_bounce_uninit(struct device *dev);
++int brcm_pcie_bounce_register_dev(struct device *dev);
+ #else
+-static inline int brcm_pcie_bounce_register_dev(struct device *dev,
+-                                              unsigned long buffer_size,
+-                                              dma_addr_t threshold)
++static inline int brcm_pcie_bounce_init(struct device *dev,
++                                      unsigned long buffer_size,
++                                      dma_addr_t threshold)
++{
++      return 0;
++}
++
++static inline int brcm_pcie_bounce_uninit(struct device *dev)
+ {
+       return 0;
+ }
+-static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
++static inline int brcm_pcie_bounce_register_dev(struct device *dev)
+ {
+       return 0;
+ }
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -650,6 +650,7 @@ static void brcm_set_dma_ops(struct devi
+ static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
+                                      unsigned int val);
++
+ static int brcmstb_platform_notifier(struct notifier_block *nb,
+                                    unsigned long event, void *__dev)
+ {
+@@ -663,12 +664,11 @@ static int brcmstb_platform_notifier(str
+                   strcmp(dev->kobj.name, rc_name)) {
+                       int ret;
+-                      ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
+-                                                          (dma_addr_t)bounce_threshold);
++                      ret = brcm_pcie_bounce_register_dev(dev);
+                       if (ret) {
+                               dev_err(dev,
+                                       "brcm_pcie_bounce_register_dev() failed: %d\n",
+-                              ret);
++                                      ret);
+                               return ret;
+                       }
+               }
+@@ -681,8 +681,6 @@ static int brcmstb_platform_notifier(str
+                       brcm_pcie_perst_set(g_pcie, 1);
+                       msleep(100);
+                       brcm_pcie_perst_set(g_pcie, 0);
+-              } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
+-                      brcm_pcie_bounce_unregister_dev(dev);
+               }
+               return NOTIFY_OK;
+@@ -1718,6 +1716,7 @@ static int brcm_pcie_probe(struct platfo
+       void __iomem *base;
+       struct pci_host_bridge *bridge;
+       struct pci_bus *child;
++      extern unsigned long max_pfn;
+       bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
+       if (!bridge)
+@@ -1753,6 +1752,20 @@ static int brcm_pcie_probe(struct platfo
+       if (IS_ERR(base))
+               return PTR_ERR(base);
++      /* To Do: Add hardware check if this ever gets fixed */
++      if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
++              int ret;
++              ret = brcm_pcie_bounce_init(&pdev->dev, bounce_buffer,
++                                          (dma_addr_t)bounce_threshold);
++              if (ret) {
++                      if (ret != -EPROBE_DEFER)
++                              dev_err(&pdev->dev,
++                                      "could not init bounce buffers: %d\n",
++                                      ret);
++                      return ret;
++              }
++      }
++
+       pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
+       if (IS_ERR(pcie->clk)) {
+               dev_warn(&pdev->dev, "could not get clock\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0566-BCM270X_DT-Leave-bulk-channel-in-dma-channel-mask.patch b/target/linux/brcm2708/patches-4.19/950-0566-BCM270X_DT-Leave-bulk-channel-in-dma-channel-mask.patch
new file mode 100644 (file)
index 0000000..20d08ba
--- /dev/null
@@ -0,0 +1,27 @@
+From db81536216256cdd4b8a17879e6628be47c74414 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 5 Jun 2019 21:32:03 +0100
+Subject: [PATCH] BCM270X_DT: Leave bulk channel in dma channel mask
+
+The updated bcm2835-dma driver does not require the BULK channel
+to be removed from the set of available channels, as provided by
+dma-channel-mask.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -124,10 +124,6 @@
+       };
+ };
+-&dma {
+-      brcm,dma-channel-mask = <0x7f34>;
+-};
+-
+ &hdmi {
+       power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0566-arm-dts-Change-downstream-vchiq-compatible-string.patch b/target/linux/brcm2708/patches-4.19/950-0566-arm-dts-Change-downstream-vchiq-compatible-string.patch
deleted file mode 100644 (file)
index 4fda05e..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 00d8817ab207a9f60e94e87acf4f170155aecd48 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 6 Feb 2019 20:45:16 +0000
-Subject: [PATCH] arm: dts: Change downstream vchiq compatible string
-
-The new cache line size mechanism requires a different vchiq compatible
-string on BCM2836 and BCM2837, but the downstream dts files didn't
-inherit the upstream changes.
-
-See: https://github.com/raspberrypi/linux/issues/2643
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 2 +-
- arch/arm/boot/dts/bcm2709-rpi.dtsi | 5 +++++
- arch/arm/boot/dts/bcm2709.dtsi     | 2 +-
- arch/arm/boot/dts/bcm2710.dtsi     | 2 +-
- 4 files changed, 8 insertions(+), 3 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2709-rpi.dtsi
-
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -68,7 +68,7 @@
-                       status = "disabled";
-               };
--              mailbox@7e00b840 {
-+              vchiq: mailbox@7e00b840 {
-                       compatible = "brcm,bcm2835-vchiq";
-                       reg = <0x7e00b840 0x3c>;
-                       interrupts = <0 2>;
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2709-rpi.dtsi
-@@ -0,0 +1,5 @@
-+#include "bcm2708-rpi.dtsi"
-+
-+&vchiq {
-+      compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
-+};
---- a/arch/arm/boot/dts/bcm2709.dtsi
-+++ b/arch/arm/boot/dts/bcm2709.dtsi
-@@ -1,6 +1,6 @@
- #include "bcm2836.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
-+#include "bcm2709-rpi.dtsi"
- / {
-       soc {
---- a/arch/arm/boot/dts/bcm2710.dtsi
-+++ b/arch/arm/boot/dts/bcm2710.dtsi
-@@ -1,6 +1,6 @@
- #include "bcm2837.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
-+#include "bcm2709-rpi.dtsi"
- / {
-       compatible = "brcm,bcm2837", "brcm,bcm2836";
diff --git a/target/linux/brcm2708/patches-4.19/950-0567-SQUASH-bcm2835-dma-Remove-debugging.patch b/target/linux/brcm2708/patches-4.19/950-0567-SQUASH-bcm2835-dma-Remove-debugging.patch
new file mode 100644 (file)
index 0000000..f8d9880
--- /dev/null
@@ -0,0 +1,45 @@
+From eecf4b8568f0a0d6b90364299eed6b12ce63c245 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 6 Jun 2019 09:35:08 +0100
+Subject: [PATCH] SQUASH: bcm2835-dma: Remove debugging
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/dma/bcm2835-dma.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -584,8 +584,6 @@ static void bcm2835_dma_fill_cb_chain_wi
+       dma_addr_t addr;
+       struct scatterlist *sgent;
+-      pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
+-
+       max_len = bcm2835_dma_max_frame_length(c);
+       for_each_sg(sgl, sgent, sg_len, i) {
+               if (c->is_40bit_channel) {
+@@ -603,7 +601,6 @@ static void bcm2835_dma_fill_cb_chain_wi
+                                       scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
+                               }
+                               scb->len = min(len, max_len);
+-                              pr_err("  %llx, %x\n", (u64)addr, scb->len);
+                       }
+               } else {
+                       for (addr = sg_dma_address(sgent),
+@@ -616,7 +613,6 @@ static void bcm2835_dma_fill_cb_chain_wi
+                               else
+                                       cb->cb->src = addr;
+                               cb->cb->length = min(len, max_len);
+-                              pr_err("  %llx, %x\n", (u64)addr, cb->cb->length);
+                       }
+               }
+       }
+@@ -659,7 +655,6 @@ static void bcm2835_dma_start_desc(struc
+       struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
+       struct bcm2835_desc *d;
+-      pr_err("dma_start_desc(%px)\n", vd);
+       if (!vd) {
+               c->desc = NULL;
+               return;
diff --git a/target/linux/brcm2708/patches-4.19/950-0567-bcm2835-dma-Add-proper-40-bit-DMA-support.patch b/target/linux/brcm2708/patches-4.19/950-0567-bcm2835-dma-Add-proper-40-bit-DMA-support.patch
deleted file mode 100644 (file)
index 7ca14c8..0000000
+++ /dev/null
@@ -1,1018 +0,0 @@
-From 621fb1606217c3e72feda69255ae6cb6a7ccfec2 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 4 Apr 2019 13:33:47 +0100
-Subject: [PATCH] bcm2835-dma: Add proper 40-bit DMA support
-
-The 40-bit additions are not fully tested, but it should be
-capable of supporting both 40-bit memcpy on BCM2711 and regular
-Lite channels on BCM2835.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2838.dtsi               |  33 +-
- drivers/dma/bcm2835-dma.c                    | 426 ++++++++++++++-----
- drivers/pci/controller/pcie-brcmstb-bounce.c |  30 +-
- drivers/pci/controller/pcie-brcmstb-bounce.h |  21 +-
- drivers/pci/controller/pcie-brcmstb.c        |  23 +-
- 5 files changed, 395 insertions(+), 138 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -372,6 +372,23 @@
-                       };
-               };
-+              dma40: dma@7e007b00 {
-+                      compatible = "brcm,bcm2838-dma";
-+                      reg = <0x0 0x7e007b00 0x400>;
-+                      interrupts =
-+                              <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
-+                              <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
-+                              <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
-+                              <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
-+                      interrupt-names = "dma11",
-+                              "dma12",
-+                              "dma13",
-+                              "dma14";
-+                      #dma-cells = <1>;
-+                      brcm,dma-channel-mask = <0x7000>;
-+              };
-+              /* DMA4 - 40 bit DMA engines */
-+
-               xhci: xhci@7e9c0000 {
-                       compatible = "generic-xhci";
-                       status = "disabled";
-@@ -689,6 +706,7 @@
- };
- &dma {
-+      reg = <0x7e007000 0xb00>;
-       interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
-               <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
-               <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
-@@ -699,12 +717,7 @@
-               <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  7 */
-               <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  8 */
-               <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite  9 */
--              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
--              /* DMA4 - 40 bit DMA engines */
--              <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4    11 */
--              <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4    12 */
--              <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4    13 */
--              <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4    14 */
-+              <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; /* dmalite 10 */
-       interrupt-names = "dma0",
-                         "dma1",
-                         "dma2",
-@@ -715,10 +728,6 @@
-                         "dma7",
-                         "dma8",
-                         "dma9",
--                        "dma10",
--                        "dma11",
--                        "dma12",
--                        "dma13",
--                        "dma14";
--      brcm,dma-channel-mask = <0x7ef5>;
-+                        "dma10";
-+      brcm,dma-channel-mask = <0x01f5>;
- };
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -50,12 +50,18 @@
- #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
- #define BCM2835_DMA_CHAN_NAME_SIZE 8
- #define BCM2835_DMA_BULK_MASK  BIT(0)
-+#define BCM2838_DMA_MEMCPY_CHAN 14
-+
-+struct bcm2835_dma_cfg_data {
-+      u32     chan_40bit_mask;
-+};
- struct bcm2835_dmadev {
-       struct dma_device ddev;
-       spinlock_t lock;
-       void __iomem *base;
-       struct device_dma_parameters dma_parms;
-+      const struct bcm2835_dma_cfg_data *cfg_data;
- };
- struct bcm2835_dma_cb {
-@@ -100,6 +106,7 @@ struct bcm2835_chan {
-       unsigned int irq_flags;
-       bool is_lite_channel;
-+      bool is_40bit_channel;
- };
- struct bcm2835_desc {
-@@ -189,7 +196,8 @@ struct bcm2835_desc {
- #define BCM2835_DMA_DATA_TYPE_S128    16
- /* Valid only for channels 0 - 14, 15 has its own base address */
--#define BCM2835_DMA_CHAN(n)   ((n) << 8) /* Base address */
-+#define BCM2835_DMA_CHAN_SIZE 0x100
-+#define BCM2835_DMA_CHAN(n)   ((n) * BCM2835_DMA_CHAN_SIZE) /* Base address */
- #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
- /* the max dma length for different channels */
-@@ -200,7 +208,7 @@ struct bcm2835_desc {
- #define BCM2838_DMA40_CS      0x00
- #define BCM2838_DMA40_CB      0x04
- #define BCM2838_DMA40_DEBUG   0x0c
--#define BCM2858_DMA40_TI      0x10
-+#define BCM2838_DMA40_TI      0x10
- #define BCM2838_DMA40_SRC     0x14
- #define BCM2838_DMA40_SRCI    0x18
- #define BCM2838_DMA40_DEST    0x1c
-@@ -209,32 +217,97 @@ struct bcm2835_desc {
- #define BCM2838_DMA40_NEXT_CB 0x28
- #define BCM2838_DMA40_DEBUG2  0x2c
--#define BCM2838_DMA40_CS_ACTIVE       BIT(0)
--#define BCM2838_DMA40_CS_END  BIT(1)
-+#define BCM2838_DMA40_ACTIVE          BIT(0)
-+#define BCM2838_DMA40_END             BIT(1)
-+#define BCM2838_DMA40_INT             BIT(2)
-+#define BCM2838_DMA40_DREQ            BIT(3)  /* DREQ state */
-+#define BCM2838_DMA40_RD_PAUSED               BIT(4)  /* Reading is paused */
-+#define BCM2838_DMA40_WR_PAUSED               BIT(5)  /* Writing is paused */
-+#define BCM2838_DMA40_DREQ_PAUSED     BIT(6)  /* Is paused by DREQ flow control */
-+#define BCM2838_DMA40_WAITING_FOR_WRITES BIT(7)  /* Waiting for last write */
-+#define BCM2838_DMA40_ERR             BIT(10)
-+#define BCM2838_DMA40_QOS(x)          (((x) & 0x1f) << 16)
-+#define BCM2838_DMA40_PANIC_QOS(x)    (((x) & 0x1f) << 20)
-+#define BCM2838_DMA40_WAIT_FOR_WRITES BIT(28)
-+#define BCM2838_DMA40_DISDEBUG                BIT(29)
-+#define BCM2838_DMA40_ABORT           BIT(30)
-+#define BCM2838_DMA40_HALT            BIT(31)
-+#define BCM2838_DMA40_CS_FLAGS(x) (x & (BCM2838_DMA40_QOS(15) | \
-+                                      BCM2838_DMA40_PANIC_QOS(15) | \
-+                                      BCM2838_DMA40_WAIT_FOR_WRITES | \
-+                                      BCM2838_DMA40_DISDEBUG))
-+
-+/* Transfer information bits */
-+#define BCM2838_DMA40_INTEN           BIT(0)
-+#define BCM2838_DMA40_TDMODE          BIT(1) /* 2D-Mode */
-+#define BCM2838_DMA40_WAIT_RESP               BIT(2) /* wait for AXI write to be acked */
-+#define BCM2838_DMA40_WAIT_RD_RESP    BIT(3) /* wait for AXI read to complete */
-+#define BCM2838_DMA40_PER_MAP(x)      ((x & 31) << 9) /* REQ source */
-+#define BCM2838_DMA40_S_DREQ          BIT(14) /* enable SREQ for source */
-+#define BCM2838_DMA40_D_DREQ          BIT(15) /* enable DREQ for destination */
-+#define BCM2838_DMA40_S_WAIT(x)               ((x & 0xff) << 16) /* add DMA read-wait cycles */
-+#define BCM2838_DMA40_D_WAIT(x)               ((x & 0xff) << 24) /* add DMA write-wait cycles */
--#define BCM2838_DMA40_CS_QOS(x)       (((x) & 0x1f) << 16)
--#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
--#define BCM2838_DMA40_CS_WRITE_WAIT   BIT(28)
-+/* debug register bits */
-+#define BCM2838_DMA40_DEBUG_WRITE_ERR         BIT(0)
-+#define BCM2838_DMA40_DEBUG_FIFO_ERR          BIT(1)
-+#define BCM2838_DMA40_DEBUG_READ_ERR          BIT(2)
-+#define BCM2838_DMA40_DEBUG_READ_CB_ERR               BIT(3)
-+#define BCM2838_DMA40_DEBUG_IN_ON_ERR         BIT(8)
-+#define BCM2838_DMA40_DEBUG_ABORT_ON_ERR      BIT(9)
-+#define BCM2838_DMA40_DEBUG_HALT_ON_ERR               BIT(10)
-+#define BCM2838_DMA40_DEBUG_DISABLE_CLK_GATE  BIT(11)
-+#define BCM2838_DMA40_DEBUG_RSTATE_SHIFT      14
-+#define BCM2838_DMA40_DEBUG_RSTATE_BITS               4
-+#define BCM2838_DMA40_DEBUG_WSTATE_SHIFT      18
-+#define BCM2838_DMA40_DEBUG_WSTATE_BITS               4
-+#define BCM2838_DMA40_DEBUG_RESET             BIT(23)
-+#define BCM2838_DMA40_DEBUG_ID_SHIFT          24
-+#define BCM2838_DMA40_DEBUG_ID_BITS           4
-+#define BCM2838_DMA40_DEBUG_VERSION_SHIFT     28
-+#define BCM2838_DMA40_DEBUG_VERSION_BITS      4
-+
-+/* Valid only for channels 0 - 3 (11 - 14) */
-+#define BCM2838_DMA40_CHAN(n) (((n) + 11) << 8) /* Base address */
-+#define BCM2838_DMA40_CHANIO(base, n) ((base) + BCM2838_DMA_CHAN(n))
--#define BCM2838_DMA40_BURST_LEN(x)    ((((x) - 1) & 0xf) << 8)
--#define BCM2838_DMA40_INC             BIT(12)
--#define BCM2838_DMA40_SIZE_128        (2 << 13)
-+/* the max dma length for different channels */
-+#define MAX_DMA40_LEN SZ_1G
--#define BCM2838_DMA40_MEMCPY_QOS \
--      (BCM2838_DMA40_CS_QOS(0x0) | \
--       BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
--       BCM2838_DMA40_CS_WRITE_WAIT)
-+#define BCM2838_DMA40_BURST_LEN(x)    ((min(x,16) - 1) << 8)
-+#define BCM2838_DMA40_INC             BIT(12)
-+#define BCM2838_DMA40_SIZE_32         (0 << 13)
-+#define BCM2838_DMA40_SIZE_64         (1 << 13)
-+#define BCM2838_DMA40_SIZE_128                (2 << 13)
-+#define BCM2838_DMA40_SIZE_256                (3 << 13)
-+#define BCM2838_DMA40_IGNORE          BIT(15)
-+#define BCM2838_DMA40_STRIDE(x)               ((x) << 16) /* For 2D mode */
-+
-+#define BCM2838_DMA40_MEMCPY_FLAGS \
-+      (BCM2838_DMA40_QOS(0) | \
-+       BCM2838_DMA40_PANIC_QOS(0) | \
-+       BCM2838_DMA40_WAIT_FOR_WRITES | \
-+       BCM2838_DMA40_DISDEBUG)
- #define BCM2838_DMA40_MEMCPY_XFER_INFO \
-       (BCM2838_DMA40_SIZE_128 | \
-        BCM2838_DMA40_INC | \
-        BCM2838_DMA40_BURST_LEN(16))
-+struct bcm2835_dmadev *memcpy_parent;
- static void __iomem *memcpy_chan;
- static struct bcm2838_dma40_scb *memcpy_scb;
- static dma_addr_t memcpy_scb_dma;
- DEFINE_SPINLOCK(memcpy_lock);
-+static const struct bcm2835_dma_cfg_data bcm2835_dma_cfg = {
-+      .chan_40bit_mask = 0,
-+};
-+
-+static const struct bcm2835_dma_cfg_data bcm2838_dma_cfg = {
-+      .chan_40bit_mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
-+};
-+
- static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
- {
-       /* lite and normal channels have different max frame length */
-@@ -264,6 +337,32 @@ static inline struct bcm2835_desc *to_bc
-       return container_of(t, struct bcm2835_desc, vd.tx);
- }
-+static inline uint32_t to_bcm2838_ti(uint32_t info)
-+{
-+      return ((info & BCM2835_DMA_INT_EN) ? BCM2838_DMA40_INTEN : 0) |
-+              ((info & BCM2835_DMA_WAIT_RESP) ? BCM2838_DMA40_WAIT_RESP : 0) |
-+              ((info & BCM2835_DMA_S_DREQ) ?
-+               (BCM2838_DMA40_S_DREQ | BCM2838_DMA40_WAIT_RD_RESP) : 0) |
-+              ((info & BCM2835_DMA_D_DREQ) ? BCM2838_DMA40_D_DREQ : 0) |
-+              BCM2838_DMA40_PER_MAP((info >> 16) & 0x1f);
-+}
-+
-+static inline uint32_t to_bcm2838_srci(uint32_t info)
-+{
-+      return ((info & BCM2835_DMA_S_INC) ? BCM2838_DMA40_INC : 0);
-+}
-+
-+static inline uint32_t to_bcm2838_dsti(uint32_t info)
-+{
-+      return ((info & BCM2835_DMA_D_INC) ? BCM2838_DMA40_INC : 0);
-+}
-+
-+static inline uint32_t to_bcm2838_cbaddr(dma_addr_t addr)
-+{
-+      BUG_ON(addr & 0x1f);
-+      return (addr >> 5);
-+}
-+
- static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
- {
-       size_t i;
-@@ -282,45 +381,53 @@ static void bcm2835_dma_desc_free(struct
- }
- static void bcm2835_dma_create_cb_set_length(
--      struct bcm2835_chan *chan,
-+      struct bcm2835_chan *c,
-       struct bcm2835_dma_cb *control_block,
-       size_t len,
-       size_t period_len,
-       size_t *total_len,
-       u32 finalextrainfo)
- {
--      size_t max_len = bcm2835_dma_max_frame_length(chan);
-+      size_t max_len = bcm2835_dma_max_frame_length(c);
-+      uint32_t cb_len;
-       /* set the length taking lite-channel limitations into account */
--      control_block->length = min_t(u32, len, max_len);
-+      cb_len = min_t(u32, len, max_len);
--      /* finished if we have no period_length */
--      if (!period_len)
--              return;
-+      if (period_len) {
-+              /*
-+               * period_len means: that we need to generate
-+               * transfers that are terminating at every
-+               * multiple of period_len - this is typically
-+               * used to set the interrupt flag in info
-+               * which is required during cyclic transfers
-+               */
--      /*
--       * period_len means: that we need to generate
--       * transfers that are terminating at every
--       * multiple of period_len - this is typically
--       * used to set the interrupt flag in info
--       * which is required during cyclic transfers
--       */
-+              /* have we filled in period_length yet? */
-+              if (*total_len + cb_len < period_len) {
-+                      /* update number of bytes in this period so far */
-+                      *total_len += cb_len;
-+              } else {
-+                      /* calculate the length that remains to reach period_len */
-+                      cb_len = period_len - *total_len;
--      /* have we filled in period_length yet? */
--      if (*total_len + control_block->length < period_len) {
--              /* update number of bytes in this period so far */
--              *total_len += control_block->length;
--              return;
-+                      /* reset total_length for next period */
-+                      *total_len = 0;
-+              }
-       }
--      /* calculate the length that remains to reach period_length */
--      control_block->length = period_len - *total_len;
--
--      /* reset total_length for next period */
--      *total_len = 0;
--
--      /* add extrainfo bits in info */
--      control_block->info |= finalextrainfo;
-+      if (c->is_40bit_channel) {
-+              struct bcm2838_dma40_scb *scb =
-+                      (struct bcm2838_dma40_scb *)control_block;
-+
-+              scb->len = cb_len;
-+              /* add extrainfo bits to ti */
-+              scb->ti |= to_bcm2838_ti(finalextrainfo);
-+      } else {
-+              control_block->length = cb_len;
-+              /* add extrainfo bits to info */
-+              control_block->info |= finalextrainfo;
-+      }
- }
- static inline size_t bcm2835_dma_count_frames_for_sg(
-@@ -343,7 +450,7 @@ static inline size_t bcm2835_dma_count_f
- /**
-  * bcm2835_dma_create_cb_chain - create a control block and fills data in
-  *
-- * @chan:           the @dma_chan for which we run this
-+ * @c:              the @bcm2835_chan for which we run this
-  * @direction:      the direction in which we transfer
-  * @cyclic:         it is a cyclic transfer
-  * @info:           the default info bits to apply per controlblock
-@@ -361,12 +468,11 @@ static inline size_t bcm2835_dma_count_f
-  * @gfp:            the GFP flag to use for allocation
-  */
- static struct bcm2835_desc *bcm2835_dma_create_cb_chain(
--      struct dma_chan *chan, enum dma_transfer_direction direction,
-+      struct bcm2835_chan *c, enum dma_transfer_direction direction,
-       bool cyclic, u32 info, u32 finalextrainfo, size_t frames,
-       dma_addr_t src, dma_addr_t dst, size_t buf_len,
-       size_t period_len, gfp_t gfp)
- {
--      struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
-       size_t len = buf_len, total_len;
-       size_t frame;
-       struct bcm2835_desc *d;
-@@ -399,11 +505,23 @@ static struct bcm2835_desc *bcm2835_dma_
-               /* fill in the control block */
-               control_block = cb_entry->cb;
--              control_block->info = info;
--              control_block->src = src;
--              control_block->dst = dst;
--              control_block->stride = 0;
--              control_block->next = 0;
-+              if (c->is_40bit_channel) {
-+                      struct bcm2838_dma40_scb *scb =
-+                              (struct bcm2838_dma40_scb *)control_block;
-+                      scb->ti = to_bcm2838_ti(info);
-+                      scb->src = lower_32_bits(src);
-+                      scb->srci= upper_32_bits(src) | to_bcm2838_srci(info);
-+                      scb->dst = lower_32_bits(dst);
-+                      scb->dsti = upper_32_bits(dst) | to_bcm2838_dsti(info);
-+                      scb->next_cb = 0;
-+              } else {
-+                      control_block->info = info;
-+                      control_block->src = src;
-+                      control_block->dst = dst;
-+                      control_block->stride = 0;
-+                      control_block->next = 0;
-+              }
-+
-               /* set up length in control_block if requested */
-               if (buf_len) {
-                       /* calculate length honoring period_length */
-@@ -417,7 +535,10 @@ static struct bcm2835_desc *bcm2835_dma_
-               }
-               /* link this the last controlblock */
--              if (frame)
-+              if (frame && c->is_40bit_channel)
-+                      d->cb_list[frame - 1].cb->next =
-+                              to_bcm2838_cbaddr(cb_entry->paddr);
-+              if (frame && !c->is_40bit_channel)
-                       d->cb_list[frame - 1].cb->next = cb_entry->paddr;
-               /* update src and dst and length */
-@@ -431,7 +552,14 @@ static struct bcm2835_desc *bcm2835_dma_
-       }
-       /* the last frame requires extra flags */
--      d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
-+      if (c->is_40bit_channel) {
-+              struct bcm2838_dma40_scb *scb =
-+                      (struct bcm2838_dma40_scb *)d->cb_list[d->frames-1].cb;
-+
-+              scb->ti |= to_bcm2838_ti(finalextrainfo);
-+      } else {
-+              d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
-+      }
-       /* detect a size missmatch */
-       if (buf_len && (d->size != buf_len))
-@@ -445,28 +573,51 @@ error_cb:
- }
- static void bcm2835_dma_fill_cb_chain_with_sg(
--      struct dma_chan *chan,
-+      struct bcm2835_chan *c,
-       enum dma_transfer_direction direction,
-       struct bcm2835_cb_entry *cb,
-       struct scatterlist *sgl,
-       unsigned int sg_len)
- {
--      struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
-       size_t len, max_len;
-       unsigned int i;
-       dma_addr_t addr;
-       struct scatterlist *sgent;
-+      pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
-+
-       max_len = bcm2835_dma_max_frame_length(c);
-       for_each_sg(sgl, sgent, sg_len, i) {
--              for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent);
--                   len > 0;
--                   addr += cb->cb->length, len -= cb->cb->length, cb++) {
--                      if (direction == DMA_DEV_TO_MEM)
--                              cb->cb->dst = addr;
--                      else
--                              cb->cb->src = addr;
--                      cb->cb->length = min(len, max_len);
-+              if (c->is_40bit_channel) {
-+                      struct bcm2838_dma40_scb *scb =
-+                              (struct bcm2838_dma40_scb *)cb->cb;
-+                      for (addr = sg_dma_address(sgent),
-+                                   len = sg_dma_len(sgent);
-+                           len > 0;
-+                           addr += scb->len, len -= scb->len, scb++) {
-+                              if (direction == DMA_DEV_TO_MEM) {
-+                                      scb->dst = lower_32_bits(addr);
-+                                      scb->dsti = upper_32_bits(addr) | BCM2838_DMA40_INC;
-+                              } else {
-+                                      scb->src = lower_32_bits(addr);
-+                                      scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
-+                              }
-+                              scb->len = min(len, max_len);
-+                              pr_err("  %llx, %x\n", (u64)addr, scb->len);
-+                      }
-+              } else {
-+                      for (addr = sg_dma_address(sgent),
-+                                   len = sg_dma_len(sgent);
-+                           len > 0;
-+                           addr += cb->cb->length, len -= cb->cb->length,
-+                           cb++) {
-+                              if (direction == DMA_DEV_TO_MEM)
-+                                      cb->cb->dst = addr;
-+                              else
-+                                      cb->cb->src = addr;
-+                              cb->cb->length = min(len, max_len);
-+                              pr_err("  %llx, %x\n", (u64)addr, cb->cb->length);
-+                      }
-               }
-       }
- }
-@@ -475,6 +626,10 @@ static int bcm2835_dma_abort(struct bcm2
- {
-       void __iomem *chan_base = c->chan_base;
-       long int timeout = 10000;
-+      u32 wait_mask = BCM2835_DMA_WAITING_FOR_WRITES;
-+
-+      if (c->is_40bit_channel)
-+              wait_mask = BCM2838_DMA40_WAITING_FOR_WRITES;
-       /*
-        * A zero control block address means the channel is idle.
-@@ -487,8 +642,7 @@ static int bcm2835_dma_abort(struct bcm2
-       writel(0, chan_base + BCM2835_DMA_CS);
-       /* Wait for any current AXI transfer to complete */
--      while ((readl(chan_base + BCM2835_DMA_CS) &
--              BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
-+      while ((readl(chan_base + BCM2835_DMA_CS) & wait_mask) && --timeout)
-               cpu_relax();
-       /* Peripheral might be stuck and fail to signal AXI write responses */
-@@ -505,6 +659,7 @@ static void bcm2835_dma_start_desc(struc
-       struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
-       struct bcm2835_desc *d;
-+      pr_err("dma_start_desc(%px)\n", vd);
-       if (!vd) {
-               c->desc = NULL;
-               return;
-@@ -514,9 +669,16 @@ static void bcm2835_dma_start_desc(struc
-       c->desc = d = to_bcm2835_dma_desc(&vd->tx);
--      writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
--      writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
--             c->chan_base + BCM2835_DMA_CS);
-+      if (c->is_40bit_channel) {
-+              writel(to_bcm2838_cbaddr(d->cb_list[0].paddr),
-+                     c->chan_base + BCM2838_DMA40_CB);
-+              writel(BCM2838_DMA40_ACTIVE | BCM2838_DMA40_CS_FLAGS(c->dreq),
-+                     c->chan_base + BCM2838_DMA40_CS);
-+      } else {
-+              writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
-+              writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
-+                     c->chan_base + BCM2835_DMA_CS);
-+      }
- }
- static irqreturn_t bcm2835_dma_callback(int irq, void *data)
-@@ -544,7 +706,8 @@ static irqreturn_t bcm2835_dma_callback(
-        * will remain idle despite the ACTIVE flag being set.
-        */
-       writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
--             BCM2835_DMA_CS_FLAGS(c->dreq),
-+             (c->is_40bit_channel ? BCM2838_DMA40_CS_FLAGS(c->dreq) :
-+              BCM2835_DMA_CS_FLAGS(c->dreq)),
-              c->chan_base + BCM2835_DMA_CS);
-       d = c->desc;
-@@ -643,9 +806,17 @@ static enum dma_status bcm2835_dma_tx_st
-               struct bcm2835_desc *d = c->desc;
-               dma_addr_t pos;
--              if (d->dir == DMA_MEM_TO_DEV)
-+              if (d->dir == DMA_MEM_TO_DEV && c->is_40bit_channel)
-+                      pos = readl(c->chan_base + BCM2838_DMA40_SRC) +
-+                              ((readl(c->chan_base + BCM2838_DMA40_SRCI) &
-+                                0xff) << 8);
-+              else if (d->dir == DMA_MEM_TO_DEV && !c->is_40bit_channel)
-                       pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD);
--              else if (d->dir == DMA_DEV_TO_MEM)
-+              else if (d->dir == DMA_DEV_TO_MEM && c->is_40bit_channel)
-+                      pos = readl(c->chan_base + BCM2838_DMA40_DEST) +
-+                              ((readl(c->chan_base + BCM2838_DMA40_DESTI) &
-+                                0xff) << 8);
-+              else if (d->dir == DMA_DEV_TO_MEM && !c->is_40bit_channel)
-                       pos = readl(c->chan_base + BCM2835_DMA_DEST_AD);
-               else
-                       pos = 0;
-@@ -691,7 +862,7 @@ static struct dma_async_tx_descriptor *b
-       frames = bcm2835_dma_frames_for_length(len, max_len);
-       /* allocate the CB chain - this also fills in the pointers */
--      d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false,
-+      d = bcm2835_dma_create_cb_chain(c, DMA_MEM_TO_MEM, false,
-                                       info, extra, frames,
-                                       src, dst, len, 0, GFP_KERNEL);
-       if (!d)
-@@ -726,11 +897,21 @@ static struct dma_async_tx_descriptor *b
-               if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
-                       return NULL;
-               src = c->cfg.src_addr;
-+              /*
-+               * One would think it ought to be possible to get the physical
-+               * to dma address mapping information from the dma-ranges DT
-+               * property, but I've not found a way yet that doesn't involve
-+               * open-coding the whole thing.
-+               */
-+              if (c->is_40bit_channel)
-+                  src |= 0x400000000ull;
-               info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
-       } else {
-               if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
-                       return NULL;
-               dst = c->cfg.dst_addr;
-+              if (c->is_40bit_channel)
-+                  dst |= 0x400000000ull;
-               info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
-       }
-@@ -738,7 +919,7 @@ static struct dma_async_tx_descriptor *b
-       frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len);
-       /* allocate the CB chain */
--      d = bcm2835_dma_create_cb_chain(chan, direction, false,
-+      d = bcm2835_dma_create_cb_chain(c, direction, false,
-                                       info, extra,
-                                       frames, src, dst, 0, 0,
-                                       GFP_KERNEL);
-@@ -746,7 +927,7 @@ static struct dma_async_tx_descriptor *b
-               return NULL;
-       /* fill in frames with scatterlist pointers */
--      bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list,
-+      bcm2835_dma_fill_cb_chain_with_sg(c, direction, d->cb_list,
-                                         sgl, sg_len);
-       return vchan_tx_prep(&c->vc, &d->vd, flags);
-@@ -815,7 +996,7 @@ static struct dma_async_tx_descriptor *b
-        * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine
-        * implementation calls prep_dma_cyclic with interrupts disabled.
-        */
--      d = bcm2835_dma_create_cb_chain(chan, direction, true,
-+      d = bcm2835_dma_create_cb_chain(c, direction, true,
-                                       info, extra,
-                                       frames, src, dst, buf_len,
-                                       period_len, GFP_NOWAIT);
-@@ -823,7 +1004,8 @@ static struct dma_async_tx_descriptor *b
-               return NULL;
-       /* wrap around into a loop */
--      d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr;
-+      d->cb_list[d->frames - 1].cb->next = c->is_40bit_channel ?
-+              to_bcm2838_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr;
-       return vchan_tx_prep(&c->vc, &d->vd, flags);
- }
-@@ -899,9 +1081,11 @@ static int bcm2835_dma_chan_init(struct
-       c->irq_number = irq;
-       c->irq_flags = irq_flags;
--      /* check in DEBUG register if this is a LITE channel */
--      if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
--              BCM2835_DMA_DEBUG_LITE)
-+      /* check for 40bit and lite channels */
-+      if (d->cfg_data->chan_40bit_mask & BIT(chan_id))
-+              c->is_40bit_channel = true;
-+      else if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
-+               BCM2835_DMA_DEBUG_LITE)
-               c->is_lite_channel = true;
-       return 0;
-@@ -918,18 +1102,16 @@ static void bcm2835_dma_free(struct bcm2
-       }
- }
--int bcm2838_dma40_memcpy_init(struct device *dev)
-+int bcm2838_dma40_memcpy_init(void)
- {
--      if (memcpy_scb)
--              return 0;
-+      if (!memcpy_parent)
-+              return -EPROBE_DEFER;
--      memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
--                                      &memcpy_scb_dma, GFP_KERNEL);
-+      if (!memcpy_chan)
-+              return -EINVAL;
--      if (!memcpy_scb) {
--              pr_err("bcm2838_dma40_memcpy_init failed!\n");
-+      if (!memcpy_scb)
-               return -ENOMEM;
--      }
-       return 0;
- }
-@@ -956,20 +1138,22 @@ void bcm2838_dma40_memcpy(dma_addr_t dst
-       scb->next_cb = 0;
-       writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
--      writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
-+      writel(BCM2838_DMA40_MEMCPY_FLAGS + BCM2838_DMA40_ACTIVE,
-              memcpy_chan + BCM2838_DMA40_CS);
-+
-       /* Poll for completion */
--      while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
-+      while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_END))
-               cpu_relax();
--      writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
-+      writel(BCM2838_DMA40_END, memcpy_chan + BCM2838_DMA40_CS);
-       spin_unlock_irqrestore(&memcpy_lock, flags);
- }
- EXPORT_SYMBOL(bcm2838_dma40_memcpy);
- static const struct of_device_id bcm2835_dma_of_match[] = {
--      { .compatible = "brcm,bcm2835-dma", },
-+      { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_cfg },
-+      { .compatible = "brcm,bcm2838-dma", .data = &bcm2838_dma_cfg },
-       {},
- };
- MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
-@@ -1001,6 +1185,8 @@ 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;
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-@@ -1022,9 +1208,13 @@ static int bcm2835_dma_probe(struct plat
-       base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
--      rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK);
--      if (rc)
--              dev_err(&pdev->dev, "Failed to initialize the legacy API\n");
-+
-+      /* The set of channels can be split across multiple instances. */
-+      chan_start = ((u32)base / BCM2835_DMA_CHAN_SIZE) & 0xf;
-+      base -= BCM2835_DMA_CHAN(chan_start);
-+      chan_count = resource_size(res) / BCM2835_DMA_CHAN_SIZE;
-+      chan_end = min(chan_start + chan_count,
-+                       BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1);
-       od->base = base;
-@@ -1054,6 +1244,14 @@ static int bcm2835_dma_probe(struct plat
-       platform_set_drvdata(pdev, od);
-+      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;
-+      }
-+
-+      od->cfg_data = of_id->data;
-+
-       /* Request DMA channel mask from device tree */
-       if (of_property_read_u32(pdev->dev.of_node,
-                       "brcm,dma-channel-mask",
-@@ -1063,18 +1261,34 @@ static int bcm2835_dma_probe(struct plat
-               goto err_no_dma;
-       }
--      /* Channel 0 is used by the legacy API */
--      chans_available &= ~BCM2835_DMA_BULK_MASK;
-+      /* One channel is reserved for the legacy API */
-+      if (chans_available & BCM2835_DMA_BULK_MASK) {
-+              rc = bcm_dmaman_probe(pdev, base,
-+                                    chans_available & BCM2835_DMA_BULK_MASK);
-+              if (rc)
-+                      dev_err(&pdev->dev,
-+                              "Failed to initialize the legacy API\n");
-+
-+              chans_available &= ~BCM2835_DMA_BULK_MASK;
-+      }
--      /* We can't use channels 11-13 yet */
--      chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
-+      /* And possibly one for the 40-bit DMA memcpy API */
-+      if (chans_available & od->cfg_data->chan_40bit_mask &
-+          BIT(BCM2838_DMA_MEMCPY_CHAN)) {
-+              memcpy_parent = od;
-+              memcpy_chan = BCM2835_DMA_CHANIO(base, BCM2838_DMA_MEMCPY_CHAN);
-+              memcpy_scb = dma_alloc_coherent(memcpy_parent->ddev.dev,
-+                                              sizeof(*memcpy_scb),
-+                                              &memcpy_scb_dma, GFP_KERNEL);
-+              if (!memcpy_scb)
-+                      dev_warn(&pdev->dev,
-+                               "Failed to allocated memcpy scb\n");
--      /* Grab channel 14 for the 40-bit DMA memcpy */
--      chans_available &= ~BIT(14);
--      memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
-+              chans_available &= ~BIT(BCM2838_DMA_MEMCPY_CHAN);
-+      }
-       /* get irqs for each channel that we support */
--      for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
-+      for (i = chan_start; i < chan_end; i++) {
-               /* skip masked out channels */
-               if (!(chans_available & (1 << i))) {
-                       irq[i] = -1;
-@@ -1097,13 +1311,17 @@ static int bcm2835_dma_probe(struct plat
-               irq[i] = platform_get_irq(pdev, i < 11 ? i : 11);
-       }
-+      chan_count = 0;
-+
-       /* get irqs for each channel */
--      for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
-+      for (i = chan_start; i < chan_end; i++) {
-               /* skip channels without irq */
-               if (irq[i] < 0)
-                       continue;
-               /* check if there are other channels that also use this irq */
-+              /* FIXME: This will fail if interrupts are shared across
-+                 instances */
-               irq_flags = 0;
-               for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
-                       if ((i != j) && (irq[j] == irq[i])) {
-@@ -1115,9 +1333,10 @@ static int bcm2835_dma_probe(struct plat
-               rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags);
-               if (rc)
-                       goto err_no_dma;
-+              chan_count++;
-       }
--      dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);
-+      dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", chan_count);
-       /* Device-tree DMA controller registration */
-       rc = of_dma_controller_register(pdev->dev.of_node,
-@@ -1149,6 +1368,13 @@ static int bcm2835_dma_remove(struct pla
-       bcm_dmaman_remove(pdev);
-       dma_async_device_unregister(&od->ddev);
-+      if (memcpy_parent == od) {
-+              dma_free_coherent(&pdev->dev, sizeof(*memcpy_scb), memcpy_scb,
-+                                memcpy_scb_dma);
-+              memcpy_parent = NULL;
-+              memcpy_scb = NULL;
-+              memcpy_chan = NULL;
-+      }
-       bcm2835_dma_free(od);
-       return 0;
---- a/drivers/pci/controller/pcie-brcmstb-bounce.c
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
-@@ -91,7 +91,7 @@ struct dmabounce_device_info {
- static struct dmabounce_device_info *g_dmabounce_device_info;
--extern int bcm2838_dma40_memcpy_init(struct device *dev);
-+extern int bcm2838_dma40_memcpy_init(void);
- extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
- #ifdef STATS
-@@ -471,9 +471,9 @@ static const struct dma_map_ops dmabounc
-       .mapping_error          = dmabounce_mapping_error,
- };
--int brcm_pcie_bounce_register_dev(struct device *dev,
--                                unsigned long buffer_size,
--                                dma_addr_t threshold)
-+int brcm_pcie_bounce_init(struct device *dev,
-+                        unsigned long buffer_size,
-+                        dma_addr_t threshold)
- {
-       struct dmabounce_device_info *device_info;
-       int ret;
-@@ -482,9 +482,9 @@ int brcm_pcie_bounce_register_dev(struct
-       if (g_dmabounce_device_info)
-               return -EBUSY;
--      ret = bcm2838_dma40_memcpy_init(dev);
-+      ret = bcm2838_dma40_memcpy_init();
-       if (ret)
--          return ret;
-+              return ret;
-       device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
-       if (!device_info) {
-@@ -515,9 +515,8 @@ int brcm_pcie_bounce_register_dev(struct
-                device_create_file(dev, &dev_attr_dmabounce_stats));
-       g_dmabounce_device_info = device_info;
--      set_dma_ops(dev, &dmabounce_ops);
--      dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
-+      dev_info(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
-                buffer_size / 1024, &threshold);
-       return 0;
-@@ -526,14 +525,13 @@ int brcm_pcie_bounce_register_dev(struct
-       kfree(device_info);
-       return ret;
- }
--EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
-+EXPORT_SYMBOL(brcm_pcie_bounce_init);
--void brcm_pcie_bounce_unregister_dev(struct device *dev)
-+void brcm_pcie_bounce_uninit(struct device *dev)
- {
-       struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-       g_dmabounce_device_info = NULL;
--      set_dma_ops(dev, NULL);
-       if (!device_info) {
-               dev_warn(dev,
-@@ -554,10 +552,16 @@ void brcm_pcie_bounce_unregister_dev(str
-                        device_remove_file(dev, &dev_attr_dmabounce_stats));
-       kfree(device_info);
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev)
-+{
-+      set_dma_ops(dev, &dmabounce_ops);
--      dev_info(dev, "dmabounce: device unregistered\n");
-+      return 0;
- }
--EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
-+EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
- MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
- MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
---- a/drivers/pci/controller/pcie-brcmstb-bounce.h
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
-@@ -8,21 +8,26 @@
- #ifdef CONFIG_ARM
--int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
--                                dma_addr_t threshold);
--
--int brcm_pcie_bounce_unregister_dev(struct device *dev);
-+int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
-+                        dma_addr_t threshold);
-+int brcm_pcie_bounce_uninit(struct device *dev);
-+int brcm_pcie_bounce_register_dev(struct device *dev);
- #else
--static inline int brcm_pcie_bounce_register_dev(struct device *dev,
--                                              unsigned long buffer_size,
--                                              dma_addr_t threshold)
-+static inline int brcm_pcie_bounce_init(struct device *dev,
-+                                      unsigned long buffer_size,
-+                                      dma_addr_t threshold)
-+{
-+      return 0;
-+}
-+
-+static inline int brcm_pcie_bounce_uninit(struct device *dev)
- {
-       return 0;
- }
--static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
-+static inline int brcm_pcie_bounce_register_dev(struct device *dev)
- {
-       return 0;
- }
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -650,6 +650,7 @@ static void brcm_set_dma_ops(struct devi
- static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
-                                      unsigned int val);
-+
- static int brcmstb_platform_notifier(struct notifier_block *nb,
-                                    unsigned long event, void *__dev)
- {
-@@ -663,12 +664,11 @@ static int brcmstb_platform_notifier(str
-                   strcmp(dev->kobj.name, rc_name)) {
-                       int ret;
--                      ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
--                                                          (dma_addr_t)bounce_threshold);
-+                      ret = brcm_pcie_bounce_register_dev(dev);
-                       if (ret) {
-                               dev_err(dev,
-                                       "brcm_pcie_bounce_register_dev() failed: %d\n",
--                              ret);
-+                                      ret);
-                               return ret;
-                       }
-               }
-@@ -681,8 +681,6 @@ static int brcmstb_platform_notifier(str
-                       brcm_pcie_perst_set(g_pcie, 1);
-                       msleep(100);
-                       brcm_pcie_perst_set(g_pcie, 0);
--              } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
--                      brcm_pcie_bounce_unregister_dev(dev);
-               }
-               return NOTIFY_OK;
-@@ -1718,6 +1716,7 @@ static int brcm_pcie_probe(struct platfo
-       void __iomem *base;
-       struct pci_host_bridge *bridge;
-       struct pci_bus *child;
-+      extern unsigned long max_pfn;
-       bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
-       if (!bridge)
-@@ -1753,6 +1752,20 @@ static int brcm_pcie_probe(struct platfo
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-+      /* To Do: Add hardware check if this ever gets fixed */
-+      if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
-+              int ret;
-+              ret = brcm_pcie_bounce_init(&pdev->dev, bounce_buffer,
-+                                          (dma_addr_t)bounce_threshold);
-+              if (ret) {
-+                      if (ret != -EPROBE_DEFER)
-+                              dev_err(&pdev->dev,
-+                                      "could not init bounce buffers: %d\n",
-+                                      ret);
-+                      return ret;
-+              }
-+      }
-+
-       pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
-       if (IS_ERR(pcie->clk)) {
-               dev_warn(&pdev->dev, "could not get clock\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0568-BCM270X_DT-Leave-bulk-channel-in-dma-channel-mask.patch b/target/linux/brcm2708/patches-4.19/950-0568-BCM270X_DT-Leave-bulk-channel-in-dma-channel-mask.patch
deleted file mode 100644 (file)
index 20d08ba..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From db81536216256cdd4b8a17879e6628be47c74414 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 5 Jun 2019 21:32:03 +0100
-Subject: [PATCH] BCM270X_DT: Leave bulk channel in dma channel mask
-
-The updated bcm2835-dma driver does not require the BULK channel
-to be removed from the set of available channels, as provided by
-dma-channel-mask.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ----
- 1 file changed, 4 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -124,10 +124,6 @@
-       };
- };
--&dma {
--      brcm,dma-channel-mask = <0x7f34>;
--};
--
- &hdmi {
-       power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0568-dts-Include-CSI-lane-config-for-csi1.patch b/target/linux/brcm2708/patches-4.19/950-0568-dts-Include-CSI-lane-config-for-csi1.patch
new file mode 100644 (file)
index 0000000..74cb946
--- /dev/null
@@ -0,0 +1,23 @@
+From 2fcb94a04778708b13b6d36390000e97063460e6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 31 May 2019 17:57:26 +0100
+Subject: [PATCH] dts: Include CSI lane config for csi1
+
+Without the include the peripheral is configured to have 0
+data lanes, which doesn't allow much data to be passed.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2711.dtsi"
++#include "bcm283x-rpi-csi1-2lane.dtsi"
+ / {
+       compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
diff --git a/target/linux/brcm2708/patches-4.19/950-0569-SQUASH-bcm2835-dma-Remove-debugging.patch b/target/linux/brcm2708/patches-4.19/950-0569-SQUASH-bcm2835-dma-Remove-debugging.patch
deleted file mode 100644 (file)
index f8d9880..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From eecf4b8568f0a0d6b90364299eed6b12ce63c245 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 6 Jun 2019 09:35:08 +0100
-Subject: [PATCH] SQUASH: bcm2835-dma: Remove debugging
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/dma/bcm2835-dma.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -584,8 +584,6 @@ static void bcm2835_dma_fill_cb_chain_wi
-       dma_addr_t addr;
-       struct scatterlist *sgent;
--      pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
--
-       max_len = bcm2835_dma_max_frame_length(c);
-       for_each_sg(sgl, sgent, sg_len, i) {
-               if (c->is_40bit_channel) {
-@@ -603,7 +601,6 @@ static void bcm2835_dma_fill_cb_chain_wi
-                                       scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
-                               }
-                               scb->len = min(len, max_len);
--                              pr_err("  %llx, %x\n", (u64)addr, scb->len);
-                       }
-               } else {
-                       for (addr = sg_dma_address(sgent),
-@@ -616,7 +613,6 @@ static void bcm2835_dma_fill_cb_chain_wi
-                               else
-                                       cb->cb->src = addr;
-                               cb->cb->length = min(len, max_len);
--                              pr_err("  %llx, %x\n", (u64)addr, cb->cb->length);
-                       }
-               }
-       }
-@@ -659,7 +655,6 @@ static void bcm2835_dma_start_desc(struc
-       struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
-       struct bcm2835_desc *d;
--      pr_err("dma_start_desc(%px)\n", vd);
-       if (!vd) {
-               c->desc = NULL;
-               return;
diff --git a/target/linux/brcm2708/patches-4.19/950-0569-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch b/target/linux/brcm2708/patches-4.19/950-0569-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch
new file mode 100644 (file)
index 0000000..6d3da8d
--- /dev/null
@@ -0,0 +1,28 @@
+From ba21a5129def696c154c84df087f07bc748abe7d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 7 Jun 2019 11:31:21 +0100
+Subject: [PATCH] drm/vc4: Fix T-format modifiers in FKMS.
+
+The wrong vc_image formats were being checked for in the switch
+statement. Correct these.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -458,10 +458,10 @@ static void vc4_plane_atomic_update(stru
+       switch (fb->modifier) {
+       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+               switch (mb->plane.vc_image_type) {
+-              case VC_IMAGE_RGBX32:
++              case VC_IMAGE_XRGB8888:
+                       mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
+                       break;
+-              case VC_IMAGE_RGBA32:
++              case VC_IMAGE_ARGB8888:
+                       mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
+                       break;
+               case VC_IMAGE_RGB565:
diff --git a/target/linux/brcm2708/patches-4.19/950-0570-bcm2711-dts-Disable-the-v3d-node-by-default.patch b/target/linux/brcm2708/patches-4.19/950-0570-bcm2711-dts-Disable-the-v3d-node-by-default.patch
new file mode 100644 (file)
index 0000000..eec00db
--- /dev/null
@@ -0,0 +1,23 @@
+From 27fc1dbeee2a58abcb80ffc1c8f161d3abfeac9a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 10 Jun 2019 17:22:44 +0100
+Subject: [PATCH] bcm2711 dts: Disable the v3d node by default
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711.dtsi
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -13,6 +13,10 @@
+       };
+ };
++&v3d {
++      status = "disabled";
++};
++
+ &dma {
+       brcm,dma-channel-mask = <0x7ef5>;
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0570-dts-Include-CSI-lane-config-for-csi1.patch b/target/linux/brcm2708/patches-4.19/950-0570-dts-Include-CSI-lane-config-for-csi1.patch
deleted file mode 100644 (file)
index 74cb946..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 2fcb94a04778708b13b6d36390000e97063460e6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 31 May 2019 17:57:26 +0100
-Subject: [PATCH] dts: Include CSI lane config for csi1
-
-Without the include the peripheral is configured to have 0
-data lanes, which doesn't allow much data to be passed.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2711.dtsi"
-+#include "bcm283x-rpi-csi1-2lane.dtsi"
- / {
-       compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
diff --git a/target/linux/brcm2708/patches-4.19/950-0571-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch b/target/linux/brcm2708/patches-4.19/950-0571-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch
deleted file mode 100644 (file)
index 6d3da8d..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From ba21a5129def696c154c84df087f07bc748abe7d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 7 Jun 2019 11:31:21 +0100
-Subject: [PATCH] drm/vc4: Fix T-format modifiers in FKMS.
-
-The wrong vc_image formats were being checked for in the switch
-statement. Correct these.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -458,10 +458,10 @@ static void vc4_plane_atomic_update(stru
-       switch (fb->modifier) {
-       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
-               switch (mb->plane.vc_image_type) {
--              case VC_IMAGE_RGBX32:
-+              case VC_IMAGE_XRGB8888:
-                       mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
-                       break;
--              case VC_IMAGE_RGBA32:
-+              case VC_IMAGE_ARGB8888:
-                       mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
-                       break;
-               case VC_IMAGE_RGB565:
diff --git a/target/linux/brcm2708/patches-4.19/950-0571-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch b/target/linux/brcm2708/patches-4.19/950-0571-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch
new file mode 100644 (file)
index 0000000..3e3d070
--- /dev/null
@@ -0,0 +1,29 @@
+From d4a180e5b67c3ca9b8559d4f926f22b6c6705082 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 10 Jun 2019 16:32:51 +0100
+Subject: [PATCH] drm/vc4: Remove 340MHz clock limit from FKMS now
+ scrambling issues resolved
+
+Firmware TMDS scrambling is now being correctly configured, so
+we can use it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -830,12 +830,6 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+               break;
+       }
+-      /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
+-       * working.
+-       */
+-      if (mode->clock > 340000)
+-              return MODE_CLOCK_HIGH;
+-
+       return MODE_OK;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0572-bcm2711-dts-Disable-the-v3d-node-by-default.patch b/target/linux/brcm2708/patches-4.19/950-0572-bcm2711-dts-Disable-the-v3d-node-by-default.patch
deleted file mode 100644 (file)
index eec00db..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 27fc1dbeee2a58abcb80ffc1c8f161d3abfeac9a Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 10 Jun 2019 17:22:44 +0100
-Subject: [PATCH] bcm2711 dts: Disable the v3d node by default
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711.dtsi | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/arm/boot/dts/bcm2711.dtsi
-+++ b/arch/arm/boot/dts/bcm2711.dtsi
-@@ -13,6 +13,10 @@
-       };
- };
-+&v3d {
-+      status = "disabled";
-+};
-+
- &dma {
-       brcm,dma-channel-mask = <0x7ef5>;
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0572-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch b/target/linux/brcm2708/patches-4.19/950-0572-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch
new file mode 100644 (file)
index 0000000..99c4e4d
--- /dev/null
@@ -0,0 +1,104 @@
+From f9c01b35ec7ea3f981c414af38c92c508487671a Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 10:55:00 +0100
+Subject: [PATCH] usb: add plumbing for updating interrupt endpoint
+ interval state
+
+xHCI caches device and endpoint data after the interface is configured,
+so an explicit command needs to be issued for any device driver wanting
+to alter the polling interval of an endpoint.
+
+Add usb_fixup_endpoint() to allow drivers to do this. The fixup must be
+called after calculating endpoint bandwidth requirements but before any
+URBs are submitted.
+
+If polling intervals are shortened, any bandwidth reservations are no
+longer valid but in practice polling intervals are only ever relaxed.
+
+Limit the scope to interrupt transfers for now.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/core/hcd.c     | 10 ++++++++++
+ drivers/usb/core/message.c | 15 +++++++++++++++
+ include/linux/usb.h        |  2 ++
+ include/linux/usb/hcd.h    |  7 +++++++
+ 4 files changed, 34 insertions(+)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2071,6 +2071,16 @@ reset:
+       return ret;
+ }
++void usb_hcd_fixup_endpoint(struct usb_device *udev,
++                          struct usb_host_endpoint *ep, int interval)
++{
++      struct usb_hcd *hcd;
++
++      hcd = bus_to_hcd(udev->bus);
++      if (hcd->driver->fixup_endpoint)
++              hcd->driver->fixup_endpoint(hcd, udev, ep, interval);
++}
++
+ /* Disables the endpoint: synchronizes with the hcd to make sure all
+  * endpoint state is gone from hardware.  usb_hcd_flush_endpoint() must
+  * have been called previously.  Use for set_configuration, set_interface,
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1113,6 +1113,21 @@ static void remove_intf_ep_devs(struct u
+       intf->ep_devs_created = 0;
+ }
++void usb_fixup_endpoint(struct usb_device *dev, int epaddr, int interval)
++{
++      unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
++      struct usb_host_endpoint *ep;
++
++      if (usb_endpoint_out(epaddr))
++              ep = dev->ep_out[epnum];
++      else
++              ep = dev->ep_in[epnum];
++
++      if (ep && usb_endpoint_xfer_int(&ep->desc))
++              usb_hcd_fixup_endpoint(dev, ep, interval);
++}
++EXPORT_SYMBOL_GPL(usb_fixup_endpoint);
++
+ /**
+  * usb_disable_endpoint -- Disable an endpoint by address
+  * @dev: the device whose endpoint is being disabled
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1809,6 +1809,8 @@ extern int usb_clear_halt(struct usb_dev
+ extern int usb_reset_configuration(struct usb_device *dev);
+ extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+ extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
++extern void usb_fixup_endpoint(struct usb_device *dev, int epaddr,
++                             int interval);
+ /* this request isn't really synchronous, but it belongs with the others */
+ extern int usb_driver_set_configuration(struct usb_device *udev, int config);
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -379,6 +379,11 @@ struct hc_driver {
+                * or bandwidth constraints.
+                */
+       void    (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
++              /* Override the endpoint-derived interval
++               * (if there is any cached hardware state).
++               */
++      void    (*fixup_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
++                                struct usb_host_endpoint *ep, int interval);
+               /* Returns the hardware-chosen device address */
+       int     (*address_device)(struct usb_hcd *, struct usb_device *udev);
+               /* prepares the hardware to send commands to the device */
+@@ -435,6 +440,8 @@ extern void usb_hcd_unmap_urb_setup_for_
+ extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
+ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
+               struct usb_host_endpoint *ep);
++extern void usb_hcd_fixup_endpoint(struct usb_device *udev,
++              struct usb_host_endpoint *ep, int interval);
+ extern void usb_hcd_disable_endpoint(struct usb_device *udev,
+               struct usb_host_endpoint *ep);
+ extern void usb_hcd_reset_endpoint(struct usb_device *udev,
diff --git a/target/linux/brcm2708/patches-4.19/950-0573-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch b/target/linux/brcm2708/patches-4.19/950-0573-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch
deleted file mode 100644 (file)
index 3e3d070..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From d4a180e5b67c3ca9b8559d4f926f22b6c6705082 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 10 Jun 2019 16:32:51 +0100
-Subject: [PATCH] drm/vc4: Remove 340MHz clock limit from FKMS now
- scrambling issues resolved
-
-Firmware TMDS scrambling is now being correctly configured, so
-we can use it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ------
- 1 file changed, 6 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -830,12 +830,6 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
-               break;
-       }
--      /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
--       * working.
--       */
--      if (mode->clock > 340000)
--              return MODE_CLOCK_HIGH;
--
-       return MODE_OK;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0573-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch b/target/linux/brcm2708/patches-4.19/950-0573-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch
new file mode 100644 (file)
index 0000000..d66b971
--- /dev/null
@@ -0,0 +1,129 @@
+From 903af89ac9a9b82b6e736ab04e3848672a0ab364 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 11:33:39 +0100
+Subject: [PATCH] xhci: implement xhci_fixup_endpoint for interval
+ adjustments
+
+Must be called in a non-atomic context, after the endpoint
+has been registered with the hardware via xhci_add_endpoint
+and before the first URB is submitted for the endpoint.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/xhci.c | 98 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 98 insertions(+)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1425,6 +1425,103 @@ command_cleanup:
+ }
+ /*
++ * RPI: Fixup endpoint intervals when requested
++ * - Check interval versus the (cached) endpoint context
++ * - set the endpoint interval to the new value
++ * - force an endpoint configure command
++ * XXX: bandwidth is not recalculated. We should probably do that.
++ */
++static void xhci_fixup_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
++                              struct usb_host_endpoint *ep, int interval)
++{
++      struct xhci_hcd *xhci;
++      struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
++      struct xhci_command *command;
++      struct xhci_input_control_ctx *ctrl_ctx;
++      struct xhci_virt_device *vdev;
++      int xhci_interval;
++      int ret;
++      int ep_index;
++      unsigned long flags;
++      u32 ep_info_tmp;
++
++      xhci = hcd_to_xhci(hcd);
++      ep_index = xhci_get_endpoint_index(&ep->desc);
++
++      /* FS/LS interval translations */
++      if ((udev->speed == USB_SPEED_FULL ||
++           udev->speed == USB_SPEED_LOW))
++              interval *= 8;
++
++      mutex_lock(&xhci->mutex);
++
++      spin_lock_irqsave(&xhci->lock, flags);
++
++      vdev = xhci->devs[udev->slot_id];
++      /* Get context-derived endpoint interval */
++      ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
++      ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
++      xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
++
++      if (interval == xhci_interval) {
++              spin_unlock_irqrestore(&xhci->lock, flags);
++              mutex_unlock(&xhci->mutex);
++              return;
++      }
++
++      xhci_dbg(xhci, "Fixup interval=%d xhci_interval=%d\n",
++               interval, xhci_interval);
++      command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
++      if (!command) {
++              /* Failure here is benign, poll at the original rate */
++              spin_unlock_irqrestore(&xhci->lock, flags);
++              mutex_unlock(&xhci->mutex);
++              return;
++      }
++
++      /* xHCI uses exponents for intervals... */
++      xhci_interval = fls(interval) - 1;
++      xhci_interval = clamp_val(xhci_interval, 3, 10);
++      ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
++      ep_info_tmp &= ~EP_INTERVAL(255);
++      ep_info_tmp |= EP_INTERVAL(xhci_interval);
++
++      /* Keep the endpoint context up-to-date while issuing the command. */
++      xhci_endpoint_copy(xhci, vdev->in_ctx,
++                         vdev->out_ctx, ep_index);
++      ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
++
++      /*
++       * We need to drop the lock, so take an explicit copy
++       * of the ep context.
++       */
++      xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
++
++      ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
++      if (!ctrl_ctx) {
++              xhci_warn(xhci,
++                        "%s: Could not get input context, bad type.\n",
++                        __func__);
++              spin_unlock_irqrestore(&xhci->lock, flags);
++              xhci_free_command(xhci, command);
++              mutex_unlock(&xhci->mutex);
++              return;
++      }
++      ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
++      ctrl_ctx->drop_flags = 0;
++
++      spin_unlock_irqrestore(&xhci->lock, flags);
++
++      ret = xhci_configure_endpoint(xhci, udev, command,
++                                    false, false);
++      if (ret)
++              xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
++                        __func__, ret);
++      xhci_free_command(xhci, command);
++      mutex_unlock(&xhci->mutex);
++}
++
++/*
+  * non-error returns are a promise to giveback() the urb later
+  * we drop ownership so next owner (or urb unlink) can get it
+  */
+@@ -5217,6 +5314,7 @@ static const struct hc_driver xhci_hc_dr
+       .endpoint_reset =       xhci_endpoint_reset,
+       .check_bandwidth =      xhci_check_bandwidth,
+       .reset_bandwidth =      xhci_reset_bandwidth,
++      .fixup_endpoint =       xhci_fixup_endpoint,
+       .address_device =       xhci_address_device,
+       .enable_device =        xhci_enable_device,
+       .update_hub_device =    xhci_update_hub_device,
diff --git a/target/linux/brcm2708/patches-4.19/950-0574-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch b/target/linux/brcm2708/patches-4.19/950-0574-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch
deleted file mode 100644 (file)
index 99c4e4d..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-From f9c01b35ec7ea3f981c414af38c92c508487671a Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 11 Jun 2019 10:55:00 +0100
-Subject: [PATCH] usb: add plumbing for updating interrupt endpoint
- interval state
-
-xHCI caches device and endpoint data after the interface is configured,
-so an explicit command needs to be issued for any device driver wanting
-to alter the polling interval of an endpoint.
-
-Add usb_fixup_endpoint() to allow drivers to do this. The fixup must be
-called after calculating endpoint bandwidth requirements but before any
-URBs are submitted.
-
-If polling intervals are shortened, any bandwidth reservations are no
-longer valid but in practice polling intervals are only ever relaxed.
-
-Limit the scope to interrupt transfers for now.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/core/hcd.c     | 10 ++++++++++
- drivers/usb/core/message.c | 15 +++++++++++++++
- include/linux/usb.h        |  2 ++
- include/linux/usb/hcd.h    |  7 +++++++
- 4 files changed, 34 insertions(+)
-
---- a/drivers/usb/core/hcd.c
-+++ b/drivers/usb/core/hcd.c
-@@ -2071,6 +2071,16 @@ reset:
-       return ret;
- }
-+void usb_hcd_fixup_endpoint(struct usb_device *udev,
-+                          struct usb_host_endpoint *ep, int interval)
-+{
-+      struct usb_hcd *hcd;
-+
-+      hcd = bus_to_hcd(udev->bus);
-+      if (hcd->driver->fixup_endpoint)
-+              hcd->driver->fixup_endpoint(hcd, udev, ep, interval);
-+}
-+
- /* Disables the endpoint: synchronizes with the hcd to make sure all
-  * endpoint state is gone from hardware.  usb_hcd_flush_endpoint() must
-  * have been called previously.  Use for set_configuration, set_interface,
---- a/drivers/usb/core/message.c
-+++ b/drivers/usb/core/message.c
-@@ -1113,6 +1113,21 @@ static void remove_intf_ep_devs(struct u
-       intf->ep_devs_created = 0;
- }
-+void usb_fixup_endpoint(struct usb_device *dev, int epaddr, int interval)
-+{
-+      unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
-+      struct usb_host_endpoint *ep;
-+
-+      if (usb_endpoint_out(epaddr))
-+              ep = dev->ep_out[epnum];
-+      else
-+              ep = dev->ep_in[epnum];
-+
-+      if (ep && usb_endpoint_xfer_int(&ep->desc))
-+              usb_hcd_fixup_endpoint(dev, ep, interval);
-+}
-+EXPORT_SYMBOL_GPL(usb_fixup_endpoint);
-+
- /**
-  * usb_disable_endpoint -- Disable an endpoint by address
-  * @dev: the device whose endpoint is being disabled
---- a/include/linux/usb.h
-+++ b/include/linux/usb.h
-@@ -1809,6 +1809,8 @@ extern int usb_clear_halt(struct usb_dev
- extern int usb_reset_configuration(struct usb_device *dev);
- extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
- extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
-+extern void usb_fixup_endpoint(struct usb_device *dev, int epaddr,
-+                             int interval);
- /* this request isn't really synchronous, but it belongs with the others */
- extern int usb_driver_set_configuration(struct usb_device *udev, int config);
---- a/include/linux/usb/hcd.h
-+++ b/include/linux/usb/hcd.h
-@@ -379,6 +379,11 @@ struct hc_driver {
-                * or bandwidth constraints.
-                */
-       void    (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
-+              /* Override the endpoint-derived interval
-+               * (if there is any cached hardware state).
-+               */
-+      void    (*fixup_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
-+                                struct usb_host_endpoint *ep, int interval);
-               /* Returns the hardware-chosen device address */
-       int     (*address_device)(struct usb_hcd *, struct usb_device *udev);
-               /* prepares the hardware to send commands to the device */
-@@ -435,6 +440,8 @@ extern void usb_hcd_unmap_urb_setup_for_
- extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
- extern void usb_hcd_flush_endpoint(struct usb_device *udev,
-               struct usb_host_endpoint *ep);
-+extern void usb_hcd_fixup_endpoint(struct usb_device *udev,
-+              struct usb_host_endpoint *ep, int interval);
- extern void usb_hcd_disable_endpoint(struct usb_device *udev,
-               struct usb_host_endpoint *ep);
- extern void usb_hcd_reset_endpoint(struct usb_device *udev,
diff --git a/target/linux/brcm2708/patches-4.19/950-0574-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch b/target/linux/brcm2708/patches-4.19/950-0574-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch
new file mode 100644 (file)
index 0000000..5926319
--- /dev/null
@@ -0,0 +1,23 @@
+From f2c46d48d1aa0f7b87b179434162eac6624122f7 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 11:42:03 +0100
+Subject: [PATCH] usbhid: call usb_fixup_endpoint after mangling
+ intervals
+
+Lets the mousepoll override mechanism work with xhci.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/hid/usbhid/hid-core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1118,6 +1118,7 @@ static int usbhid_start(struct hid_devic
+                               interval = hid_kbpoll_interval;
+                       break;
+               }
++              usb_fixup_endpoint(dev, endpoint->bEndpointAddress, interval);
+               ret = -ENOMEM;
+               if (usb_endpoint_dir_in(endpoint)) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0575-drm-vc4-Add-status-of-which-display-is-updated-throu.patch b/target/linux/brcm2708/patches-4.19/950-0575-drm-vc4-Add-status-of-which-display-is-updated-throu.patch
new file mode 100644 (file)
index 0000000..dd5b284
--- /dev/null
@@ -0,0 +1,85 @@
+From 77ae227664bc2460a5341be765044d0b8fb184ac Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 4 Jun 2019 12:14:30 +0100
+Subject: [PATCH] drm: vc4: Add status of which display is updated
+ through vblank
+
+Previously multiple  displays were slaved off the same SMI
+interrupt, triggered by HVS channel 1 (HDMI0).
+This doesn't work if you only have a DPI or DSI screen (HVS channel
+0), and gives slightly erroneous results with dual HDMI as the
+events for HDMI1 are incorrect.
+
+Use SMIDSW0 and SMIDSW1 registers to denote which display has
+triggered the vblank.
+Handling should be backwards compatible with older firmware.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 41 ++++++++++++++++++++++----
+ 1 file changed, 36 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -230,8 +230,13 @@ static const struct vc_image_format *vc4
+  * hardware, which has only this one register.
+  */
+ #define SMICS 0x0
++#define SMIDSW0 0x14
++#define SMIDSW1 0x1C
+ #define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11))
++/* Flag to denote that the firmware is giving multiple display callbacks */
++#define SMI_NEW 0xabcd0000
++
+ #define vc4_crtc vc4_kms_crtc
+ #define to_vc4_crtc to_vc4_kms_crtc
+ struct vc4_crtc {
+@@ -884,16 +889,42 @@ static irqreturn_t vc4_crtc_irq_handler(
+       int i;
+       u32 stat = readl(crtc_list[0]->regs + SMICS);
+       irqreturn_t ret = IRQ_NONE;
++      u32 chan;
+       if (stat & SMICS_INTERRUPTS) {
+               writel(0, crtc_list[0]->regs + SMICS);
+-              for (i = 0; crtc_list[i]; i++) {
+-                      if (crtc_list[i]->vblank_enabled)
+-                              drm_crtc_handle_vblank(&crtc_list[i]->base);
+-                      vc4_crtc_handle_page_flip(crtc_list[i]);
+-                      ret = IRQ_HANDLED;
++              chan = readl(crtc_list[0]->regs + SMIDSW0);
++
++              if ((chan & 0xFFFF0000) != SMI_NEW) {
++                      /* Older firmware. Treat the one interrupt as vblank/
++                       * complete for all crtcs.
++                       */
++                      for (i = 0; crtc_list[i]; i++) {
++                              if (crtc_list[i]->vblank_enabled)
++                                      drm_crtc_handle_vblank(&crtc_list[i]->base);
++                              vc4_crtc_handle_page_flip(crtc_list[i]);
++                      }
++              } else {
++                      if (chan & 1) {
++                              writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0);
++                              if (crtc_list[0]->vblank_enabled)
++                                      drm_crtc_handle_vblank(&crtc_list[0]->base);
++                              vc4_crtc_handle_page_flip(crtc_list[0]);
++                      }
++
++                      /* Check for the secondary display too */
++                      chan = readl(crtc_list[0]->regs + SMIDSW1);
++
++                      if (chan & 1) {
++                              writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
++                              if (crtc_list[1]->vblank_enabled)
++                                      drm_crtc_handle_vblank(&crtc_list[1]->base);
++                              vc4_crtc_handle_page_flip(crtc_list[1]);
++                      }
+               }
++
++              ret = IRQ_HANDLED;
+       }
+       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0575-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch b/target/linux/brcm2708/patches-4.19/950-0575-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch
deleted file mode 100644 (file)
index d66b971..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-From 903af89ac9a9b82b6e736ab04e3848672a0ab364 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 11 Jun 2019 11:33:39 +0100
-Subject: [PATCH] xhci: implement xhci_fixup_endpoint for interval
- adjustments
-
-Must be called in a non-atomic context, after the endpoint
-has been registered with the hardware via xhci_add_endpoint
-and before the first URB is submitted for the endpoint.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/host/xhci.c | 98 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 98 insertions(+)
-
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -1425,6 +1425,103 @@ command_cleanup:
- }
- /*
-+ * RPI: Fixup endpoint intervals when requested
-+ * - Check interval versus the (cached) endpoint context
-+ * - set the endpoint interval to the new value
-+ * - force an endpoint configure command
-+ * XXX: bandwidth is not recalculated. We should probably do that.
-+ */
-+static void xhci_fixup_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
-+                              struct usb_host_endpoint *ep, int interval)
-+{
-+      struct xhci_hcd *xhci;
-+      struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
-+      struct xhci_command *command;
-+      struct xhci_input_control_ctx *ctrl_ctx;
-+      struct xhci_virt_device *vdev;
-+      int xhci_interval;
-+      int ret;
-+      int ep_index;
-+      unsigned long flags;
-+      u32 ep_info_tmp;
-+
-+      xhci = hcd_to_xhci(hcd);
-+      ep_index = xhci_get_endpoint_index(&ep->desc);
-+
-+      /* FS/LS interval translations */
-+      if ((udev->speed == USB_SPEED_FULL ||
-+           udev->speed == USB_SPEED_LOW))
-+              interval *= 8;
-+
-+      mutex_lock(&xhci->mutex);
-+
-+      spin_lock_irqsave(&xhci->lock, flags);
-+
-+      vdev = xhci->devs[udev->slot_id];
-+      /* Get context-derived endpoint interval */
-+      ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
-+      ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
-+      xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
-+
-+      if (interval == xhci_interval) {
-+              spin_unlock_irqrestore(&xhci->lock, flags);
-+              mutex_unlock(&xhci->mutex);
-+              return;
-+      }
-+
-+      xhci_dbg(xhci, "Fixup interval=%d xhci_interval=%d\n",
-+               interval, xhci_interval);
-+      command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
-+      if (!command) {
-+              /* Failure here is benign, poll at the original rate */
-+              spin_unlock_irqrestore(&xhci->lock, flags);
-+              mutex_unlock(&xhci->mutex);
-+              return;
-+      }
-+
-+      /* xHCI uses exponents for intervals... */
-+      xhci_interval = fls(interval) - 1;
-+      xhci_interval = clamp_val(xhci_interval, 3, 10);
-+      ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
-+      ep_info_tmp &= ~EP_INTERVAL(255);
-+      ep_info_tmp |= EP_INTERVAL(xhci_interval);
-+
-+      /* Keep the endpoint context up-to-date while issuing the command. */
-+      xhci_endpoint_copy(xhci, vdev->in_ctx,
-+                         vdev->out_ctx, ep_index);
-+      ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
-+
-+      /*
-+       * We need to drop the lock, so take an explicit copy
-+       * of the ep context.
-+       */
-+      xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
-+
-+      ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
-+      if (!ctrl_ctx) {
-+              xhci_warn(xhci,
-+                        "%s: Could not get input context, bad type.\n",
-+                        __func__);
-+              spin_unlock_irqrestore(&xhci->lock, flags);
-+              xhci_free_command(xhci, command);
-+              mutex_unlock(&xhci->mutex);
-+              return;
-+      }
-+      ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
-+      ctrl_ctx->drop_flags = 0;
-+
-+      spin_unlock_irqrestore(&xhci->lock, flags);
-+
-+      ret = xhci_configure_endpoint(xhci, udev, command,
-+                                    false, false);
-+      if (ret)
-+              xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
-+                        __func__, ret);
-+      xhci_free_command(xhci, command);
-+      mutex_unlock(&xhci->mutex);
-+}
-+
-+/*
-  * non-error returns are a promise to giveback() the urb later
-  * we drop ownership so next owner (or urb unlink) can get it
-  */
-@@ -5217,6 +5314,7 @@ static const struct hc_driver xhci_hc_dr
-       .endpoint_reset =       xhci_endpoint_reset,
-       .check_bandwidth =      xhci_check_bandwidth,
-       .reset_bandwidth =      xhci_reset_bandwidth,
-+      .fixup_endpoint =       xhci_fixup_endpoint,
-       .address_device =       xhci_address_device,
-       .enable_device =        xhci_enable_device,
-       .update_hub_device =    xhci_update_hub_device,
diff --git a/target/linux/brcm2708/patches-4.19/950-0576-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch b/target/linux/brcm2708/patches-4.19/950-0576-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch
new file mode 100644 (file)
index 0000000..a72f142
--- /dev/null
@@ -0,0 +1,36 @@
+From 5643e47700d3c1b2a8a1aca56629f12e90df407c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:13:21 +0100
+Subject: [PATCH] drm/vc4: In FKMS look at the modifiers correctly for
+ SAND
+
+Incorrect masking was used in the switch for the modifier,
+therefore for SAND (which puts the column pitch in the
+modifier) it didn't match.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ 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
+@@ -460,7 +460,7 @@ static void vc4_plane_atomic_update(stru
+       }
+       mb->plane.planes[3] = 0;
+-      switch (fb->modifier) {
++      switch (fourcc_mod_broadcom_mod(fb->modifier)) {
+       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+               switch (mb->plane.vc_image_type) {
+               case VC_IMAGE_XRGB8888:
+@@ -476,6 +476,9 @@ static void vc4_plane_atomic_update(stru
+               break;
+       case DRM_FORMAT_MOD_BROADCOM_SAND128:
+               mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
++              /* Note that the column pitch is passed across in lines, not
++               * bytes.
++               */
+               mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
+               break;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0576-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch b/target/linux/brcm2708/patches-4.19/950-0576-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch
deleted file mode 100644 (file)
index 5926319..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From f2c46d48d1aa0f7b87b179434162eac6624122f7 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 11 Jun 2019 11:42:03 +0100
-Subject: [PATCH] usbhid: call usb_fixup_endpoint after mangling
- intervals
-
-Lets the mousepoll override mechanism work with xhci.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/hid/usbhid/hid-core.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/hid/usbhid/hid-core.c
-+++ b/drivers/hid/usbhid/hid-core.c
-@@ -1118,6 +1118,7 @@ static int usbhid_start(struct hid_devic
-                               interval = hid_kbpoll_interval;
-                       break;
-               }
-+              usb_fixup_endpoint(dev, endpoint->bEndpointAddress, interval);
-               ret = -ENOMEM;
-               if (usb_endpoint_dir_in(endpoint)) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0577-arm-dts-Fix-Pi4-PWR-LED-configuration.patch b/target/linux/brcm2708/patches-4.19/950-0577-arm-dts-Fix-Pi4-PWR-LED-configuration.patch
new file mode 100644 (file)
index 0000000..34772d5
--- /dev/null
@@ -0,0 +1,29 @@
+From 4d4d714061ee6f54dc5feeaeda4389e2346386aa Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Jun 2019 10:06:55 +0100
+Subject: [PATCH] arm: dts: Fix Pi4 PWR LED configuration
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -126,13 +126,13 @@
+       act_led: act {
+               label = "led0";
+               linux,default-trigger = "mmc0";
+-              gpios = <&gpio 42 0>;
++              gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
+       };
+       pwr_led: pwr {
+               label = "led1";
+-              linux,default-trigger = "input";
+-              gpios = <&expgpio 2 0>;
++              linux,default-trigger = "default-on";
++              gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0577-drm-vc4-Add-status-of-which-display-is-updated-throu.patch b/target/linux/brcm2708/patches-4.19/950-0577-drm-vc4-Add-status-of-which-display-is-updated-throu.patch
deleted file mode 100644 (file)
index dd5b284..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-From 77ae227664bc2460a5341be765044d0b8fb184ac Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 4 Jun 2019 12:14:30 +0100
-Subject: [PATCH] drm: vc4: Add status of which display is updated
- through vblank
-
-Previously multiple  displays were slaved off the same SMI
-interrupt, triggered by HVS channel 1 (HDMI0).
-This doesn't work if you only have a DPI or DSI screen (HVS channel
-0), and gives slightly erroneous results with dual HDMI as the
-events for HDMI1 are incorrect.
-
-Use SMIDSW0 and SMIDSW1 registers to denote which display has
-triggered the vblank.
-Handling should be backwards compatible with older firmware.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 41 ++++++++++++++++++++++----
- 1 file changed, 36 insertions(+), 5 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -230,8 +230,13 @@ static const struct vc_image_format *vc4
-  * hardware, which has only this one register.
-  */
- #define SMICS 0x0
-+#define SMIDSW0 0x14
-+#define SMIDSW1 0x1C
- #define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11))
-+/* Flag to denote that the firmware is giving multiple display callbacks */
-+#define SMI_NEW 0xabcd0000
-+
- #define vc4_crtc vc4_kms_crtc
- #define to_vc4_crtc to_vc4_kms_crtc
- struct vc4_crtc {
-@@ -884,16 +889,42 @@ static irqreturn_t vc4_crtc_irq_handler(
-       int i;
-       u32 stat = readl(crtc_list[0]->regs + SMICS);
-       irqreturn_t ret = IRQ_NONE;
-+      u32 chan;
-       if (stat & SMICS_INTERRUPTS) {
-               writel(0, crtc_list[0]->regs + SMICS);
--              for (i = 0; crtc_list[i]; i++) {
--                      if (crtc_list[i]->vblank_enabled)
--                              drm_crtc_handle_vblank(&crtc_list[i]->base);
--                      vc4_crtc_handle_page_flip(crtc_list[i]);
--                      ret = IRQ_HANDLED;
-+              chan = readl(crtc_list[0]->regs + SMIDSW0);
-+
-+              if ((chan & 0xFFFF0000) != SMI_NEW) {
-+                      /* Older firmware. Treat the one interrupt as vblank/
-+                       * complete for all crtcs.
-+                       */
-+                      for (i = 0; crtc_list[i]; i++) {
-+                              if (crtc_list[i]->vblank_enabled)
-+                                      drm_crtc_handle_vblank(&crtc_list[i]->base);
-+                              vc4_crtc_handle_page_flip(crtc_list[i]);
-+                      }
-+              } else {
-+                      if (chan & 1) {
-+                              writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0);
-+                              if (crtc_list[0]->vblank_enabled)
-+                                      drm_crtc_handle_vblank(&crtc_list[0]->base);
-+                              vc4_crtc_handle_page_flip(crtc_list[0]);
-+                      }
-+
-+                      /* Check for the secondary display too */
-+                      chan = readl(crtc_list[0]->regs + SMIDSW1);
-+
-+                      if (chan & 1) {
-+                              writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
-+                              if (crtc_list[1]->vblank_enabled)
-+                                      drm_crtc_handle_vblank(&crtc_list[1]->base);
-+                              vc4_crtc_handle_page_flip(crtc_list[1]);
-+                      }
-               }
-+
-+              ret = IRQ_HANDLED;
-       }
-       return ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0578-bcm2838.dtsi-Correct-gic400-memory-address-ranges.patch b/target/linux/brcm2708/patches-4.19/950-0578-bcm2838.dtsi-Correct-gic400-memory-address-ranges.patch
new file mode 100644 (file)
index 0000000..75999d0
--- /dev/null
@@ -0,0 +1,23 @@
+From 43420c9bb90d4290e02bbcaa40c19e00fb347615 Mon Sep 17 00:00:00 2001
+From: dp111 <dominic.plunkett@gmail.com>
+Date: Sat, 15 Jun 2019 18:19:50 +0100
+Subject: [PATCH] bcm2838.dtsi : Correct gic400 memory address ranges
+
+It appears to me the addresses for the gic400 are slightly wrong .  See section 3.2 https://static.docs.arm.com/ddi0471/a/DDI0471A_gic400_r0p0_trm.pdf
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -30,8 +30,8 @@
+                       compatible = "arm,gic-400";
+                       reg =   <0x40041000 0x1000>,
+                               <0x40042000 0x2000>,
+-                              <0x40046000 0x2000>,
+-                              <0x40048000 0x2000>;
++                              <0x40044000 0x2000>,
++                              <0x40046000 0x2000>;
+               };
+               thermal: thermal@7d5d2200 {
diff --git a/target/linux/brcm2708/patches-4.19/950-0578-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch b/target/linux/brcm2708/patches-4.19/950-0578-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch
deleted file mode 100644 (file)
index a72f142..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From 5643e47700d3c1b2a8a1aca56629f12e90df407c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 12 Jun 2019 17:13:21 +0100
-Subject: [PATCH] drm/vc4: In FKMS look at the modifiers correctly for
- SAND
-
-Incorrect masking was used in the switch for the modifier,
-therefore for SAND (which puts the column pitch in the
-modifier) it didn't match.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- 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
-@@ -460,7 +460,7 @@ static void vc4_plane_atomic_update(stru
-       }
-       mb->plane.planes[3] = 0;
--      switch (fb->modifier) {
-+      switch (fourcc_mod_broadcom_mod(fb->modifier)) {
-       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
-               switch (mb->plane.vc_image_type) {
-               case VC_IMAGE_XRGB8888:
-@@ -476,6 +476,9 @@ static void vc4_plane_atomic_update(stru
-               break;
-       case DRM_FORMAT_MOD_BROADCOM_SAND128:
-               mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
-+              /* Note that the column pitch is passed across in lines, not
-+               * bytes.
-+               */
-               mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
-               break;
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0579-arm-dts-Fix-Pi4-PWR-LED-configuration.patch b/target/linux/brcm2708/patches-4.19/950-0579-arm-dts-Fix-Pi4-PWR-LED-configuration.patch
deleted file mode 100644 (file)
index 34772d5..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 4d4d714061ee6f54dc5feeaeda4389e2346386aa Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 17 Jun 2019 10:06:55 +0100
-Subject: [PATCH] arm: dts: Fix Pi4 PWR LED configuration
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -126,13 +126,13 @@
-       act_led: act {
-               label = "led0";
-               linux,default-trigger = "mmc0";
--              gpios = <&gpio 42 0>;
-+              gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
-       };
-       pwr_led: pwr {
-               label = "led1";
--              linux,default-trigger = "input";
--              gpios = <&expgpio 2 0>;
-+              linux,default-trigger = "default-on";
-+              gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0579-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch b/target/linux/brcm2708/patches-4.19/950-0579-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch
new file mode 100644 (file)
index 0000000..808fdaf
--- /dev/null
@@ -0,0 +1,51 @@
+From 65a5b304668ed6cb4568ac1a0ffbeabb28208b38 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Jun 2019 12:15:50 +0100
+Subject: [PATCH] staging: vchiq: Use the old dma controller for OF
+ config on platform devices
+
+vchiq on Pi4 is no longer under the soc node, therefore it
+doesn't get the dma-ranges for the VPU.
+
+Switch to using the configuration of the old dma controller as
+that will set the dma-ranges correctly.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../interface/vchiq_arm/vchiq_arm.c             | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3599,6 +3599,7 @@ vchiq_register_child(struct platform_dev
+ {
+       struct platform_device_info pdevinfo;
+       struct platform_device *new_dev;
++      struct device_node *np;
+       memset(&pdevinfo, 0, sizeof(pdevinfo));
+@@ -3612,10 +3613,20 @@ vchiq_register_child(struct platform_dev
+               return NULL;
+       /*
+-       * We want the dma-ranges etc to be copied from the parent VCHIQ device
+-       * to be passed on to the children too.
++       * We want the dma-ranges etc to be copied from a device with the
++       * correct dma-ranges for the VPU.
++       * VCHIQ on Pi4 is now under scb which doesn't get those dma-ranges.
++       * Take the "dma" node as going to be suitable as it sees the world
++       * through the same eyes as the VPU.
+        */
+-      of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
++      np = of_find_node_by_path("dma");
++      if (!np)
++              np = pdev->dev.of_node;
++
++      of_dma_configure(&new_dev->dev, np, true);
++
++      if (np != pdev->dev.of_node)
++              of_node_put(np);
+       return new_dev;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0580-bcm2838.dtsi-Correct-gic400-memory-address-ranges.patch b/target/linux/brcm2708/patches-4.19/950-0580-bcm2838.dtsi-Correct-gic400-memory-address-ranges.patch
deleted file mode 100644 (file)
index 75999d0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 43420c9bb90d4290e02bbcaa40c19e00fb347615 Mon Sep 17 00:00:00 2001
-From: dp111 <dominic.plunkett@gmail.com>
-Date: Sat, 15 Jun 2019 18:19:50 +0100
-Subject: [PATCH] bcm2838.dtsi : Correct gic400 memory address ranges
-
-It appears to me the addresses for the gic400 are slightly wrong .  See section 3.2 https://static.docs.arm.com/ddi0471/a/DDI0471A_gic400_r0p0_trm.pdf
----
- arch/arm/boot/dts/bcm2838.dtsi | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -30,8 +30,8 @@
-                       compatible = "arm,gic-400";
-                       reg =   <0x40041000 0x1000>,
-                               <0x40042000 0x2000>,
--                              <0x40046000 0x2000>,
--                              <0x40048000 0x2000>;
-+                              <0x40044000 0x2000>,
-+                              <0x40046000 0x2000>;
-               };
-               thermal: thermal@7d5d2200 {
diff --git a/target/linux/brcm2708/patches-4.19/950-0580-drm-vc4-Limit-fkms-to-modes-85Hz.patch b/target/linux/brcm2708/patches-4.19/950-0580-drm-vc4-Limit-fkms-to-modes-85Hz.patch
new file mode 100644 (file)
index 0000000..b95a4db
--- /dev/null
@@ -0,0 +1,26 @@
+From 06a0e398e7dcd6ba0a61713596c32ec6d43b47c8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Jun 2019 21:37:45 +0100
+Subject: [PATCH] drm/vc4: Limit fkms to modes <= 85Hz
+
+Selecting 1080p100 and 120 has very limited gain, but don't want
+to block VGA85 and similar.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -822,6 +822,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)
++              return MODE_BAD_VVALUE;
++
+       /* Limit the pixel clock based on the HDMI clock limits from the
+        * firmware
+        */
diff --git a/target/linux/brcm2708/patches-4.19/950-0581-arm-bcm2835-Add-bcm2838-compatible-string.patch b/target/linux/brcm2708/patches-4.19/950-0581-arm-bcm2835-Add-bcm2838-compatible-string.patch
new file mode 100644 (file)
index 0000000..1099608
--- /dev/null
@@ -0,0 +1,20 @@
+From aca60a3944ff6a4da66e96d9ae54f4bca271b600 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 11 Jun 2019 17:38:28 +0100
+Subject: [PATCH] arm: bcm2835: Add bcm2838 compatible string.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -118,6 +118,7 @@ static const char * const bcm2835_compat
+ #ifdef CONFIG_ARCH_MULTI_V7
+       "brcm,bcm2836",
+       "brcm,bcm2837",
++      "brcm,bcm2838",
+ #endif
+       NULL
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0581-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch b/target/linux/brcm2708/patches-4.19/950-0581-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch
deleted file mode 100644 (file)
index 808fdaf..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From 65a5b304668ed6cb4568ac1a0ffbeabb28208b38 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Jun 2019 12:15:50 +0100
-Subject: [PATCH] staging: vchiq: Use the old dma controller for OF
- config on platform devices
-
-vchiq on Pi4 is no longer under the soc node, therefore it
-doesn't get the dma-ranges for the VPU.
-
-Switch to using the configuration of the old dma controller as
-that will set the dma-ranges correctly.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../interface/vchiq_arm/vchiq_arm.c             | 17 ++++++++++++++---
- 1 file changed, 14 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -3599,6 +3599,7 @@ vchiq_register_child(struct platform_dev
- {
-       struct platform_device_info pdevinfo;
-       struct platform_device *new_dev;
-+      struct device_node *np;
-       memset(&pdevinfo, 0, sizeof(pdevinfo));
-@@ -3612,10 +3613,20 @@ vchiq_register_child(struct platform_dev
-               return NULL;
-       /*
--       * We want the dma-ranges etc to be copied from the parent VCHIQ device
--       * to be passed on to the children too.
-+       * We want the dma-ranges etc to be copied from a device with the
-+       * correct dma-ranges for the VPU.
-+       * VCHIQ on Pi4 is now under scb which doesn't get those dma-ranges.
-+       * Take the "dma" node as going to be suitable as it sees the world
-+       * through the same eyes as the VPU.
-        */
--      of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
-+      np = of_find_node_by_path("dma");
-+      if (!np)
-+              np = pdev->dev.of_node;
-+
-+      of_dma_configure(&new_dev->dev, np, true);
-+
-+      if (np != pdev->dev.of_node)
-+              of_node_put(np);
-       return new_dev;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0582-arm-dts-Improve-the-bcm27xx-inclusion-hierarchy.patch b/target/linux/brcm2708/patches-4.19/950-0582-arm-dts-Improve-the-bcm27xx-inclusion-hierarchy.patch
new file mode 100644 (file)
index 0000000..875d891
--- /dev/null
@@ -0,0 +1,490 @@
+From d27f2b90df0b787859c2f5665feaecbe87e6b1ff Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 4 Jun 2019 16:22:22 +0100
+Subject: [PATCH] arm: dts: Improve the bcm27xx inclusion hierarchy
+
+1) The top-level .dts files now include parallel chains of bcm27xx.dtsi
+   and bcm27xx-rpi.dtsi files, with no cross-inclusion between the two
+   chains.
+
+2) Move definitions and deletions to the point of maximum commonality
+   to reduce redundancy.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi-b-plus.dts   |  1 +
+ arch/arm/boot/dts/bcm2708-rpi-b.dts        |  1 +
+ arch/arm/boot/dts/bcm2708-rpi-cm.dtsi      |  1 +
+ arch/arm/boot/dts/bcm2708-rpi-zero-w.dts   |  1 +
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts     |  1 +
+ arch/arm/boot/dts/bcm2708-rpi.dtsi         | 63 +++++++---------------
+ arch/arm/boot/dts/bcm2708.dtsi             |  1 -
+ arch/arm/boot/dts/bcm2709-rpi-2-b.dts      |  1 +
+ arch/arm/boot/dts/bcm2709.dtsi             |  1 -
+ arch/arm/boot/dts/bcm270x.dtsi             | 18 +------
+ 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/bcm2710-rpi-cm3.dts      |  1 +
+ arch/arm/boot/dts/bcm2710.dtsi             |  1 -
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts      | 15 ++++--
+ arch/arm/boot/dts/bcm2711-rpi.dtsi         |  7 +++
+ arch/arm/boot/dts/bcm2711.dtsi             | 10 ----
+ arch/arm/boot/dts/bcm2835-rpi.dtsi         | 16 ++++++
+ arch/arm/boot/dts/bcm2838.dtsi             | 33 ++++++++----
+ arch/arm/boot/dts/bcm283x.dtsi             |  2 +-
+ 20 files changed, 86 insertions(+), 90 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2711-rpi.dtsi
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9512.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
+@@ -1,4 +1,5 @@
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+ &leds {
+       act_led: act {
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ / {
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ / {
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -1,6 +1,6 @@
+-/* Downstream version of bcm2835-rpi.dtsi */
++/* Downstream modifications to bcm2835-rpi.dtsi */
+-#include <dt-bindings/power/raspberrypi-power.h>
++#include "bcm2835-rpi.dtsi"
+ / {
+       memory {
+@@ -49,29 +49,10 @@
+                       reg = <0x7e200000 0x1000>;
+               };
+-              firmware: firmware {
+-                      compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
+-                      #address-cells = <0>;
+-                      #size-cells = <0>;
+-                      mboxes = <&mailbox>;
+-              };
+-
+-              power: power {
+-                      compatible = "raspberrypi,bcm2835-power";
+-                      firmware = <&firmware>;
+-                      #power-domain-cells = <1>;
+-              };
+-
+               fb: fb {
+                       compatible = "brcm,bcm2708-fb";
+                       firmware = <&firmware>;
+-                      status = "disabled";
+-              };
+-
+-              vchiq: mailbox@7e00b840 {
+-                      compatible = "brcm,bcm2835-vchiq";
+-                      reg = <0x7e00b840 0x3c>;
+-                      interrupts = <0 2>;
++                      status = "okay";
+               };
+               vcsm: vcsm {
+@@ -91,10 +72,6 @@
+               sound: sound {
+                       status = "disabled";
+               };
+-
+-              txp: txp@7e004000 {
+-                      status = "disabled";
+-              };
+       };
+       __overrides__ {
+@@ -125,11 +102,23 @@
+ };
+ &hdmi {
+-      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "disabled";
+ };
+-&usb {
+-      power-domains = <&power RPI_POWER_DOMAIN_USB>;
++&txp {
++      status = "disabled";
++};
++
++&i2c0 {
++      status = "disabled";
++};
++
++&i2c1 {
++      status = "disabled";
++};
++
++&i2c2 {
++      status = "disabled";
+ };
+ &clocks {
+@@ -141,16 +130,8 @@ sdhost_pins: &sdhost_gpio48 {
+ };
+ &sdhost {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&sdhost_gpio48>;
+-      bus-width = <4>;
+       brcm,overclock-50 = <0>;
+       brcm,pio-limit = <1>;
+-      status = "okay";
+-};
+-
+-&fb {
+-      status = "okay";
+ };
+ &cpu_thermal {
+@@ -160,11 +141,3 @@ sdhost_pins: &sdhost_gpio48 {
+ &vec {
+       status = "disabled";
+ };
+-
+-&csi0 {
+-      power-domains = <&power RPI_POWER_DOMAIN_UNICAM0>;
+-};
+-
+-&csi1 {
+-      power-domains = <&power RPI_POWER_DOMAIN_UNICAM1>;
+-};
+--- a/arch/arm/boot/dts/bcm2708.dtsi
++++ b/arch/arm/boot/dts/bcm2708.dtsi
+@@ -1,6 +1,5 @@
+ #include "bcm2835.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
+ / {
+       /delete-node/ cpus;
+--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2709.dtsi"
++#include "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+--- a/arch/arm/boot/dts/bcm2709.dtsi
++++ b/arch/arm/boot/dts/bcm2709.dtsi
+@@ -1,6 +1,5 @@
+ #include "bcm2836.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2709-rpi.dtsi"
+ / {
+       soc {
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -68,7 +68,7 @@
+               /delete-node/ sdhci@7e300000;
+-              mmc: mmc@7e300000 {
++              sdhci: mmc: mmc@7e300000 {
+                       compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
+                       reg = <0x7e300000 0x100>;
+                       interrupts = <2 30>;
+@@ -152,22 +152,6 @@
+               };
+       };
+-      vdd_5v0_reg: fixedregulator_5v0 {
+-              compatible = "regulator-fixed";
+-              regulator-name = "5v0";
+-              regulator-min-microvolt = <5000000>;
+-              regulator-max-microvolt = <5000000>;
+-              regulator-always-on;
+-      };
+-
+-      vdd_3v3_reg: fixedregulator_3v3 {
+-              compatible = "regulator-fixed";
+-              regulator-name = "3v3";
+-              regulator-min-microvolt = <3300000>;
+-              regulator-max-microvolt = <3300000>;
+-              regulator-always-on;
+-      };
+-
+       __overrides__ {
+               cam0-pwdn-ctrl;
+               cam0-pwdn;
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2710.dtsi"
++#include "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-lan7515.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2710.dtsi"
++#include "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+ #include "bcm2710.dtsi"
++#include "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-csi0-2lane.dtsi"
+ #include "bcm283x-rpi-csi1-4lane.dtsi"
+--- a/arch/arm/boot/dts/bcm2710.dtsi
++++ b/arch/arm/boot/dts/bcm2710.dtsi
+@@ -1,6 +1,5 @@
+ #include "bcm2837.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2709-rpi.dtsi"
+ / {
+       compatible = "brcm,bcm2837", "brcm,bcm2836";
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -1,13 +1,12 @@
+ /dts-v1/;
+ #include "bcm2711.dtsi"
++#include "bcm2711-rpi.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ / {
+-      compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
++      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
+       model = "Raspberry Pi 4 Model B";
+-      #address-cells = <2>;
+-      #size-cells = <1>;
+       memory {
+               device_type = "memory";
+@@ -48,10 +47,18 @@
+ };
+ &firmware {
+-      expgpio: expgpio {
++      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",
++                                "",
++                                "";
+               status = "okay";
+       };
+ };
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -0,0 +1,7 @@
++#include "bcm2708-rpi.dtsi"
++#include "bcm2838-rpi.dtsi"
++
++&v3d {
++     /* Undo the overwriting by bcm270x.dtsi */
++     power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
++};
+--- a/arch/arm/boot/dts/bcm2711.dtsi
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -1,10 +1,8 @@
+ #include "bcm2838.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
+ / {
+       soc {
+-              /delete-node/ mailbox@7e00b840;
+               /delete-node/ v3d@7ec00000;
+       };
+@@ -17,14 +15,6 @@
+       status = "disabled";
+ };
+-&dma {
+-      brcm,dma-channel-mask = <0x7ef5>;
+-};
+-
+-&txp {
+-      interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+-};
+-
+ &firmwarekms {
+       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ };
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -36,6 +36,22 @@
+                       interrupts = <0 2>;
+               };
+       };
++
++      vdd_3v3_reg: fixedregulator_3v3 {
++              compatible = "regulator-fixed";
++              regulator-name = "3v3";
++              regulator-min-microvolt = <3300000>;
++              regulator-max-microvolt = <3300000>;
++              regulator-always-on;
++      };
++
++      vdd_5v0_reg: fixedregulator_5v0 {
++              compatible = "regulator-fixed";
++              regulator-name = "5v0";
++              regulator-min-microvolt = <5000000>;
++              regulator-max-microvolt = <5000000>;
++              regulator-always-on;
++      };
+ };
+ &gpio {
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -5,7 +5,10 @@
+ #include <dt-bindings/soc/bcm2835-pm.h>
+ / {
+-      compatible = "brcm,bcm2838", "brcm,bcm2837";
++      compatible = "brcm,bcm2838";
++
++      #address-cells = <2>;
++      #size-cells = <1>;
+       interrupt-parent = <&gicv2>;
+@@ -16,8 +19,8 @@
+               /* Emulate a contiguous 30-bit address range for DMA */
+               dma-ranges = <0xc0000000  0x0 0x00000000  0x3c000000>;
+-              /delete-node/ mailbox@7e00b840;
+               /delete-node/ interrupt-controller@7e00f300;
++              /delete-node/ v3d@7ec00000;
+               local_intc: local_intc@40000000 {
+                       compatible = "brcm,bcm2836-l1-intc";
+@@ -191,6 +194,16 @@
+                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+               };
++              pwm1: pwm@7e20c800 {
++                      compatible = "brcm,bcm2835-pwm";
++                      reg = <0x7e20c800 0x28>;
++                      clocks = <&clocks BCM2835_CLOCK_PWM>;
++                      assigned-clocks = <&clocks BCM2835_CLOCK_PWM>;
++                      assigned-clock-rates = <10000000>;
++                      #pwm-cells = <2>;
++                      status = "disabled";
++              };
++
+               emmc2: emmc2@7e340000 {
+                       compatible = "brcm,bcm2711-emmc2";
+                       status = "okay";
+@@ -385,7 +398,7 @@
+                               "dma13",
+                               "dma14";
+                       #dma-cells = <1>;
+-                      brcm,dma-channel-mask = <0x7000>;
++                      brcm,dma-channel-mask = <0x7800>;
+               };
+               /* DMA4 - 40 bit DMA engines */
+@@ -396,12 +409,6 @@
+                       interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+               };
+-              vchiq: mailbox@7e00b840 {
+-                      compatible = "brcm,bcm2838-vchiq";
+-                      reg = <0 0x7e00b840 0x3c>;
+-                      interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+-              };
+-
+               hevc-decoder@7eb00000 {
+                       compatible = "raspberrypi,argon-hevc-decoder";
+                       reg = <0x0 0x7eb00000 0x10000>;
+@@ -450,6 +457,8 @@
+ };
+ &gpio {
++      compatible = "brcm,bcm2838-gpio", "brcm,bcm2835-gpio";
++
+       gpclk0_gpio49: gpclk0_gpio49 {
+               brcm,pins = <49>;
+               brcm,function = <BCM2835_FSEL_ALT1>;
+@@ -729,5 +738,9 @@
+                         "dma8",
+                         "dma9",
+                         "dma10";
+-      brcm,dma-channel-mask = <0x01f5>;
++      brcm,dma-channel-mask = <0x07f5>;
++};
++
++&txp {
++      interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ };
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -55,7 +55,7 @@
+               #address-cells = <1>;
+               #size-cells = <1>;
+-              txp@7e004000 {
++              txp: txp@7e004000 {
+                       compatible = "brcm,bcm2835-txp";
+                       reg = <0x7e004000 0x20>;
+                       interrupts = <1 11>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0582-drm-vc4-Limit-fkms-to-modes-85Hz.patch b/target/linux/brcm2708/patches-4.19/950-0582-drm-vc4-Limit-fkms-to-modes-85Hz.patch
deleted file mode 100644 (file)
index b95a4db..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 06a0e398e7dcd6ba0a61713596c32ec6d43b47c8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Jun 2019 21:37:45 +0100
-Subject: [PATCH] drm/vc4: Limit fkms to modes <= 85Hz
-
-Selecting 1080p100 and 120 has very limited gain, but don't want
-to block VGA85 and similar.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -822,6 +822,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)
-+              return MODE_BAD_VVALUE;
-+
-       /* Limit the pixel clock based on the HDMI clock limits from the
-        * firmware
-        */
diff --git a/target/linux/brcm2708/patches-4.19/950-0583-arm-bcm2835-Add-bcm2838-compatible-string.patch b/target/linux/brcm2708/patches-4.19/950-0583-arm-bcm2835-Add-bcm2838-compatible-string.patch
deleted file mode 100644 (file)
index 1099608..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From aca60a3944ff6a4da66e96d9ae54f4bca271b600 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 11 Jun 2019 17:38:28 +0100
-Subject: [PATCH] arm: bcm2835: Add bcm2838 compatible string.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/mach-bcm/board_bcm2835.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -118,6 +118,7 @@ static const char * const bcm2835_compat
- #ifdef CONFIG_ARCH_MULTI_V7
-       "brcm,bcm2836",
-       "brcm,bcm2837",
-+      "brcm,bcm2838",
- #endif
-       NULL
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0583-arm-dts-First-draft-of-upstream-Pi4-DTS.patch b/target/linux/brcm2708/patches-4.19/950-0583-arm-dts-First-draft-of-upstream-Pi4-DTS.patch
new file mode 100644 (file)
index 0000000..0fa4cf3
--- /dev/null
@@ -0,0 +1,176 @@
+From 5216bb8a1257a8216362affe4757a96a36b60b32 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 11 Jun 2019 18:08:05 +0100
+Subject: [PATCH] arm: dts: First draft of upstream Pi4 DTS
+
+I've attempted to follow the upstream conventions in the DT commits,
+but this is just presented here initially as a talking point.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile            |   1 +
+ arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 118 ++++++++++++++++++++++++++
+ arch/arm/boot/dts/bcm2838-rpi.dtsi    |  25 ++++++
+ 3 files changed, 144 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2838-rpi-4-b.dts
+ create mode 100644 arch/arm/boot/dts/bcm2838-rpi.dtsi
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -94,6 +94,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2836-rpi-2-b.dtb \
+       bcm2837-rpi-3-b.dtb \
+       bcm2837-rpi-3-b-plus.dtb \
++      bcm2838-rpi-4-b.dtb \
+       bcm2835-rpi-zero.dtb \
+       bcm2835-rpi-zero-w.dtb
+ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
+@@ -0,0 +1,118 @@
++// SPDX-License-Identifier: GPL-2.0
++/dts-v1/;
++#include "bcm2838.dtsi"
++#include "bcm2835-rpi.dtsi"
++#include "bcm2838-rpi.dtsi"
++
++/ {
++      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
++      model = "Raspberry Pi 4 Model B";
++
++      chosen {
++              /* 8250 auxiliary UART instead of pl011 */
++              stdout-path = "serial1:115200n8";
++      };
++
++      memory {
++              reg = <0 0 0x40000000>;
++      };
++
++      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 {
++              status = "okay";
++              compatible = "regulator-gpio";
++              vin-supply = <&vdd_5v0_reg>;
++              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>;
++      };
++};
++
++&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",
++                                "",
++                                "";
++              status = "okay";
++      };
++};
++
++&pwm1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&pwm0_gpio40 &pwm1_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>;
++      status = "okay";
++      bus-width = <4>;
++      non-removable;
++      mmc-pwrseq = <&wifi_pwrseq>;
++
++      brcmf: wifi@1 {
++              reg = <1>;
++              compatible = "brcm,bcm4329-fmac";
++      };
++};
++
++/* EMMC2 is used to drive the SD card */
++&emmc2 {
++      status = "okay";
++      broken-cd;
++      vqmmc-supply = <&sd_io_1v8_reg>;
++};
++
++/* uart0 communicates with the BT module */
++&uart0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32 &gpclk2_gpio43>;
++      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";
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2838-rpi.dtsi
+@@ -0,0 +1,25 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/ {
++      soc {
++              /delete-node/ mailbox@7e00b840;
++      };
++};
++
++&scb {
++      vchiq: mailbox@7e00b840 {
++              compatible = "brcm,bcm2838-vchiq";
++              reg = <0 0x7e00b840 0x3c>;
++              interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
++      };
++};
++
++&dma {
++      /* The VPU firmware uses DMA channel 11 for VCHIQ */
++      brcm,dma-channel-mask = <0x1f5>;
++};
++
++&dma40 {
++      /* The VPU firmware DMA channel 11 for VCHIQ */
++      brcm,dma-channel-mask = <0x7000>;
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0584-arm-dts-Improve-the-bcm27xx-inclusion-hierarchy.patch b/target/linux/brcm2708/patches-4.19/950-0584-arm-dts-Improve-the-bcm27xx-inclusion-hierarchy.patch
deleted file mode 100644 (file)
index 875d891..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-From d27f2b90df0b787859c2f5665feaecbe87e6b1ff Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 4 Jun 2019 16:22:22 +0100
-Subject: [PATCH] arm: dts: Improve the bcm27xx inclusion hierarchy
-
-1) The top-level .dts files now include parallel chains of bcm27xx.dtsi
-   and bcm27xx-rpi.dtsi files, with no cross-inclusion between the two
-   chains.
-
-2) Move definitions and deletions to the point of maximum commonality
-   to reduce redundancy.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi-b-plus.dts   |  1 +
- arch/arm/boot/dts/bcm2708-rpi-b.dts        |  1 +
- arch/arm/boot/dts/bcm2708-rpi-cm.dtsi      |  1 +
- arch/arm/boot/dts/bcm2708-rpi-zero-w.dts   |  1 +
- arch/arm/boot/dts/bcm2708-rpi-zero.dts     |  1 +
- arch/arm/boot/dts/bcm2708-rpi.dtsi         | 63 +++++++---------------
- arch/arm/boot/dts/bcm2708.dtsi             |  1 -
- arch/arm/boot/dts/bcm2709-rpi-2-b.dts      |  1 +
- arch/arm/boot/dts/bcm2709.dtsi             |  1 -
- arch/arm/boot/dts/bcm270x.dtsi             | 18 +------
- 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/bcm2710-rpi-cm3.dts      |  1 +
- arch/arm/boot/dts/bcm2710.dtsi             |  1 -
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts      | 15 ++++--
- arch/arm/boot/dts/bcm2711-rpi.dtsi         |  7 +++
- arch/arm/boot/dts/bcm2711.dtsi             | 10 ----
- arch/arm/boot/dts/bcm2835-rpi.dtsi         | 16 ++++++
- arch/arm/boot/dts/bcm2838.dtsi             | 33 ++++++++----
- arch/arm/boot/dts/bcm283x.dtsi             |  2 +-
- 20 files changed, 86 insertions(+), 90 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2711-rpi.dtsi
-
---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-smsc9512.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
-@@ -1,4 +1,5 @@
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
- &leds {
-       act_led: act {
---- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
- / {
---- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
- / {
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -1,6 +1,6 @@
--/* Downstream version of bcm2835-rpi.dtsi */
-+/* Downstream modifications to bcm2835-rpi.dtsi */
--#include <dt-bindings/power/raspberrypi-power.h>
-+#include "bcm2835-rpi.dtsi"
- / {
-       memory {
-@@ -49,29 +49,10 @@
-                       reg = <0x7e200000 0x1000>;
-               };
--              firmware: firmware {
--                      compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
--                      #address-cells = <0>;
--                      #size-cells = <0>;
--                      mboxes = <&mailbox>;
--              };
--
--              power: power {
--                      compatible = "raspberrypi,bcm2835-power";
--                      firmware = <&firmware>;
--                      #power-domain-cells = <1>;
--              };
--
-               fb: fb {
-                       compatible = "brcm,bcm2708-fb";
-                       firmware = <&firmware>;
--                      status = "disabled";
--              };
--
--              vchiq: mailbox@7e00b840 {
--                      compatible = "brcm,bcm2835-vchiq";
--                      reg = <0x7e00b840 0x3c>;
--                      interrupts = <0 2>;
-+                      status = "okay";
-               };
-               vcsm: vcsm {
-@@ -91,10 +72,6 @@
-               sound: sound {
-                       status = "disabled";
-               };
--
--              txp: txp@7e004000 {
--                      status = "disabled";
--              };
-       };
-       __overrides__ {
-@@ -125,11 +102,23 @@
- };
- &hdmi {
--      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "disabled";
- };
--&usb {
--      power-domains = <&power RPI_POWER_DOMAIN_USB>;
-+&txp {
-+      status = "disabled";
-+};
-+
-+&i2c0 {
-+      status = "disabled";
-+};
-+
-+&i2c1 {
-+      status = "disabled";
-+};
-+
-+&i2c2 {
-+      status = "disabled";
- };
- &clocks {
-@@ -141,16 +130,8 @@ sdhost_pins: &sdhost_gpio48 {
- };
- &sdhost {
--      pinctrl-names = "default";
--      pinctrl-0 = <&sdhost_gpio48>;
--      bus-width = <4>;
-       brcm,overclock-50 = <0>;
-       brcm,pio-limit = <1>;
--      status = "okay";
--};
--
--&fb {
--      status = "okay";
- };
- &cpu_thermal {
-@@ -160,11 +141,3 @@ sdhost_pins: &sdhost_gpio48 {
- &vec {
-       status = "disabled";
- };
--
--&csi0 {
--      power-domains = <&power RPI_POWER_DOMAIN_UNICAM0>;
--};
--
--&csi1 {
--      power-domains = <&power RPI_POWER_DOMAIN_UNICAM1>;
--};
---- a/arch/arm/boot/dts/bcm2708.dtsi
-+++ b/arch/arm/boot/dts/bcm2708.dtsi
-@@ -1,6 +1,5 @@
- #include "bcm2835.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
- / {
-       /delete-node/ cpus;
---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts
-+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2709.dtsi"
-+#include "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
---- a/arch/arm/boot/dts/bcm2709.dtsi
-+++ b/arch/arm/boot/dts/bcm2709.dtsi
-@@ -1,6 +1,5 @@
- #include "bcm2836.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2709-rpi.dtsi"
- / {
-       soc {
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -68,7 +68,7 @@
-               /delete-node/ sdhci@7e300000;
--              mmc: mmc@7e300000 {
-+              sdhci: mmc: mmc@7e300000 {
-                       compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
-                       reg = <0x7e300000 0x100>;
-                       interrupts = <2 30>;
-@@ -152,22 +152,6 @@
-               };
-       };
--      vdd_5v0_reg: fixedregulator_5v0 {
--              compatible = "regulator-fixed";
--              regulator-name = "5v0";
--              regulator-min-microvolt = <5000000>;
--              regulator-max-microvolt = <5000000>;
--              regulator-always-on;
--      };
--
--      vdd_3v3_reg: fixedregulator_3v3 {
--              compatible = "regulator-fixed";
--              regulator-name = "3v3";
--              regulator-min-microvolt = <3300000>;
--              regulator-max-microvolt = <3300000>;
--              regulator-always-on;
--      };
--
-       __overrides__ {
-               cam0-pwdn-ctrl;
-               cam0-pwdn;
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2710.dtsi"
-+#include "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-lan7515.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2710.dtsi"
-+#include "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
- #include "bcm2710.dtsi"
-+#include "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-csi0-2lane.dtsi"
- #include "bcm283x-rpi-csi1-4lane.dtsi"
---- a/arch/arm/boot/dts/bcm2710.dtsi
-+++ b/arch/arm/boot/dts/bcm2710.dtsi
-@@ -1,6 +1,5 @@
- #include "bcm2837.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2709-rpi.dtsi"
- / {
-       compatible = "brcm,bcm2837", "brcm,bcm2836";
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -1,13 +1,12 @@
- /dts-v1/;
- #include "bcm2711.dtsi"
-+#include "bcm2711-rpi.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
- / {
--      compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
-+      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
-       model = "Raspberry Pi 4 Model B";
--      #address-cells = <2>;
--      #size-cells = <1>;
-       memory {
-               device_type = "memory";
-@@ -48,10 +47,18 @@
- };
- &firmware {
--      expgpio: expgpio {
-+      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",
-+                                "",
-+                                "";
-               status = "okay";
-       };
- };
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
-@@ -0,0 +1,7 @@
-+#include "bcm2708-rpi.dtsi"
-+#include "bcm2838-rpi.dtsi"
-+
-+&v3d {
-+     /* Undo the overwriting by bcm270x.dtsi */
-+     power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
-+};
---- a/arch/arm/boot/dts/bcm2711.dtsi
-+++ b/arch/arm/boot/dts/bcm2711.dtsi
-@@ -1,10 +1,8 @@
- #include "bcm2838.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
- / {
-       soc {
--              /delete-node/ mailbox@7e00b840;
-               /delete-node/ v3d@7ec00000;
-       };
-@@ -17,14 +15,6 @@
-       status = "disabled";
- };
--&dma {
--      brcm,dma-channel-mask = <0x7ef5>;
--};
--
--&txp {
--      interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
--};
--
- &firmwarekms {
-       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
- };
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -36,6 +36,22 @@
-                       interrupts = <0 2>;
-               };
-       };
-+
-+      vdd_3v3_reg: fixedregulator_3v3 {
-+              compatible = "regulator-fixed";
-+              regulator-name = "3v3";
-+              regulator-min-microvolt = <3300000>;
-+              regulator-max-microvolt = <3300000>;
-+              regulator-always-on;
-+      };
-+
-+      vdd_5v0_reg: fixedregulator_5v0 {
-+              compatible = "regulator-fixed";
-+              regulator-name = "5v0";
-+              regulator-min-microvolt = <5000000>;
-+              regulator-max-microvolt = <5000000>;
-+              regulator-always-on;
-+      };
- };
- &gpio {
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -5,7 +5,10 @@
- #include <dt-bindings/soc/bcm2835-pm.h>
- / {
--      compatible = "brcm,bcm2838", "brcm,bcm2837";
-+      compatible = "brcm,bcm2838";
-+
-+      #address-cells = <2>;
-+      #size-cells = <1>;
-       interrupt-parent = <&gicv2>;
-@@ -16,8 +19,8 @@
-               /* Emulate a contiguous 30-bit address range for DMA */
-               dma-ranges = <0xc0000000  0x0 0x00000000  0x3c000000>;
--              /delete-node/ mailbox@7e00b840;
-               /delete-node/ interrupt-controller@7e00f300;
-+              /delete-node/ v3d@7ec00000;
-               local_intc: local_intc@40000000 {
-                       compatible = "brcm,bcm2836-l1-intc";
-@@ -191,6 +194,16 @@
-                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
-               };
-+              pwm1: pwm@7e20c800 {
-+                      compatible = "brcm,bcm2835-pwm";
-+                      reg = <0x7e20c800 0x28>;
-+                      clocks = <&clocks BCM2835_CLOCK_PWM>;
-+                      assigned-clocks = <&clocks BCM2835_CLOCK_PWM>;
-+                      assigned-clock-rates = <10000000>;
-+                      #pwm-cells = <2>;
-+                      status = "disabled";
-+              };
-+
-               emmc2: emmc2@7e340000 {
-                       compatible = "brcm,bcm2711-emmc2";
-                       status = "okay";
-@@ -385,7 +398,7 @@
-                               "dma13",
-                               "dma14";
-                       #dma-cells = <1>;
--                      brcm,dma-channel-mask = <0x7000>;
-+                      brcm,dma-channel-mask = <0x7800>;
-               };
-               /* DMA4 - 40 bit DMA engines */
-@@ -396,12 +409,6 @@
-                       interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
-               };
--              vchiq: mailbox@7e00b840 {
--                      compatible = "brcm,bcm2838-vchiq";
--                      reg = <0 0x7e00b840 0x3c>;
--                      interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
--              };
--
-               hevc-decoder@7eb00000 {
-                       compatible = "raspberrypi,argon-hevc-decoder";
-                       reg = <0x0 0x7eb00000 0x10000>;
-@@ -450,6 +457,8 @@
- };
- &gpio {
-+      compatible = "brcm,bcm2838-gpio", "brcm,bcm2835-gpio";
-+
-       gpclk0_gpio49: gpclk0_gpio49 {
-               brcm,pins = <49>;
-               brcm,function = <BCM2835_FSEL_ALT1>;
-@@ -729,5 +738,9 @@
-                         "dma8",
-                         "dma9",
-                         "dma10";
--      brcm,dma-channel-mask = <0x01f5>;
-+      brcm,dma-channel-mask = <0x07f5>;
-+};
-+
-+&txp {
-+      interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- };
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -55,7 +55,7 @@
-               #address-cells = <1>;
-               #size-cells = <1>;
--              txp@7e004000 {
-+              txp: txp@7e004000 {
-                       compatible = "brcm,bcm2835-txp";
-                       reg = <0x7e004000 0x20>;
-                       interrupts = <1 11>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0584-overlays-Fix-compatible-string-for-ds1307-RTC.patch b/target/linux/brcm2708/patches-4.19/950-0584-overlays-Fix-compatible-string-for-ds1307-RTC.patch
new file mode 100644 (file)
index 0000000..220cd5e
--- /dev/null
@@ -0,0 +1,28 @@
+From 4a5715f95d8865c817c9a747f28f38b234f5df42 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Jun 2019 14:36:12 +0100
+Subject: [PATCH] overlays: Fix compatible string for ds1307 RTC
+
+Kernels since 4.19 have required the correct manufacture name in the
+compatible string for I2C devices, and unfortunately the one for the
+Dallas/Maxim DS1307 should have been "dallas,ds1307" and not
+"maxim,ds1307".
+
+See: https://github.com/raspberrypi/linux/issues/3013
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ 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
+@@ -30,7 +30,7 @@
+                       status = "okay";
+                       ds1307: ds1307@68 {
+-                              compatible = "maxim,ds1307";
++                              compatible = "dallas,ds1307";
+                               reg = <0x68>;
+                               status = "okay";
+                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0585-arm-dts-First-draft-of-upstream-Pi4-DTS.patch b/target/linux/brcm2708/patches-4.19/950-0585-arm-dts-First-draft-of-upstream-Pi4-DTS.patch
deleted file mode 100644 (file)
index 0fa4cf3..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-From 5216bb8a1257a8216362affe4757a96a36b60b32 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 11 Jun 2019 18:08:05 +0100
-Subject: [PATCH] arm: dts: First draft of upstream Pi4 DTS
-
-I've attempted to follow the upstream conventions in the DT commits,
-but this is just presented here initially as a talking point.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile            |   1 +
- arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 118 ++++++++++++++++++++++++++
- arch/arm/boot/dts/bcm2838-rpi.dtsi    |  25 ++++++
- 3 files changed, 144 insertions(+)
- create mode 100644 arch/arm/boot/dts/bcm2838-rpi-4-b.dts
- create mode 100644 arch/arm/boot/dts/bcm2838-rpi.dtsi
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -94,6 +94,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
-       bcm2836-rpi-2-b.dtb \
-       bcm2837-rpi-3-b.dtb \
-       bcm2837-rpi-3-b-plus.dtb \
-+      bcm2838-rpi-4-b.dtb \
-       bcm2835-rpi-zero.dtb \
-       bcm2835-rpi-zero-w.dtb
- dtb-$(CONFIG_ARCH_BCM_5301X) += \
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
-@@ -0,0 +1,118 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/dts-v1/;
-+#include "bcm2838.dtsi"
-+#include "bcm2835-rpi.dtsi"
-+#include "bcm2838-rpi.dtsi"
-+
-+/ {
-+      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
-+      model = "Raspberry Pi 4 Model B";
-+
-+      chosen {
-+              /* 8250 auxiliary UART instead of pl011 */
-+              stdout-path = "serial1:115200n8";
-+      };
-+
-+      memory {
-+              reg = <0 0 0x40000000>;
-+      };
-+
-+      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 {
-+              status = "okay";
-+              compatible = "regulator-gpio";
-+              vin-supply = <&vdd_5v0_reg>;
-+              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>;
-+      };
-+};
-+
-+&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",
-+                                "",
-+                                "";
-+              status = "okay";
-+      };
-+};
-+
-+&pwm1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwm0_gpio40 &pwm1_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>;
-+      status = "okay";
-+      bus-width = <4>;
-+      non-removable;
-+      mmc-pwrseq = <&wifi_pwrseq>;
-+
-+      brcmf: wifi@1 {
-+              reg = <1>;
-+              compatible = "brcm,bcm4329-fmac";
-+      };
-+};
-+
-+/* EMMC2 is used to drive the SD card */
-+&emmc2 {
-+      status = "okay";
-+      broken-cd;
-+      vqmmc-supply = <&sd_io_1v8_reg>;
-+};
-+
-+/* uart0 communicates with the BT module */
-+&uart0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32 &gpclk2_gpio43>;
-+      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";
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2838-rpi.dtsi
-@@ -0,0 +1,25 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+/ {
-+      soc {
-+              /delete-node/ mailbox@7e00b840;
-+      };
-+};
-+
-+&scb {
-+      vchiq: mailbox@7e00b840 {
-+              compatible = "brcm,bcm2838-vchiq";
-+              reg = <0 0x7e00b840 0x3c>;
-+              interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-+      };
-+};
-+
-+&dma {
-+      /* The VPU firmware uses DMA channel 11 for VCHIQ */
-+      brcm,dma-channel-mask = <0x1f5>;
-+};
-+
-+&dma40 {
-+      /* The VPU firmware DMA channel 11 for VCHIQ */
-+      brcm,dma-channel-mask = <0x7000>;
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0585-overlays-Fix-further-maxim-ds1307-references.patch b/target/linux/brcm2708/patches-4.19/950-0585-overlays-Fix-further-maxim-ds1307-references.patch
new file mode 100644 (file)
index 0000000..30dcaf4
--- /dev/null
@@ -0,0 +1,47 @@
+From ff25f8c70fd995e4f76a3c1245556cc0ec3db19d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 18 Jun 2019 11:16:13 +0100
+Subject: [PATCH] overlays: Fix further maxim,ds1307 references
+
+See: https://github.com/raspberrypi/linux/issues/3013
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/balena-fin-overlay.dts   | 2 +-
+ arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts    | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -84,7 +84,7 @@
+                       // rtc clock
+                       ds1307: ds1307@68 {
+-                              compatible = "maxim,ds1307";
++                              compatible = "dallas,ds1307";
+                               reg = <0x68>;
+                               status = "okay";
+                       };
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -46,7 +46,7 @@
+                       status = "okay";
+                       ds1307: ds1307@68 {
+-                              compatible = "maxim,ds1307";
++                              compatible = "dallas,ds1307";
+                               reg = <0x68>;
+                               status = "okay";
+                       };
+--- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
+@@ -155,7 +155,7 @@
+                       status = "okay";
+                       ds1307: ds1307@68 {
+-                              compatible = "maxim,ds1307";
++                              compatible = "dallas,ds1307";
+                               reg = <0x68>;
+                               status = "okay";
+                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0586-overlays-Cosmetic-change-to-upstream-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0586-overlays-Cosmetic-change-to-upstream-overlay.patch
new file mode 100644 (file)
index 0000000..51db874
--- /dev/null
@@ -0,0 +1,25 @@
+From ce7469a397da34a19112b8d14eb283e02088755b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 18 Jun 2019 11:19:59 +0100
+Subject: [PATCH] overlays: Cosmetic change to upstream overlay
+
+The dwc2 overlay no longer uses the dwc2_usb label, and the latest
+ovmerge (which generates the upstream overlay) removes unused labels.
+Update the checked-in version to match.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/upstream-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -113,7 +113,7 @@
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+-              dwc2_usb: __overlay__ {
++              __overlay__ {
+                       compatible = "brcm,bcm2835-usb";
+                       dr_mode = "otg";
+                       g-np-tx-fifo-size = <32>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0586-overlays-Fix-compatible-string-for-ds1307-RTC.patch b/target/linux/brcm2708/patches-4.19/950-0586-overlays-Fix-compatible-string-for-ds1307-RTC.patch
deleted file mode 100644 (file)
index 220cd5e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 4a5715f95d8865c817c9a747f28f38b234f5df42 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 17 Jun 2019 14:36:12 +0100
-Subject: [PATCH] overlays: Fix compatible string for ds1307 RTC
-
-Kernels since 4.19 have required the correct manufacture name in the
-compatible string for I2C devices, and unfortunately the one for the
-Dallas/Maxim DS1307 should have been "dallas,ds1307" and not
-"maxim,ds1307".
-
-See: https://github.com/raspberrypi/linux/issues/3013
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- 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
-@@ -30,7 +30,7 @@
-                       status = "okay";
-                       ds1307: ds1307@68 {
--                              compatible = "maxim,ds1307";
-+                              compatible = "dallas,ds1307";
-                               reg = <0x68>;
-                               status = "okay";
-                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0587-overlays-Fix-further-maxim-ds1307-references.patch b/target/linux/brcm2708/patches-4.19/950-0587-overlays-Fix-further-maxim-ds1307-references.patch
deleted file mode 100644 (file)
index 30dcaf4..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From ff25f8c70fd995e4f76a3c1245556cc0ec3db19d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 18 Jun 2019 11:16:13 +0100
-Subject: [PATCH] overlays: Fix further maxim,ds1307 references
-
-See: https://github.com/raspberrypi/linux/issues/3013
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/balena-fin-overlay.dts   | 2 +-
- arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/tinylcd35-overlay.dts    | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -84,7 +84,7 @@
-                       // rtc clock
-                       ds1307: ds1307@68 {
--                              compatible = "maxim,ds1307";
-+                              compatible = "dallas,ds1307";
-                               reg = <0x68>;
-                               status = "okay";
-                       };
---- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-@@ -46,7 +46,7 @@
-                       status = "okay";
-                       ds1307: ds1307@68 {
--                              compatible = "maxim,ds1307";
-+                              compatible = "dallas,ds1307";
-                               reg = <0x68>;
-                               status = "okay";
-                       };
---- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-@@ -155,7 +155,7 @@
-                       status = "okay";
-                       ds1307: ds1307@68 {
--                              compatible = "maxim,ds1307";
-+                              compatible = "dallas,ds1307";
-                               reg = <0x68>;
-                               status = "okay";
-                       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0587-w1-ds2805-rename-w1_family-struct-fixing-c-p-typo.patch b/target/linux/brcm2708/patches-4.19/950-0587-w1-ds2805-rename-w1_family-struct-fixing-c-p-typo.patch
new file mode 100644 (file)
index 0000000..2f33f63
--- /dev/null
@@ -0,0 +1,44 @@
+From 4f1fd30b76c1bec76069483b88747783a0654f38 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Sat, 25 May 2019 10:45:38 +0200
+Subject: [PATCH] w1: ds2805: rename w1_family struct, fixing c-p typo
+
+commit 0e3743d870711ae4daf1e7170c8d9381564e244d upstream.
+
+The ds2805 has a structure named: w1_family_2d, which surely
+comes from a w1_ds2431 module. This commit fixes this name to
+prevent confusion and mark a correct family name.
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2805.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2805.c
++++ b/drivers/w1/slaves/w1_ds2805.c
+@@ -288,7 +288,7 @@ static struct w1_family_ops w1_f0d_fops
+       .remove_slave   = w1_f0d_remove_slave,
+ };
+-static struct w1_family w1_family_2d = {
++static struct w1_family w1_family_0d = {
+       .fid = W1_EEPROM_DS2805,
+       .fops = &w1_f0d_fops,
+ };
+@@ -296,13 +296,13 @@ static struct w1_family w1_family_2d = {
+ static int __init w1_f0d_init(void)
+ {
+       pr_info("%s()\n", __func__);
+-      return w1_register_family(&w1_family_2d);
++      return w1_register_family(&w1_family_0d);
+ }
+ static void __exit w1_f0d_fini(void)
+ {
+       pr_info("%s()\n", __func__);
+-      w1_unregister_family(&w1_family_2d);
++      w1_unregister_family(&w1_family_0d);
+ }
+ module_init(w1_f0d_init);
diff --git a/target/linux/brcm2708/patches-4.19/950-0588-overlays-Cosmetic-change-to-upstream-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0588-overlays-Cosmetic-change-to-upstream-overlay.patch
deleted file mode 100644 (file)
index 51db874..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From ce7469a397da34a19112b8d14eb283e02088755b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 18 Jun 2019 11:19:59 +0100
-Subject: [PATCH] overlays: Cosmetic change to upstream overlay
-
-The dwc2 overlay no longer uses the dwc2_usb label, and the latest
-ovmerge (which generates the upstream overlay) removes unused labels.
-Update the checked-in version to match.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/upstream-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -113,7 +113,7 @@
-               target = <&usb>;
-               #address-cells = <1>;
-               #size-cells = <1>;
--              dwc2_usb: __overlay__ {
-+              __overlay__ {
-                       compatible = "brcm,bcm2835-usb";
-                       dr_mode = "otg";
-                       g-np-tx-fifo-size = <32>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0588-w1-ds2413-output_write-cosmetic-fixes-simplify.patch b/target/linux/brcm2708/patches-4.19/950-0588-w1-ds2413-output_write-cosmetic-fixes-simplify.patch
new file mode 100644 (file)
index 0000000..6c0a304
--- /dev/null
@@ -0,0 +1,64 @@
+From 3280ce5f5483a351f49e84b48ad98df87989346a Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 20 May 2019 09:05:55 +0200
+Subject: [PATCH] w1: ds2413: output_write() cosmetic fixes / simplify
+
+commit ae2ee27aa985232f66421d7cd1c7f4b87c7dba7d upstream.
+
+Make the output_write simpler.
+Based on Jean-Francois Dagenais code from:
+49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -69,6 +69,7 @@ static ssize_t output_write(struct file
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       u8 w1_buf[3];
+       unsigned int retries = W1_F3A_RETRIES;
++      ssize_t bytes_written = -EIO;
+       if (count != 1 || off != 0)
+               return -EFAULT;
+@@ -78,7 +79,7 @@ static ssize_t output_write(struct file
+       dev_dbg(&sl->dev, "mutex locked");
+       if (w1_reset_select_slave(sl))
+-              goto error;
++              goto out;
+       /* according to the DS2413 datasheet the most significant 6 bits
+          should be set to "1"s, so do it now */
+@@ -91,18 +92,20 @@ static ssize_t output_write(struct file
+               w1_write_block(sl->master, w1_buf, 3);
+               if (w1_read_8(sl->master) == W1_F3A_SUCCESS_CONFIRM_BYTE) {
+-                      mutex_unlock(&sl->master->bus_mutex);
+-                      dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries);
+-                      return 1;
++                      bytes_written = 1;
++                      goto out;
+               }
+               if (w1_reset_resume_command(sl->master))
+-                      goto error;
++                      goto out; /* unrecoverable error */
++
++              dev_warn(&sl->dev, "PIO_ACCESS_WRITE error, retries left: %d\n", retries);
+       }
+-error:
++out:
+       mutex_unlock(&sl->master->bus_mutex);
+-      dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
+-      return -EIO;
++      dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
++              (bytes_written > 0) ? "succeeded" : "error", retries);
++      return bytes_written;
+ }
+ static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
diff --git a/target/linux/brcm2708/patches-4.19/950-0589-w1-ds2413-add-retry-support-to-state_read.patch b/target/linux/brcm2708/patches-4.19/950-0589-w1-ds2413-add-retry-support-to-state_read.patch
new file mode 100644 (file)
index 0000000..07c6157
--- /dev/null
@@ -0,0 +1,74 @@
+From 91e443597cdd8f89d2b68ea5bf0f0823d1853ab7 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 20 May 2019 09:05:56 +0200
+Subject: [PATCH] w1: ds2413: add retry support to state_read()
+
+commit c50d09a86172073f55ebac0b92ad5a75907d64e7 upstream.
+
+The state_read() was calling PIO_ACCESS_READ once and bail out if it
+failed for this first time.
+This commit is improving this to trying more times before it give up,
+similarly as the write call is currently doing.
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 37 +++++++++++++++++++++++------------
+ 1 file changed, 24 insertions(+), 13 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -30,6 +30,9 @@ static ssize_t state_read(struct file *f
+                         size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
++      unsigned int retries = W1_F3A_RETRIES;
++      ssize_t bytes_read = -EIO;
++
+       dev_dbg(&sl->dev,
+               "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
+               bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
+@@ -42,22 +45,30 @@ static ssize_t state_read(struct file *f
+       mutex_lock(&sl->master->bus_mutex);
+       dev_dbg(&sl->dev, "mutex locked");
+-      if (w1_reset_select_slave(sl)) {
+-              mutex_unlock(&sl->master->bus_mutex);
+-              return -EIO;
+-      }
++      if (w1_reset_select_slave(sl))
++              goto out;
+-      w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+-      *buf = w1_read_8(sl->master);
++      while (retries--) {
++              w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+-      mutex_unlock(&sl->master->bus_mutex);
+-      dev_dbg(&sl->dev, "mutex unlocked");
++              *buf = w1_read_8(sl->master);
++              /* check for correct complement */
++              if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
++                      bytes_read = 1;
++                      goto out;
++              }
++
++              if (w1_reset_resume_command(sl->master))
++                      goto out; /* unrecoverable error */
+-      /* check for correct complement */
+-      if ((*buf & 0x0F) != ((~*buf >> 4) & 0x0F))
+-              return -EIO;
+-      else
+-              return 1;
++              dev_warn(&sl->dev, "PIO_ACCESS_READ error, retries left: %d\n", retries);
++      }
++
++out:
++      mutex_unlock(&sl->master->bus_mutex);
++      dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
++              (bytes_read > 0) ? "succeeded" : "error", retries);
++      return bytes_read;
+ }
+ static BIN_ATTR_RO(state, 1);
diff --git a/target/linux/brcm2708/patches-4.19/950-0589-w1-ds2805-rename-w1_family-struct-fixing-c-p-typo.patch b/target/linux/brcm2708/patches-4.19/950-0589-w1-ds2805-rename-w1_family-struct-fixing-c-p-typo.patch
deleted file mode 100644 (file)
index 2f33f63..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 4f1fd30b76c1bec76069483b88747783a0654f38 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Sat, 25 May 2019 10:45:38 +0200
-Subject: [PATCH] w1: ds2805: rename w1_family struct, fixing c-p typo
-
-commit 0e3743d870711ae4daf1e7170c8d9381564e244d upstream.
-
-The ds2805 has a structure named: w1_family_2d, which surely
-comes from a w1_ds2431 module. This commit fixes this name to
-prevent confusion and mark a correct family name.
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2805.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2805.c
-+++ b/drivers/w1/slaves/w1_ds2805.c
-@@ -288,7 +288,7 @@ static struct w1_family_ops w1_f0d_fops
-       .remove_slave   = w1_f0d_remove_slave,
- };
--static struct w1_family w1_family_2d = {
-+static struct w1_family w1_family_0d = {
-       .fid = W1_EEPROM_DS2805,
-       .fops = &w1_f0d_fops,
- };
-@@ -296,13 +296,13 @@ static struct w1_family w1_family_2d = {
- static int __init w1_f0d_init(void)
- {
-       pr_info("%s()\n", __func__);
--      return w1_register_family(&w1_family_2d);
-+      return w1_register_family(&w1_family_0d);
- }
- static void __exit w1_f0d_fini(void)
- {
-       pr_info("%s()\n", __func__);
--      w1_unregister_family(&w1_family_2d);
-+      w1_unregister_family(&w1_family_0d);
- }
- module_init(w1_f0d_init);
diff --git a/target/linux/brcm2708/patches-4.19/950-0590-w1-ds2413-output_write-cosmetic-fixes-simplify.patch b/target/linux/brcm2708/patches-4.19/950-0590-w1-ds2413-output_write-cosmetic-fixes-simplify.patch
deleted file mode 100644 (file)
index 6c0a304..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From 3280ce5f5483a351f49e84b48ad98df87989346a Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Mon, 20 May 2019 09:05:55 +0200
-Subject: [PATCH] w1: ds2413: output_write() cosmetic fixes / simplify
-
-commit ae2ee27aa985232f66421d7cd1c7f4b87c7dba7d upstream.
-
-Make the output_write simpler.
-Based on Jean-Francois Dagenais code from:
-49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 19 +++++++++++--------
- 1 file changed, 11 insertions(+), 8 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -69,6 +69,7 @@ static ssize_t output_write(struct file
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-       u8 w1_buf[3];
-       unsigned int retries = W1_F3A_RETRIES;
-+      ssize_t bytes_written = -EIO;
-       if (count != 1 || off != 0)
-               return -EFAULT;
-@@ -78,7 +79,7 @@ static ssize_t output_write(struct file
-       dev_dbg(&sl->dev, "mutex locked");
-       if (w1_reset_select_slave(sl))
--              goto error;
-+              goto out;
-       /* according to the DS2413 datasheet the most significant 6 bits
-          should be set to "1"s, so do it now */
-@@ -91,18 +92,20 @@ static ssize_t output_write(struct file
-               w1_write_block(sl->master, w1_buf, 3);
-               if (w1_read_8(sl->master) == W1_F3A_SUCCESS_CONFIRM_BYTE) {
--                      mutex_unlock(&sl->master->bus_mutex);
--                      dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries);
--                      return 1;
-+                      bytes_written = 1;
-+                      goto out;
-               }
-               if (w1_reset_resume_command(sl->master))
--                      goto error;
-+                      goto out; /* unrecoverable error */
-+
-+              dev_warn(&sl->dev, "PIO_ACCESS_WRITE error, retries left: %d\n", retries);
-       }
--error:
-+out:
-       mutex_unlock(&sl->master->bus_mutex);
--      dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
--      return -EIO;
-+      dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
-+              (bytes_written > 0) ? "succeeded" : "error", retries);
-+      return bytes_written;
- }
- static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
diff --git a/target/linux/brcm2708/patches-4.19/950-0590-w1-ds2413-when-the-slave-is-not-responding-during-re.patch b/target/linux/brcm2708/patches-4.19/950-0590-w1-ds2413-when-the-slave-is-not-responding-during-re.patch
new file mode 100644 (file)
index 0000000..9d7a941
--- /dev/null
@@ -0,0 +1,56 @@
+From c84676e57896fedb47a69739fb82bb9941f624c4 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Wed, 22 May 2019 12:40:53 +0200
+Subject: [PATCH] w1: ds2413: when the slave is not responding during
+ read, select it again
+
+commit 3856032a0628e6b94badb9131a706dda185e071d upstream.
+
+The protocol is not allowing to obtain a byte of 0xff for PIO_ACCESS_READ
+call. It is very likely that the slave was not addressed properly and
+it is just not respoding (leaving the bus in logic high state) during
+the read of sampled PIO value.
+We cannot just call w1_reset_resume_command() because the problem will
+persist, instead try selecting (addressing) the slave again.
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -24,6 +24,7 @@
+ #define W1_F3A_FUNC_PIO_ACCESS_READ        0xF5
+ #define W1_F3A_FUNC_PIO_ACCESS_WRITE       0x5A
+ #define W1_F3A_SUCCESS_CONFIRM_BYTE        0xAA
++#define W1_F3A_INVALID_PIO_STATE           0xFF
+ static ssize_t state_read(struct file *filp, struct kobject *kobj,
+                         struct bin_attribute *bin_attr, char *buf, loff_t off,
+@@ -45,6 +46,7 @@ static ssize_t state_read(struct file *f
+       mutex_lock(&sl->master->bus_mutex);
+       dev_dbg(&sl->dev, "mutex locked");
++next:
+       if (w1_reset_select_slave(sl))
+               goto out;
+@@ -52,10 +54,15 @@ static ssize_t state_read(struct file *f
+               w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+               *buf = w1_read_8(sl->master);
+-              /* check for correct complement */
+               if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
++                      /* complement is correct */
+                       bytes_read = 1;
+                       goto out;
++              } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
++                      /* slave didn't respond, try to select it again */
++                      dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
++                                          "reselecting, retries left: %d\n", retries);
++                      goto next;
+               }
+               if (w1_reset_resume_command(sl->master))
diff --git a/target/linux/brcm2708/patches-4.19/950-0591-w1-ds2413-add-retry-support-to-state_read.patch b/target/linux/brcm2708/patches-4.19/950-0591-w1-ds2413-add-retry-support-to-state_read.patch
deleted file mode 100644 (file)
index 07c6157..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-From 91e443597cdd8f89d2b68ea5bf0f0823d1853ab7 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Mon, 20 May 2019 09:05:56 +0200
-Subject: [PATCH] w1: ds2413: add retry support to state_read()
-
-commit c50d09a86172073f55ebac0b92ad5a75907d64e7 upstream.
-
-The state_read() was calling PIO_ACCESS_READ once and bail out if it
-failed for this first time.
-This commit is improving this to trying more times before it give up,
-similarly as the write call is currently doing.
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 37 +++++++++++++++++++++++------------
- 1 file changed, 24 insertions(+), 13 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -30,6 +30,9 @@ static ssize_t state_read(struct file *f
-                         size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-+      unsigned int retries = W1_F3A_RETRIES;
-+      ssize_t bytes_read = -EIO;
-+
-       dev_dbg(&sl->dev,
-               "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
-               bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
-@@ -42,22 +45,30 @@ static ssize_t state_read(struct file *f
-       mutex_lock(&sl->master->bus_mutex);
-       dev_dbg(&sl->dev, "mutex locked");
--      if (w1_reset_select_slave(sl)) {
--              mutex_unlock(&sl->master->bus_mutex);
--              return -EIO;
--      }
-+      if (w1_reset_select_slave(sl))
-+              goto out;
--      w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
--      *buf = w1_read_8(sl->master);
-+      while (retries--) {
-+              w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
--      mutex_unlock(&sl->master->bus_mutex);
--      dev_dbg(&sl->dev, "mutex unlocked");
-+              *buf = w1_read_8(sl->master);
-+              /* check for correct complement */
-+              if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
-+                      bytes_read = 1;
-+                      goto out;
-+              }
-+
-+              if (w1_reset_resume_command(sl->master))
-+                      goto out; /* unrecoverable error */
--      /* check for correct complement */
--      if ((*buf & 0x0F) != ((~*buf >> 4) & 0x0F))
--              return -EIO;
--      else
--              return 1;
-+              dev_warn(&sl->dev, "PIO_ACCESS_READ error, retries left: %d\n", retries);
-+      }
-+
-+out:
-+      mutex_unlock(&sl->master->bus_mutex);
-+      dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
-+              (bytes_read > 0) ? "succeeded" : "error", retries);
-+      return bytes_read;
- }
- static BIN_ATTR_RO(state, 1);
diff --git a/target/linux/brcm2708/patches-4.19/950-0591-w1-ds2413-fix-state-byte-comparision.patch b/target/linux/brcm2708/patches-4.19/950-0591-w1-ds2413-fix-state-byte-comparision.patch
new file mode 100644 (file)
index 0000000..3d3b74e
--- /dev/null
@@ -0,0 +1,48 @@
+From 38ca046063ee6fcef66c9c3bec5844a65f9d48d9 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Thu, 30 May 2019 09:51:25 +0200
+Subject: [PATCH] w1: ds2413: fix state byte comparision
+
+commit aacd152ecd7b18af5d2d96dea9e7284c1c93abea upstream.
+
+This commit is fixing a smatch warning:
+drivers/w1/slaves/w1_ds2413.c:61 state_read() warn: impossible condition '(*buf == 255) => ((-128)-127 == 255)'
+by creating additional u8 variable for the bus reading and comparision
+
+Reported-by: kbuild test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: Dan Carpenter <dan.carpenter@oracle.com>
+Fixes: 3856032a0628 ("w1: ds2413: when the slave is not responding during read, select it again")
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -33,6 +33,7 @@ static ssize_t state_read(struct file *f
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       unsigned int retries = W1_F3A_RETRIES;
+       ssize_t bytes_read = -EIO;
++      u8 state;
+       dev_dbg(&sl->dev,
+               "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
+@@ -53,12 +54,13 @@ next:
+       while (retries--) {
+               w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+-              *buf = w1_read_8(sl->master);
+-              if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
++              state = w1_read_8(sl->master);
++              if ((state & 0x0F) == ((~state >> 4) & 0x0F)) {
+                       /* complement is correct */
++                      *buf = state;
+                       bytes_read = 1;
+                       goto out;
+-              } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
++              } else if (state == W1_F3A_INVALID_PIO_STATE) {
+                       /* slave didn't respond, try to select it again */
+                       dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
+                                           "reselecting, retries left: %d\n", retries);
diff --git a/target/linux/brcm2708/patches-4.19/950-0592-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch b/target/linux/brcm2708/patches-4.19/950-0592-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch
new file mode 100644 (file)
index 0000000..63b8e8b
--- /dev/null
@@ -0,0 +1,135 @@
+From 496b26b154da9a962a5310641d8f4b73200fe590 Mon Sep 17 00:00:00 2001
+From: Chris Miller <chris@mesl2.co.uk>
+Date: Wed, 26 Jun 2019 10:40:30 +0100
+Subject: [PATCH] drm: vc4_dsi: Fix DMA channel and memory leak in vc4
+ (#3012)
+
+Signed-off-by: Chris G Miller <chris@creative-electronics.net>
+---
+ drivers/gpu/drm/vc4/vc4_dsi.c | 35 ++++++++++++++++++++++++-----------
+ 1 file changed, 24 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_dsi.c
++++ b/drivers/gpu/drm/vc4/vc4_dsi.c
+@@ -1536,9 +1536,11 @@ static int vc4_dsi_bind(struct device *d
+       /* DSI1 has a broken AXI slave that doesn't respond to writes
+        * from the ARM.  It does handle writes from the DMA engine,
+        * so set up a channel for talking to it.
++       * Where possible managed resource providers are used, but the DMA channel
++       * must - if acquired - be explicitly released prior to taking an error exit path.
+        */
+       if (dsi->port == 1) {
+-              dsi->reg_dma_mem = dma_alloc_coherent(dev, 4,
++              dsi->reg_dma_mem = dmam_alloc_coherent(dev, 4,
+                                                     &dsi->reg_dma_paddr,
+                                                     GFP_KERNEL);
+               if (!dsi->reg_dma_mem) {
+@@ -1557,6 +1559,8 @@ static int vc4_dsi_bind(struct device *d
+                       return ret;
+               }
++              /* From here on, any error exits must release the dma channel */
++
+               /* Get the physical address of the device's registers.  The
+                * struct resource for the regs gives us the bus address
+                * instead.
+@@ -1583,7 +1587,7 @@ static int vc4_dsi_bind(struct device *d
+       if (ret) {
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get interrupt: %d\n", ret);
+-              return ret;
++              goto rel_dma_exit;
+       }
+       dsi->escape_clock = devm_clk_get(dev, "escape");
+@@ -1591,7 +1595,7 @@ static int vc4_dsi_bind(struct device *d
+               ret = PTR_ERR(dsi->escape_clock);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get escape clock: %d\n", ret);
+-              return ret;
++              goto rel_dma_exit;
+       }
+       dsi->pll_phy_clock = devm_clk_get(dev, "phy");
+@@ -1599,7 +1603,7 @@ static int vc4_dsi_bind(struct device *d
+               ret = PTR_ERR(dsi->pll_phy_clock);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get phy clock: %d\n", ret);
+-              return ret;
++              goto rel_dma_exit;
+       }
+       dsi->pixel_clock = devm_clk_get(dev, "pixel");
+@@ -1607,7 +1611,7 @@ static int vc4_dsi_bind(struct device *d
+               ret = PTR_ERR(dsi->pixel_clock);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get pixel clock: %d\n", ret);
+-              return ret;
++              goto rel_dma_exit;
+       }
+       ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+@@ -1622,26 +1626,28 @@ static int vc4_dsi_bind(struct device *d
+               if (ret == -ENODEV)
+                       return 0;
+-              return ret;
++              goto rel_dma_exit;
+       }
+       if (panel) {
+               dsi->bridge = devm_drm_panel_bridge_add(dev, panel,
+                                                       DRM_MODE_CONNECTOR_DSI);
+-              if (IS_ERR(dsi->bridge))
+-                      return PTR_ERR(dsi->bridge);
++              if (IS_ERR(dsi->bridge)){
++                      ret = PTR_ERR(dsi->bridge);
++                      goto rel_dma_exit;
++              }
+       }
+       /* The esc clock rate is supposed to always be 100Mhz. */
+       ret = clk_set_rate(dsi->escape_clock, 100 * 1000000);
+       if (ret) {
+               dev_err(dev, "Failed to set esc clock: %d\n", ret);
+-              return ret;
++              goto rel_dma_exit;
+       }
+       ret = vc4_dsi_init_phy_clocks(dsi);
+       if (ret)
+-              return ret;
++              goto rel_dma_exit;
+       if (dsi->port == 1)
+               vc4->dsi1 = dsi;
+@@ -1653,7 +1659,7 @@ static int vc4_dsi_bind(struct device *d
+       ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
+       if (ret) {
+               dev_err(dev, "bridge attach failed: %d\n", ret);
+-              return ret;
++              goto rel_dma_exit;
+       }
+       /* Disable the atomic helper calls into the bridge.  We
+        * manually call the bridge pre_enable / enable / etc. calls
+@@ -1665,6 +1671,11 @@ static int vc4_dsi_bind(struct device *d
+       pm_runtime_enable(dev);
+       return 0;
++
++rel_dma_exit:
++      dma_release_channel(dsi->reg_dma_chan);
++
++      return ret;
+ }
+ static void vc4_dsi_unbind(struct device *dev, struct device *master,
+@@ -1679,6 +1690,8 @@ static void vc4_dsi_unbind(struct device
+       vc4_dsi_encoder_destroy(dsi->encoder);
++      dma_release_channel(dsi->reg_dma_chan);
++
+       if (dsi->port == 1)
+               vc4->dsi1 = NULL;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0592-w1-ds2413-when-the-slave-is-not-responding-during-re.patch b/target/linux/brcm2708/patches-4.19/950-0592-w1-ds2413-when-the-slave-is-not-responding-during-re.patch
deleted file mode 100644 (file)
index 9d7a941..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From c84676e57896fedb47a69739fb82bb9941f624c4 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Wed, 22 May 2019 12:40:53 +0200
-Subject: [PATCH] w1: ds2413: when the slave is not responding during
- read, select it again
-
-commit 3856032a0628e6b94badb9131a706dda185e071d upstream.
-
-The protocol is not allowing to obtain a byte of 0xff for PIO_ACCESS_READ
-call. It is very likely that the slave was not addressed properly and
-it is just not respoding (leaving the bus in logic high state) during
-the read of sampled PIO value.
-We cannot just call w1_reset_resume_command() because the problem will
-persist, instead try selecting (addressing) the slave again.
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -24,6 +24,7 @@
- #define W1_F3A_FUNC_PIO_ACCESS_READ        0xF5
- #define W1_F3A_FUNC_PIO_ACCESS_WRITE       0x5A
- #define W1_F3A_SUCCESS_CONFIRM_BYTE        0xAA
-+#define W1_F3A_INVALID_PIO_STATE           0xFF
- static ssize_t state_read(struct file *filp, struct kobject *kobj,
-                         struct bin_attribute *bin_attr, char *buf, loff_t off,
-@@ -45,6 +46,7 @@ static ssize_t state_read(struct file *f
-       mutex_lock(&sl->master->bus_mutex);
-       dev_dbg(&sl->dev, "mutex locked");
-+next:
-       if (w1_reset_select_slave(sl))
-               goto out;
-@@ -52,10 +54,15 @@ static ssize_t state_read(struct file *f
-               w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
-               *buf = w1_read_8(sl->master);
--              /* check for correct complement */
-               if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
-+                      /* complement is correct */
-                       bytes_read = 1;
-                       goto out;
-+              } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
-+                      /* slave didn't respond, try to select it again */
-+                      dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
-+                                          "reselecting, retries left: %d\n", retries);
-+                      goto next;
-               }
-               if (w1_reset_resume_command(sl->master))
diff --git a/target/linux/brcm2708/patches-4.19/950-0593-video-bcm2708_fb-Revert-cma-allocation-attempt.patch b/target/linux/brcm2708/patches-4.19/950-0593-video-bcm2708_fb-Revert-cma-allocation-attempt.patch
new file mode 100644 (file)
index 0000000..1eed4f7
--- /dev/null
@@ -0,0 +1,159 @@
+From b3fe618a47d770f6c9808ade14360fd81a599789 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 19 Jun 2019 03:55:50 +0100
+Subject: [PATCH] video/bcm2708_fb: Revert cma allocation attempt
+
+"4600e91 Pulled in the multi frame buffer support from the Pi3 repo"
+pulled back in the code for allocating the framebuffer from the CMA
+heap.
+Revert it again.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c           | 101 +++------------------
+ include/soc/bcm2835/raspberrypi-firmware.h |   1 -
+ 2 files changed, 13 insertions(+), 89 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -112,9 +112,6 @@ struct bcm2708_fb {
+       struct vc4_display_settings_t display_settings;
+       struct debugfs_regset32 screeninfo_regset;
+       struct bcm2708_fb_dev *fbdev;
+-      unsigned int image_size;
+-      dma_addr_t dma_addr;
+-      void *cpuaddr;
+ };
+ #define MAX_FRAMEBUFFERS 3
+@@ -377,12 +374,12 @@ static int bcm2708_fb_set_par(struct fb_
+                       .xoffset = info->var.xoffset,
+                       .yoffset = info->var.yoffset,
+               .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+-                      /* base and screen_size will be initialised later */
+-              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
+-                      /* pitch will be initialised later */
++                      .base = 0,
++                      .screen_size = 0,
++              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
++                      .pitch = 0,
+       };
+-      int ret, image_size;
+-
++      int ret;
+       print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
+                   info,
+@@ -397,76 +394,12 @@ static int bcm2708_fb_set_par(struct fb_
+        */
+       set_display_num(fb);
+-      /* Try allocating our own buffer. We can specify all the parameters */
+-      image_size = ((info->var.xres * info->var.yres) *
+-                    info->var.bits_per_pixel) >> 3;
+-
+-      if (!fb->fbdev->disable_arm_alloc &&
+-          (image_size != fb->image_size || !fb->dma_addr)) {
+-              if (fb->dma_addr) {
+-                      dma_free_coherent(info->device, fb->image_size,
+-                                        fb->cpuaddr, fb->dma_addr);
+-                      fb->image_size = 0;
+-                      fb->cpuaddr = NULL;
+-                      fb->dma_addr = 0;
+-              }
+-
+-              fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
+-                                               &fb->dma_addr, GFP_KERNEL);
+-
+-              if (!fb->cpuaddr) {
+-                      fb->dma_addr = 0;
+-                      fb->fbdev->disable_arm_alloc = true;
+-              } else {
+-                      fb->image_size = image_size;
+-              }
+-      }
+-
+-      if (fb->cpuaddr) {
+-              fbinfo.base = fb->dma_addr;
+-              fbinfo.screen_size = image_size;
+-              fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
+-
+-              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
+-                                               sizeof(fbinfo));
+-              if (ret || fbinfo.base != fb->dma_addr) {
+-                      /* Firmware either failed, or assigned a different base
+-                       * address (ie it doesn't support being passed an FB
+-                       * allocation).
+-                       * Destroy the allocation, and don't try again.
+-                       */
+-                      dma_free_coherent(info->device, fb->image_size,
+-                                        fb->cpuaddr, fb->dma_addr);
+-                      fb->image_size = 0;
+-                      fb->cpuaddr = NULL;
+-                      fb->dma_addr = 0;
+-                      fb->fbdev->disable_arm_alloc = true;
+-              }
+-      } else {
+-              /* Our allocation failed - drop into the old scheme of
+-               * allocation by the VPU.
+-               */
+-              ret = -ENOMEM;
+-      }
+-
++      ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
++                                       sizeof(fbinfo));
+       if (ret) {
+-              /* Old scheme:
+-               * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
+-               * - GET_PITCH instead of SET_PITCH.
+-               */
+-              fbinfo.base = 0;
+-              fbinfo.screen_size = 0;
+-              fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
+-              fbinfo.pitch = 0;
+-
+-              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
+-                                               sizeof(fbinfo));
+-              if (ret) {
+-                      dev_err(info->device,
+-                              "Failed to allocate GPU framebuffer (%d)\n",
+-                              ret);
+-                      return ret;
+-              }
++              dev_err(info->device,
++                      "Failed to allocate GPU framebuffer (%d)\n", ret);
++              return ret;
+       }
+       if (info->var.bits_per_pixel <= 8)
+@@ -481,17 +414,9 @@ static int bcm2708_fb_set_par(struct fb_
+       fb->fb.fix.smem_start = fbinfo.base;
+       fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
+       fb->fb.screen_size = fbinfo.screen_size;
+-
+-      if (!fb->dma_addr) {
+-              if (fb->fb.screen_base)
+-                      iounmap(fb->fb.screen_base);
+-
+-              fb->fb.screen_base = ioremap_wc(fbinfo.base,
+-                                              fb->fb.screen_size);
+-      } else {
+-              fb->fb.screen_base = fb->cpuaddr;
+-      }
+-
++      if (fb->fb.screen_base)
++              iounmap(fb->fb.screen_base);
++      fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
+       if (!fb->fb.screen_base) {
+               /* the console may currently be locked */
+               console_trylock();
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -138,7 +138,6 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH =                  0x00048005,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER =            0x00048006,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE =             0x00048007,
+-      RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH =                  0x00048008,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET =         0x00048009,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN =               0x0004800a,
+       RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE =                0x0004800b,
diff --git a/target/linux/brcm2708/patches-4.19/950-0593-w1-ds2413-fix-state-byte-comparision.patch b/target/linux/brcm2708/patches-4.19/950-0593-w1-ds2413-fix-state-byte-comparision.patch
deleted file mode 100644 (file)
index 3d3b74e..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 38ca046063ee6fcef66c9c3bec5844a65f9d48d9 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Thu, 30 May 2019 09:51:25 +0200
-Subject: [PATCH] w1: ds2413: fix state byte comparision
-
-commit aacd152ecd7b18af5d2d96dea9e7284c1c93abea upstream.
-
-This commit is fixing a smatch warning:
-drivers/w1/slaves/w1_ds2413.c:61 state_read() warn: impossible condition '(*buf == 255) => ((-128)-127 == 255)'
-by creating additional u8 variable for the bus reading and comparision
-
-Reported-by: kbuild test robot <lkp@intel.com>
-Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
-Cc: Dan Carpenter <dan.carpenter@oracle.com>
-Fixes: 3856032a0628 ("w1: ds2413: when the slave is not responding during read, select it again")
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -33,6 +33,7 @@ static ssize_t state_read(struct file *f
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-       unsigned int retries = W1_F3A_RETRIES;
-       ssize_t bytes_read = -EIO;
-+      u8 state;
-       dev_dbg(&sl->dev,
-               "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
-@@ -53,12 +54,13 @@ next:
-       while (retries--) {
-               w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
--              *buf = w1_read_8(sl->master);
--              if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
-+              state = w1_read_8(sl->master);
-+              if ((state & 0x0F) == ((~state >> 4) & 0x0F)) {
-                       /* complement is correct */
-+                      *buf = state;
-                       bytes_read = 1;
-                       goto out;
--              } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
-+              } else if (state == W1_F3A_INVALID_PIO_STATE) {
-                       /* slave didn't respond, try to select it again */
-                       dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
-                                           "reselecting, retries left: %d\n", retries);
diff --git a/target/linux/brcm2708/patches-4.19/950-0594-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch b/target/linux/brcm2708/patches-4.19/950-0594-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch
new file mode 100644 (file)
index 0000000..ad3732d
--- /dev/null
@@ -0,0 +1,110 @@
+From ee96684cb2f528ad1036ae9a9126c9118a80dfbe Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Jun 2019 02:29:40 +0100
+Subject: [PATCH] drm/vc4: Add support for color encoding on YUV planes
+
+Adds signalling for BT601/709/2020, and limited/full range
+(on BT601).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++++++++++++-
+ drivers/gpu/drm/vc4/vc_image_types.h   | 28 ++++++++++++++++++++++
+ 2 files changed, 59 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -66,7 +66,7 @@ struct set_plane {
+       u8 alpha;
+       u8 num_planes;
+       u8 is_vu;
+-      u8 padding;
++      u8 color_encoding;
+       u32 planes[4];  /* DMA address of each plane */
+@@ -454,6 +454,28 @@ static void vc4_plane_atomic_update(stru
+               if (num_planes == 3 &&
+                   (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
+                       mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
++
++              switch (state->color_encoding) {
++              default:
++              case DRM_COLOR_YCBCR_BT601:
++                      if (state->color_range == DRM_COLOR_YCBCR_LIMITED_RANGE)
++                              mb->plane.color_encoding =
++                                              VC_IMAGE_YUVINFO_CSC_ITUR_BT601;
++                      else
++                              mb->plane.color_encoding =
++                                              VC_IMAGE_YUVINFO_CSC_JPEG_JFIF;
++                      break;
++              case DRM_COLOR_YCBCR_BT709:
++                      /* Currently no support for a full range BT709 */
++                      mb->plane.color_encoding =
++                                              VC_IMAGE_YUVINFO_CSC_ITUR_BT709;
++                      break;
++              case DRM_COLOR_YCBCR_BT2020:
++                      /* Currently no support for a full range BT2020 */
++                      mb->plane.color_encoding =
++                                      VC_IMAGE_YUVINFO_CSC_REC_2020;
++                      break;
++              }
+       } else {
+               mb->plane.planes[1] = 0;
+               mb->plane.planes[2] = 0;
+@@ -643,6 +665,14 @@ static struct drm_plane *vc4_fkms_plane_
+       drm_plane_create_alpha_property(plane);
+       drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
+                                          SUPPORTED_ROTATIONS);
++      drm_plane_create_color_properties(plane,
++                                        BIT(DRM_COLOR_YCBCR_BT601) |
++                                        BIT(DRM_COLOR_YCBCR_BT709) |
++                                        BIT(DRM_COLOR_YCBCR_BT2020),
++                                        BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
++                                        BIT(DRM_COLOR_YCBCR_FULL_RANGE),
++                                        DRM_COLOR_YCBCR_BT709,
++                                        DRM_COLOR_YCBCR_LIMITED_RANGE);
+       /*
+        * Default frame buffer setup is with FB on -127, and raspistill etc
+--- a/drivers/gpu/drm/vc4/vc_image_types.h
++++ b/drivers/gpu/drm/vc4/vc_image_types.h
+@@ -4,6 +4,8 @@
+  *
+  * Values taken from vc_image_types.h released by Broadcom at
+  * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
++ * and vc_image_structs.h at
++ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_structs.h
+  *
+  * 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
+@@ -141,3 +143,29 @@ enum {
+       VC_IMAGE_MAX,     /* bounds for error checking */
+       VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
+ };
++
++enum {
++      /* Unknown or unset - defaults to BT601 interstitial */
++      VC_IMAGE_YUVINFO_UNSPECIFIED    = 0,
++
++      /* colour-space conversions data [4 bits] */
++
++      /* ITU-R BT.601-5 [SDTV] (compatible with VideoCore-II) */
++      VC_IMAGE_YUVINFO_CSC_ITUR_BT601      = 1,
++      /* ITU-R BT.709-3 [HDTV] */
++      VC_IMAGE_YUVINFO_CSC_ITUR_BT709      = 2,
++      /* JPEG JFIF */
++      VC_IMAGE_YUVINFO_CSC_JPEG_JFIF       = 3,
++      /* Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
++      VC_IMAGE_YUVINFO_CSC_FCC             = 4,
++      /* Society of Motion Picture and Television Engineers 240M (1999) */
++      VC_IMAGE_YUVINFO_CSC_SMPTE_240M      = 5,
++      /* ITU-R BT.470-2 System M */
++      VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_M  = 6,
++      /* ITU-R BT.470-2 System B,G */
++      VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_BG = 7,
++      /* JPEG JFIF, but with 16..255 luma */
++      VC_IMAGE_YUVINFO_CSC_JPEG_JFIF_Y16_255 = 8,
++      /* Rec 2020 */
++      VC_IMAGE_YUVINFO_CSC_REC_2020        = 9,
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0594-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch b/target/linux/brcm2708/patches-4.19/950-0594-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch
deleted file mode 100644 (file)
index 63b8e8b..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-From 496b26b154da9a962a5310641d8f4b73200fe590 Mon Sep 17 00:00:00 2001
-From: Chris Miller <chris@mesl2.co.uk>
-Date: Wed, 26 Jun 2019 10:40:30 +0100
-Subject: [PATCH] drm: vc4_dsi: Fix DMA channel and memory leak in vc4
- (#3012)
-
-Signed-off-by: Chris G Miller <chris@creative-electronics.net>
----
- drivers/gpu/drm/vc4/vc4_dsi.c | 35 ++++++++++++++++++++++++-----------
- 1 file changed, 24 insertions(+), 11 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_dsi.c
-+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
-@@ -1536,9 +1536,11 @@ static int vc4_dsi_bind(struct device *d
-       /* DSI1 has a broken AXI slave that doesn't respond to writes
-        * from the ARM.  It does handle writes from the DMA engine,
-        * so set up a channel for talking to it.
-+       * Where possible managed resource providers are used, but the DMA channel
-+       * must - if acquired - be explicitly released prior to taking an error exit path.
-        */
-       if (dsi->port == 1) {
--              dsi->reg_dma_mem = dma_alloc_coherent(dev, 4,
-+              dsi->reg_dma_mem = dmam_alloc_coherent(dev, 4,
-                                                     &dsi->reg_dma_paddr,
-                                                     GFP_KERNEL);
-               if (!dsi->reg_dma_mem) {
-@@ -1557,6 +1559,8 @@ static int vc4_dsi_bind(struct device *d
-                       return ret;
-               }
-+              /* From here on, any error exits must release the dma channel */
-+
-               /* Get the physical address of the device's registers.  The
-                * struct resource for the regs gives us the bus address
-                * instead.
-@@ -1583,7 +1587,7 @@ static int vc4_dsi_bind(struct device *d
-       if (ret) {
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to get interrupt: %d\n", ret);
--              return ret;
-+              goto rel_dma_exit;
-       }
-       dsi->escape_clock = devm_clk_get(dev, "escape");
-@@ -1591,7 +1595,7 @@ static int vc4_dsi_bind(struct device *d
-               ret = PTR_ERR(dsi->escape_clock);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to get escape clock: %d\n", ret);
--              return ret;
-+              goto rel_dma_exit;
-       }
-       dsi->pll_phy_clock = devm_clk_get(dev, "phy");
-@@ -1599,7 +1603,7 @@ static int vc4_dsi_bind(struct device *d
-               ret = PTR_ERR(dsi->pll_phy_clock);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to get phy clock: %d\n", ret);
--              return ret;
-+              goto rel_dma_exit;
-       }
-       dsi->pixel_clock = devm_clk_get(dev, "pixel");
-@@ -1607,7 +1611,7 @@ static int vc4_dsi_bind(struct device *d
-               ret = PTR_ERR(dsi->pixel_clock);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to get pixel clock: %d\n", ret);
--              return ret;
-+              goto rel_dma_exit;
-       }
-       ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
-@@ -1622,26 +1626,28 @@ static int vc4_dsi_bind(struct device *d
-               if (ret == -ENODEV)
-                       return 0;
--              return ret;
-+              goto rel_dma_exit;
-       }
-       if (panel) {
-               dsi->bridge = devm_drm_panel_bridge_add(dev, panel,
-                                                       DRM_MODE_CONNECTOR_DSI);
--              if (IS_ERR(dsi->bridge))
--                      return PTR_ERR(dsi->bridge);
-+              if (IS_ERR(dsi->bridge)){
-+                      ret = PTR_ERR(dsi->bridge);
-+                      goto rel_dma_exit;
-+              }
-       }
-       /* The esc clock rate is supposed to always be 100Mhz. */
-       ret = clk_set_rate(dsi->escape_clock, 100 * 1000000);
-       if (ret) {
-               dev_err(dev, "Failed to set esc clock: %d\n", ret);
--              return ret;
-+              goto rel_dma_exit;
-       }
-       ret = vc4_dsi_init_phy_clocks(dsi);
-       if (ret)
--              return ret;
-+              goto rel_dma_exit;
-       if (dsi->port == 1)
-               vc4->dsi1 = dsi;
-@@ -1653,7 +1659,7 @@ static int vc4_dsi_bind(struct device *d
-       ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
-       if (ret) {
-               dev_err(dev, "bridge attach failed: %d\n", ret);
--              return ret;
-+              goto rel_dma_exit;
-       }
-       /* Disable the atomic helper calls into the bridge.  We
-        * manually call the bridge pre_enable / enable / etc. calls
-@@ -1665,6 +1671,11 @@ static int vc4_dsi_bind(struct device *d
-       pm_runtime_enable(dev);
-       return 0;
-+
-+rel_dma_exit:
-+      dma_release_channel(dsi->reg_dma_chan);
-+
-+      return ret;
- }
- static void vc4_dsi_unbind(struct device *dev, struct device *master,
-@@ -1679,6 +1690,8 @@ static void vc4_dsi_unbind(struct device
-       vc4_dsi_encoder_destroy(dsi->encoder);
-+      dma_release_channel(dsi->reg_dma_chan);
-+
-       if (dsi->port == 1)
-               vc4->dsi1 = NULL;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0595-arm-dts-Add-coherent_pool-1M-to-Pi-4-bootargs.patch b/target/linux/brcm2708/patches-4.19/950-0595-arm-dts-Add-coherent_pool-1M-to-Pi-4-bootargs.patch
new file mode 100644 (file)
index 0000000..222de5b
--- /dev/null
@@ -0,0 +1,28 @@
+From f9dfd577dcc8e3173ddce79bca535eeee0fad1a4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 2 Jul 2019 17:13:05 +0100
+Subject: [PATCH] arm: dts: Add coherent_pool=1M to Pi 4 bootargs
+
+Downstream Raspberry Pi dts files add "coherent_pool=1M" to the kernel
+command line to aid the dwc_otg driver, but this excluded Pi 4 which
+uses a new XCHI interface instead. UAS also benefits from a larger
+coherent_pool value, so replicate the addition in bcm2711-rpi-4-b.dts.
+
+See: https://github.com/raspberrypi/linux/pull/3040
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -14,7 +14,7 @@
+       };
+       chosen {
+-              bootargs = "8250.nr_uarts=1 cma=64M";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 cma=64M";
+       };
+       aliases {
diff --git a/target/linux/brcm2708/patches-4.19/950-0595-video-bcm2708_fb-Revert-cma-allocation-attempt.patch b/target/linux/brcm2708/patches-4.19/950-0595-video-bcm2708_fb-Revert-cma-allocation-attempt.patch
deleted file mode 100644 (file)
index 1eed4f7..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-From b3fe618a47d770f6c9808ade14360fd81a599789 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 19 Jun 2019 03:55:50 +0100
-Subject: [PATCH] video/bcm2708_fb: Revert cma allocation attempt
-
-"4600e91 Pulled in the multi frame buffer support from the Pi3 repo"
-pulled back in the code for allocating the framebuffer from the CMA
-heap.
-Revert it again.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c           | 101 +++------------------
- include/soc/bcm2835/raspberrypi-firmware.h |   1 -
- 2 files changed, 13 insertions(+), 89 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -112,9 +112,6 @@ struct bcm2708_fb {
-       struct vc4_display_settings_t display_settings;
-       struct debugfs_regset32 screeninfo_regset;
-       struct bcm2708_fb_dev *fbdev;
--      unsigned int image_size;
--      dma_addr_t dma_addr;
--      void *cpuaddr;
- };
- #define MAX_FRAMEBUFFERS 3
-@@ -377,12 +374,12 @@ static int bcm2708_fb_set_par(struct fb_
-                       .xoffset = info->var.xoffset,
-                       .yoffset = info->var.yoffset,
-               .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
--                      /* base and screen_size will be initialised later */
--              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
--                      /* pitch will be initialised later */
-+                      .base = 0,
-+                      .screen_size = 0,
-+              .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
-+                      .pitch = 0,
-       };
--      int ret, image_size;
--
-+      int ret;
-       print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
-                   info,
-@@ -397,76 +394,12 @@ static int bcm2708_fb_set_par(struct fb_
-        */
-       set_display_num(fb);
--      /* Try allocating our own buffer. We can specify all the parameters */
--      image_size = ((info->var.xres * info->var.yres) *
--                    info->var.bits_per_pixel) >> 3;
--
--      if (!fb->fbdev->disable_arm_alloc &&
--          (image_size != fb->image_size || !fb->dma_addr)) {
--              if (fb->dma_addr) {
--                      dma_free_coherent(info->device, fb->image_size,
--                                        fb->cpuaddr, fb->dma_addr);
--                      fb->image_size = 0;
--                      fb->cpuaddr = NULL;
--                      fb->dma_addr = 0;
--              }
--
--              fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
--                                               &fb->dma_addr, GFP_KERNEL);
--
--              if (!fb->cpuaddr) {
--                      fb->dma_addr = 0;
--                      fb->fbdev->disable_arm_alloc = true;
--              } else {
--                      fb->image_size = image_size;
--              }
--      }
--
--      if (fb->cpuaddr) {
--              fbinfo.base = fb->dma_addr;
--              fbinfo.screen_size = image_size;
--              fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
--
--              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
--                                               sizeof(fbinfo));
--              if (ret || fbinfo.base != fb->dma_addr) {
--                      /* Firmware either failed, or assigned a different base
--                       * address (ie it doesn't support being passed an FB
--                       * allocation).
--                       * Destroy the allocation, and don't try again.
--                       */
--                      dma_free_coherent(info->device, fb->image_size,
--                                        fb->cpuaddr, fb->dma_addr);
--                      fb->image_size = 0;
--                      fb->cpuaddr = NULL;
--                      fb->dma_addr = 0;
--                      fb->fbdev->disable_arm_alloc = true;
--              }
--      } else {
--              /* Our allocation failed - drop into the old scheme of
--               * allocation by the VPU.
--               */
--              ret = -ENOMEM;
--      }
--
-+      ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-+                                       sizeof(fbinfo));
-       if (ret) {
--              /* Old scheme:
--               * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
--               * - GET_PITCH instead of SET_PITCH.
--               */
--              fbinfo.base = 0;
--              fbinfo.screen_size = 0;
--              fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
--              fbinfo.pitch = 0;
--
--              ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
--                                               sizeof(fbinfo));
--              if (ret) {
--                      dev_err(info->device,
--                              "Failed to allocate GPU framebuffer (%d)\n",
--                              ret);
--                      return ret;
--              }
-+              dev_err(info->device,
-+                      "Failed to allocate GPU framebuffer (%d)\n", ret);
-+              return ret;
-       }
-       if (info->var.bits_per_pixel <= 8)
-@@ -481,17 +414,9 @@ static int bcm2708_fb_set_par(struct fb_
-       fb->fb.fix.smem_start = fbinfo.base;
-       fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
-       fb->fb.screen_size = fbinfo.screen_size;
--
--      if (!fb->dma_addr) {
--              if (fb->fb.screen_base)
--                      iounmap(fb->fb.screen_base);
--
--              fb->fb.screen_base = ioremap_wc(fbinfo.base,
--                                              fb->fb.screen_size);
--      } else {
--              fb->fb.screen_base = fb->cpuaddr;
--      }
--
-+      if (fb->fb.screen_base)
-+              iounmap(fb->fb.screen_base);
-+      fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
-       if (!fb->fb.screen_base) {
-               /* the console may currently be locked */
-               console_trylock();
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -138,7 +138,6 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH =                  0x00048005,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER =            0x00048006,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE =             0x00048007,
--      RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH =                  0x00048008,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET =         0x00048009,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN =               0x0004800a,
-       RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE =                0x0004800b,
diff --git a/target/linux/brcm2708/patches-4.19/950-0596-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch b/target/linux/brcm2708/patches-4.19/950-0596-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch
deleted file mode 100644 (file)
index ad3732d..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-From ee96684cb2f528ad1036ae9a9126c9118a80dfbe Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Jun 2019 02:29:40 +0100
-Subject: [PATCH] drm/vc4: Add support for color encoding on YUV planes
-
-Adds signalling for BT601/709/2020, and limited/full range
-(on BT601).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++++++++++++-
- drivers/gpu/drm/vc4/vc_image_types.h   | 28 ++++++++++++++++++++++
- 2 files changed, 59 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -66,7 +66,7 @@ struct set_plane {
-       u8 alpha;
-       u8 num_planes;
-       u8 is_vu;
--      u8 padding;
-+      u8 color_encoding;
-       u32 planes[4];  /* DMA address of each plane */
-@@ -454,6 +454,28 @@ static void vc4_plane_atomic_update(stru
-               if (num_planes == 3 &&
-                   (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
-                       mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
-+
-+              switch (state->color_encoding) {
-+              default:
-+              case DRM_COLOR_YCBCR_BT601:
-+                      if (state->color_range == DRM_COLOR_YCBCR_LIMITED_RANGE)
-+                              mb->plane.color_encoding =
-+                                              VC_IMAGE_YUVINFO_CSC_ITUR_BT601;
-+                      else
-+                              mb->plane.color_encoding =
-+                                              VC_IMAGE_YUVINFO_CSC_JPEG_JFIF;
-+                      break;
-+              case DRM_COLOR_YCBCR_BT709:
-+                      /* Currently no support for a full range BT709 */
-+                      mb->plane.color_encoding =
-+                                              VC_IMAGE_YUVINFO_CSC_ITUR_BT709;
-+                      break;
-+              case DRM_COLOR_YCBCR_BT2020:
-+                      /* Currently no support for a full range BT2020 */
-+                      mb->plane.color_encoding =
-+                                      VC_IMAGE_YUVINFO_CSC_REC_2020;
-+                      break;
-+              }
-       } else {
-               mb->plane.planes[1] = 0;
-               mb->plane.planes[2] = 0;
-@@ -643,6 +665,14 @@ static struct drm_plane *vc4_fkms_plane_
-       drm_plane_create_alpha_property(plane);
-       drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
-                                          SUPPORTED_ROTATIONS);
-+      drm_plane_create_color_properties(plane,
-+                                        BIT(DRM_COLOR_YCBCR_BT601) |
-+                                        BIT(DRM_COLOR_YCBCR_BT709) |
-+                                        BIT(DRM_COLOR_YCBCR_BT2020),
-+                                        BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
-+                                        BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-+                                        DRM_COLOR_YCBCR_BT709,
-+                                        DRM_COLOR_YCBCR_LIMITED_RANGE);
-       /*
-        * Default frame buffer setup is with FB on -127, and raspistill etc
---- a/drivers/gpu/drm/vc4/vc_image_types.h
-+++ b/drivers/gpu/drm/vc4/vc_image_types.h
-@@ -4,6 +4,8 @@
-  *
-  * Values taken from vc_image_types.h released by Broadcom at
-  * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
-+ * and vc_image_structs.h at
-+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_structs.h
-  *
-  * 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
-@@ -141,3 +143,29 @@ enum {
-       VC_IMAGE_MAX,     /* bounds for error checking */
-       VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
- };
-+
-+enum {
-+      /* Unknown or unset - defaults to BT601 interstitial */
-+      VC_IMAGE_YUVINFO_UNSPECIFIED    = 0,
-+
-+      /* colour-space conversions data [4 bits] */
-+
-+      /* ITU-R BT.601-5 [SDTV] (compatible with VideoCore-II) */
-+      VC_IMAGE_YUVINFO_CSC_ITUR_BT601      = 1,
-+      /* ITU-R BT.709-3 [HDTV] */
-+      VC_IMAGE_YUVINFO_CSC_ITUR_BT709      = 2,
-+      /* JPEG JFIF */
-+      VC_IMAGE_YUVINFO_CSC_JPEG_JFIF       = 3,
-+      /* Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
-+      VC_IMAGE_YUVINFO_CSC_FCC             = 4,
-+      /* Society of Motion Picture and Television Engineers 240M (1999) */
-+      VC_IMAGE_YUVINFO_CSC_SMPTE_240M      = 5,
-+      /* ITU-R BT.470-2 System M */
-+      VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_M  = 6,
-+      /* ITU-R BT.470-2 System B,G */
-+      VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_BG = 7,
-+      /* JPEG JFIF, but with 16..255 luma */
-+      VC_IMAGE_YUVINFO_CSC_JPEG_JFIF_Y16_255 = 8,
-+      /* Rec 2020 */
-+      VC_IMAGE_YUVINFO_CSC_REC_2020        = 9,
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0596-overlays-Correct-gpio-fan-gpio-flags-for-4.19.patch b/target/linux/brcm2708/patches-4.19/950-0596-overlays-Correct-gpio-fan-gpio-flags-for-4.19.patch
new file mode 100644 (file)
index 0000000..765874e
--- /dev/null
@@ -0,0 +1,30 @@
+From 21e4c9306bd20ab4e02f90cd452d90bc4e4a0a98 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 3 Jul 2019 20:37:14 +0100
+Subject: [PATCH] overlays: Correct gpio-fan gpio flags for 4.19
+
+The gpio-fan overlay was submitted for the 4.14 kernel where the second
+value in the Device Tree gpios declaration was ignored (thanks to an
+old-style driver), allowing the fan-control output to be active-high
+even though the declaration appears to request it be active-low.
+The gpio-fan driver in 4.19 uses GPIO descriptors and honours the
+active-low flag that the overlay (accidentally?) supplies.
+
+Change/correct the flags field to mark the GPIO as active-high.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ 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
+@@ -45,7 +45,7 @@
+               __overlay__ {
+                       fan0: gpio-fan@0 {
+                               compatible = "gpio-fan";
+-                              gpios = <&gpio 12 1>;
++                              gpios = <&gpio 12 0>;
+                               gpio-fan,speed-map = <0    0>,
+                                                                        <5000 1>;
+                               #cooling-cells = <2>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0597-arm-dts-Add-coherent_pool-1M-to-Pi-4-bootargs.patch b/target/linux/brcm2708/patches-4.19/950-0597-arm-dts-Add-coherent_pool-1M-to-Pi-4-bootargs.patch
deleted file mode 100644 (file)
index 222de5b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From f9dfd577dcc8e3173ddce79bca535eeee0fad1a4 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 2 Jul 2019 17:13:05 +0100
-Subject: [PATCH] arm: dts: Add coherent_pool=1M to Pi 4 bootargs
-
-Downstream Raspberry Pi dts files add "coherent_pool=1M" to the kernel
-command line to aid the dwc_otg driver, but this excluded Pi 4 which
-uses a new XCHI interface instead. UAS also benefits from a larger
-coherent_pool value, so replicate the addition in bcm2711-rpi-4-b.dts.
-
-See: https://github.com/raspberrypi/linux/pull/3040
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -14,7 +14,7 @@
-       };
-       chosen {
--              bootargs = "8250.nr_uarts=1 cma=64M";
-+              bootargs = "coherent_pool=1M 8250.nr_uarts=1 cma=64M";
-       };
-       aliases {
diff --git a/target/linux/brcm2708/patches-4.19/950-0597-staging-vcsm-cma-Remove-cache-manipulation-ioctl-fro.patch b/target/linux/brcm2708/patches-4.19/950-0597-staging-vcsm-cma-Remove-cache-manipulation-ioctl-fro.patch
new file mode 100644 (file)
index 0000000..38bff7a
--- /dev/null
@@ -0,0 +1,78 @@
+From b30537425b4bf90311b8d43c95484d9d339be25f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Jun 2019 00:29:44 +0100
+Subject: [PATCH] staging: vcsm-cma: Remove cache manipulation ioctl
+ from ARM64
+
+The cache flushing ioctls are used by the Pi3 HEVC hw-assisted
+decoder as it needs finer grained flushing control than dma_ops
+allow.
+These cache calls are not present for ARM64, therefore disable
+them. We are not actively supporting 64bit kernels at present,
+and the use case of the HEVC decoder is fairly limited.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1259,6 +1259,7 @@ error:
+       return ret;
+ }
++#ifndef CONFIG_ARM64
+ /* Converts VCSM_CACHE_OP_* to an operating function. */
+ static void (*cache_op_to_func(const unsigned int cache_op))
+                                               (const void*, const void*)
+@@ -1351,6 +1352,7 @@ out:
+       return ret;
+ }
++#endif
+ static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
+                           unsigned long arg)
+@@ -1448,6 +1450,7 @@ static long vc_sm_cma_ioctl(struct file
+               break;
+       }
++#ifndef CONFIG_ARM64
+       /*
+        * Flush/Invalidate the cache for a given mapping.
+        * Blocks must be pinned (i.e. accessed) before this call.
+@@ -1455,6 +1458,7 @@ static long vc_sm_cma_ioctl(struct file
+       case VC_SM_CMA_CMD_CLEAN_INVALID2:
+               ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
+               break;
++#endif
+       default:
+               pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
+@@ -1467,6 +1471,7 @@ static long vc_sm_cma_ioctl(struct file
+       return ret;
+ }
++#ifndef CONFIG_ARM64
+ #ifdef CONFIG_COMPAT
+ struct vc_sm_cma_ioctl_clean_invalid2_32 {
+       u32 op_count;
+@@ -1496,14 +1501,17 @@ static long vc_sm_cma_compat_ioctl(struc
+       }
+ }
+ #endif
++#endif
+ /* Device operations that we managed in this driver. */
+ static const struct file_operations vc_sm_ops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = vc_sm_cma_ioctl,
++#ifndef CONFIG_ARM64
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl = vc_sm_cma_compat_ioctl,
+ #endif
++#endif
+       .open = vc_sm_cma_open,
+       .release = vc_sm_cma_release,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0598-overlays-Correct-gpio-fan-gpio-flags-for-4.19.patch b/target/linux/brcm2708/patches-4.19/950-0598-overlays-Correct-gpio-fan-gpio-flags-for-4.19.patch
deleted file mode 100644 (file)
index 765874e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 21e4c9306bd20ab4e02f90cd452d90bc4e4a0a98 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 3 Jul 2019 20:37:14 +0100
-Subject: [PATCH] overlays: Correct gpio-fan gpio flags for 4.19
-
-The gpio-fan overlay was submitted for the 4.14 kernel where the second
-value in the Device Tree gpios declaration was ignored (thanks to an
-old-style driver), allowing the fan-control output to be active-high
-even though the declaration appears to request it be active-low.
-The gpio-fan driver in 4.19 uses GPIO descriptors and honours the
-active-low flag that the overlay (accidentally?) supplies.
-
-Change/correct the flags field to mark the GPIO as active-high.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- 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
-@@ -45,7 +45,7 @@
-               __overlay__ {
-                       fan0: gpio-fan@0 {
-                               compatible = "gpio-fan";
--                              gpios = <&gpio 12 1>;
-+                              gpios = <&gpio 12 0>;
-                               gpio-fan,speed-map = <0    0>,
-                                                                        <5000 1>;
-                               #cooling-cells = <2>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0598-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch b/target/linux/brcm2708/patches-4.19/950-0598-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch
new file mode 100644 (file)
index 0000000..e8896c0
--- /dev/null
@@ -0,0 +1,758 @@
+From e4cb138abe457a6ab9b98458660a1c8e548fab7f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 1 Jul 2019 11:57:25 +0100
+Subject: [PATCH] staging: vcsm-cma: Rework to use dma APIs, not CMA
+
+Due to a misunderstanding of the DMA mapping APIs, I made
+the wrong decision on how to implement this.
+
+Rework to use dma_alloc_coherent instead of the CMA
+API. This also allows it to be built as a module easily.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/Kconfig   |   4 +-
+ .../staging/vc04_services/vc-sm-cma/Makefile  |   2 +-
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 291 ++++++++++--------
+ .../staging/vc04_services/vc-sm-cma/vc_sm.h   |  13 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c       |  98 ------
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h       |  39 ---
+ 6 files changed, 168 insertions(+), 279 deletions(-)
+ delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+ delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
++++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
+@@ -1,6 +1,6 @@
+ config BCM_VC_SM_CMA
+-      bool "VideoCore Shared Memory (CMA) driver"
+-      depends on BCM2835_VCHIQ && DMA_CMA
++      tristate "VideoCore Shared Memory (CMA) driver"
++      depends on BCM2835_VCHIQ
+       select RBTREE
+       select DMA_SHARED_BUFFER
+       help
+--- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
++++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
+@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
+ ccflags-y += -D__VCCOREVER__=0
+ vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
+-      vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
++      vc_sm.o vc_sm_cma_vchi.o
+ obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -6,8 +6,8 @@
+  * Dave Stevenson <dave.stevenson@raspberrypi.org>
+  *
+  * Based on vmcs_sm driver from Broadcom Corporation for some API,
+- * and taking some code for CMA/dmabuf handling from the Android Ion
+- * driver (Google/Linaro).
++ * and taking some code for buffer allocation and dmabuf handling from
++ * videobuf2.
+  *
+  *
+  * This driver has 3 main uses:
+@@ -52,7 +52,6 @@
+ #include "vc_sm_cma_vchi.h"
+ #include "vc_sm.h"
+-#include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
+ #include <linux/broadcom/vc_sm_cma_ioctl.h>
+@@ -89,7 +88,6 @@ struct sm_state_t {
+       struct miscdevice misc_dev;
+       struct sm_instance *sm_handle;  /* Handle for videocore service. */
+-      struct cma *cma_heap;
+       spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
+       struct idr kernelid_map;
+@@ -110,8 +108,9 @@ struct sm_state_t {
+ struct vc_sm_dma_buf_attachment {
+       struct device *dev;
+-      struct sg_table *table;
++      struct sg_table sg_table;
+       struct list_head list;
++      enum dma_data_direction dma_dir;
+ };
+ /* ---- Private Variables ----------------------------------------------- */
+@@ -202,9 +201,10 @@ static int vc_sm_cma_global_state_show(s
+                                          resource->import.attach);
+                               seq_printf(s, "           SGT          %p\n",
+                                          resource->import.sgt);
++                      } else {
++                              seq_printf(s, "           SGT          %p\n",
++                                         resource->alloc.sg_table);
+                       }
+-                      seq_printf(s, "           SG_TABLE     %p\n",
+-                                 resource->sg_table);
+                       seq_printf(s, "           DMA_ADDR     %pad\n",
+                                  &resource->dma_addr);
+                       seq_printf(s, "           VC_HANDLE     %08x\n",
+@@ -296,8 +296,9 @@ static void vc_sm_vpu_free(struct vc_sm_
+  */
+ static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
+ {
+-      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
+-               __func__, buffer, buffer->name, buffer->size);
++      pr_debug("[%s]: buffer %p (name %s, size %zu), imported %u\n",
++               __func__, buffer, buffer->name, buffer->size,
++               buffer->imported);
+       if (buffer->vc_handle) {
+               /* We've sent the unmap request but not had the response. */
+@@ -313,8 +314,6 @@ static void vc_sm_release_resource(struc
+       /* Release the allocation (whether imported dmabuf or CMA allocation) */
+       if (buffer->imported) {
+-              pr_debug("%s: Release imported dmabuf %p\n", __func__,
+-                       buffer->import.dma_buf);
+               if (buffer->import.dma_buf)
+                       dma_buf_put(buffer->import.dma_buf);
+               else
+@@ -322,16 +321,8 @@ static void vc_sm_release_resource(struc
+                              __func__, buffer);
+               buffer->import.dma_buf = NULL;
+       } else {
+-              if (buffer->sg_table) {
+-                      /* Our own allocation that we need to dma_unmap_sg */
+-                      dma_unmap_sg(&sm_state->pdev->dev,
+-                                   buffer->sg_table->sgl,
+-                                   buffer->sg_table->nents,
+-                                   DMA_BIDIRECTIONAL);
+-              }
+-              pr_debug("%s: Release our allocation\n", __func__);
+-              vc_sm_cma_buffer_free(&buffer->alloc);
+-              pr_debug("%s: Release our allocation - done\n", __func__);
++              dma_free_coherent(&sm_state->pdev->dev, buffer->size,
++                                buffer->cookie, buffer->dma_addr);
+       }
+@@ -371,38 +362,6 @@ static struct vc_sm_privdata_t *vc_sm_cm
+       return file_data;
+ }
+-static struct sg_table *dup_sg_table(struct sg_table *table)
+-{
+-      struct sg_table *new_table;
+-      int ret, i;
+-      struct scatterlist *sg, *new_sg;
+-
+-      new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
+-      if (!new_table)
+-              return ERR_PTR(-ENOMEM);
+-
+-      ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
+-      if (ret) {
+-              kfree(new_table);
+-              return ERR_PTR(ret);
+-      }
+-
+-      new_sg = new_table->sgl;
+-      for_each_sg(table->sgl, sg, table->nents, i) {
+-              memcpy(new_sg, sg, sizeof(*sg));
+-              sg->dma_address = 0;
+-              new_sg = sg_next(new_sg);
+-      }
+-
+-      return new_table;
+-}
+-
+-static void free_duped_table(struct sg_table *table)
+-{
+-      sg_free_table(table);
+-      kfree(table);
+-}
+-
+ /* Dma buf operations for use with our own allocations */
+ static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
+@@ -410,28 +369,45 @@ static int vc_sm_dma_buf_attach(struct d
+ {
+       struct vc_sm_dma_buf_attachment *a;
+-      struct sg_table *table;
++      struct sg_table *sgt;
+       struct vc_sm_buffer *buf = dmabuf->priv;
++      struct scatterlist *rd, *wr;
++      int ret, i;
+       a = kzalloc(sizeof(*a), GFP_KERNEL);
+       if (!a)
+               return -ENOMEM;
+-      table = dup_sg_table(buf->sg_table);
+-      if (IS_ERR(table)) {
++      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
++
++      mutex_lock(&buf->lock);
++
++      INIT_LIST_HEAD(&a->list);
++
++      sgt = &a->sg_table;
++
++      /* Copy the buf->base_sgt scatter list to the attachment, as we can't
++       * map the same scatter list to multiple attachments at the same time.
++       */
++      ret = sg_alloc_table(sgt, buf->alloc.sg_table->orig_nents, GFP_KERNEL);
++      if (ret) {
+               kfree(a);
+-              return PTR_ERR(table);
++              return -ENOMEM;
+       }
+-      a->table = table;
+-      INIT_LIST_HEAD(&a->list);
++      rd = buf->alloc.sg_table->sgl;
++      wr = sgt->sgl;
++      for (i = 0; i < sgt->orig_nents; ++i) {
++              sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
++              rd = sg_next(rd);
++              wr = sg_next(wr);
++      }
++      a->dma_dir = DMA_NONE;
+       attachment->priv = a;
+-      mutex_lock(&buf->lock);
+       list_add(&a->list, &buf->attachments);
+       mutex_unlock(&buf->lock);
+-      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
+       return 0;
+ }
+@@ -441,9 +417,20 @@ static void vc_sm_dma_buf_detach(struct
+ {
+       struct vc_sm_dma_buf_attachment *a = attachment->priv;
+       struct vc_sm_buffer *buf = dmabuf->priv;
++      struct sg_table *sgt;
+       pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
+-      free_duped_table(a->table);
++      if (!a)
++              return;
++
++      sgt = &a->sg_table;
++
++      /* release the scatterlist cache */
++      if (a->dma_dir != DMA_NONE)
++              dma_unmap_sg(attachment->dev, sgt->sgl, sgt->orig_nents,
++                           a->dma_dir);
++      sg_free_table(sgt);
++
+       mutex_lock(&buf->lock);
+       list_del(&a->list);
+       mutex_unlock(&buf->lock);
+@@ -455,13 +442,38 @@ static struct sg_table *vc_sm_map_dma_bu
+                                         enum dma_data_direction direction)
+ {
+       struct vc_sm_dma_buf_attachment *a = attachment->priv;
++      /* stealing dmabuf mutex to serialize map/unmap operations */
++      struct mutex *lock = &attachment->dmabuf->lock;
+       struct sg_table *table;
+-      table = a->table;
++      mutex_lock(lock);
++      pr_debug("%s attachment %p\n", __func__, attachment);
++      table = &a->sg_table;
++
++      /* return previously mapped sg table */
++      if (a->dma_dir == direction) {
++              mutex_unlock(lock);
++              return table;
++      }
++
++      /* release any previous cache */
++      if (a->dma_dir != DMA_NONE) {
++              dma_unmap_sg(attachment->dev, table->sgl, table->orig_nents,
++                           a->dma_dir);
++              a->dma_dir = DMA_NONE;
++      }
++
++      /* mapping to the client with new direction */
++      table->nents = dma_map_sg(attachment->dev, table->sgl,
++                                table->orig_nents, direction);
++      if (!table->nents) {
++              pr_err("failed to map scatterlist\n");
++              mutex_unlock(lock);
++              return ERR_PTR(-EIO);
++      }
+-      if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
+-                      direction))
+-              return ERR_PTR(-ENOMEM);
++      a->dma_dir = direction;
++      mutex_unlock(lock);
+       pr_debug("%s attachment %p\n", __func__, attachment);
+       return table;
+@@ -478,41 +490,26 @@ static void vc_sm_unmap_dma_buf(struct d
+ static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+ {
+       struct vc_sm_buffer *buf = dmabuf->priv;
+-      struct sg_table *table = buf->sg_table;
+-      unsigned long addr = vma->vm_start;
+-      unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
+-      struct scatterlist *sg;
+-      int i;
+-      int ret = 0;
++      int ret;
+       pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
+-               buf, addr);
++               buf, vma->vm_start);
+       mutex_lock(&buf->lock);
+       /* now map it to userspace */
+-      for_each_sg(table->sgl, sg, table->nents, i) {
+-              struct page *page = sg_page(sg);
+-              unsigned long remainder = vma->vm_end - addr;
+-              unsigned long len = sg->length;
++      vma->vm_pgoff = 0;
+-              if (offset >= sg->length) {
+-                      offset -= sg->length;
+-                      continue;
+-              } else if (offset) {
+-                      page += offset / PAGE_SIZE;
+-                      len = sg->length - offset;
+-                      offset = 0;
+-              }
+-              len = min(len, remainder);
+-              ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
+-                                    vma->vm_page_prot);
+-              if (ret)
+-                      break;
+-              addr += len;
+-              if (addr >= vma->vm_end)
+-                      break;
++      ret = dma_mmap_coherent(&sm_state->pdev->dev, vma, buf->cookie,
++                              buf->dma_addr, buf->size);
++
++      if (ret) {
++              pr_err("Remapping memory failed, error: %d\n", ret);
++              return ret;
+       }
++
++      vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
++
+       mutex_unlock(&buf->lock);
+       if (ret)
+@@ -570,8 +567,8 @@ static int vc_sm_dma_buf_begin_cpu_acces
+       mutex_lock(&buf->lock);
+       list_for_each_entry(a, &buf->attachments, list) {
+-              dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
+-                                  direction);
++              dma_sync_sg_for_cpu(a->dev, a->sg_table.sgl,
++                                  a->sg_table.nents, direction);
+       }
+       mutex_unlock(&buf->lock);
+@@ -593,8 +590,8 @@ static int vc_sm_dma_buf_end_cpu_access(
+       mutex_lock(&buf->lock);
+       list_for_each_entry(a, &buf->attachments, list) {
+-              dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
+-                                     direction);
++              dma_sync_sg_for_device(a->dev, a->sg_table.sgl,
++                                     a->sg_table.nents, direction);
+       }
+       mutex_unlock(&buf->lock);
+@@ -625,7 +622,9 @@ static const struct dma_buf_ops dma_buf_
+       .map = vc_sm_dma_buf_kmap,
+       .unmap = vc_sm_dma_buf_kunmap,
+ };
++
+ /* Dma_buf operations for chaining through to an imported dma_buf */
++
+ static
+ int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
+                               struct dma_buf_attachment *attachment)
+@@ -819,7 +818,7 @@ vc_sm_cma_import_dmabuf_internal(struct
+       import.type = VC_SM_ALLOC_NON_CACHED;
+       dma_addr = sg_dma_address(sgt->sgl);
+-      import.addr = (uint32_t)dma_addr;
++      import.addr = (u32)dma_addr;
+       if ((import.addr & 0xC0000000) != 0xC0000000) {
+               pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
+                      __func__, &dma_addr);
+@@ -911,11 +910,12 @@ error:
+       return ret;
+ }
+-static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
++static int vc_sm_cma_vpu_alloc(u32 size, u32 align, const char *name,
+                              u32 mem_handle, struct vc_sm_buffer **ret_buffer)
+ {
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+       struct vc_sm_buffer *buffer = NULL;
++      struct sg_table *sgt;
+       int aligned_size;
+       int ret = 0;
+@@ -938,23 +938,34 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+        */
+       mutex_lock(&buffer->lock);
+-      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+-                                    aligned_size)) {
+-              pr_err("[%s]: cma alloc of %d bytes failed\n",
++      buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
++                                          aligned_size, &buffer->dma_addr,
++                                          GFP_KERNEL);
++      if (!buffer->cookie) {
++              pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
+                      __func__, aligned_size);
+               ret = -ENOMEM;
+               goto error;
+       }
+-      buffer->sg_table = buffer->alloc.sg_table;
+-      pr_debug("[%s]: cma alloc of %d bytes success\n",
++      pr_debug("[%s]: alloc of %d bytes success\n",
+                __func__, aligned_size);
+-      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+-                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
+-              pr_err("[%s]: dma_map_sg failed\n", __func__);
++      sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
++      if (!sgt) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
++                            buffer->dma_addr, buffer->size);
++      if (ret < 0) {
++              pr_err("failed to get scatterlist from DMA API\n");
++              kfree(sgt);
++              ret = -ENOMEM;
+               goto error;
+       }
++      buffer->alloc.sg_table = sgt;
+       INIT_LIST_HEAD(&buffer->attachments);
+@@ -971,10 +982,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+               ret = PTR_ERR(buffer->dma_buf);
+               goto error;
+       }
+-      buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++      buffer->dma_addr = (u32)sg_dma_address(buffer->alloc.sg_table->sgl);
+       if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
+-              pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
+-                     __func__, &buffer->dma_addr);
++              pr_warn_once("%s: Expecting an uncached alias for dma_addr %pad\n",
++                           __func__, &buffer->dma_addr);
+               buffer->dma_addr |= 0xC0000000;
+       }
+       buffer->private = sm_state->vpu_allocs;
+@@ -1145,6 +1156,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       struct vc_sm_import import = { 0 };
+       struct vc_sm_import_result result = { 0 };
+       struct dma_buf *dmabuf = NULL;
++      struct sg_table *sgt;
+       int aligned_size;
+       int ret = 0;
+       int status;
+@@ -1162,18 +1174,13 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+               goto error;
+       }
+-      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+-                                    aligned_size)) {
+-              pr_err("[%s]: cma alloc of %d bytes failed\n",
++      buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
++                                          aligned_size,
++                                          &buffer->dma_addr,
++                                          GFP_KERNEL);
++      if (!buffer->cookie) {
++              pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
+                      __func__, aligned_size);
+-              kfree(buffer);
+-              return -ENOMEM;
+-      }
+-      buffer->sg_table = buffer->alloc.sg_table;
+-
+-      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+-                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
+-              pr_err("[%s]: dma_map_sg failed\n", __func__);
+               ret = -ENOMEM;
+               goto error;
+       }
+@@ -1204,7 +1211,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       }
+       buffer->dma_buf = dmabuf;
+-      import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++      import.addr = buffer->dma_addr;
+       import.size = aligned_size;
+       import.kernel_id = get_kernel_id(buffer);
+@@ -1229,10 +1236,25 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       buffer->private = private;
+       buffer->vc_handle = result.res_handle;
+       buffer->size = import.size;
+-      buffer->dma_addr = import.addr;
+       buffer->vpu_state = VPU_MAPPED;
+       buffer->kernel_id = import.kernel_id;
+-      //buffer->res_cached = ioparam->cached;
++
++      sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
++      if (!sgt) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
++      ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
++                            buffer->dma_addr, buffer->size);
++      if (ret < 0) {
++              /* FIXME: error handling */
++              pr_err("failed to get scatterlist from DMA API\n");
++              kfree(sgt);
++              ret = -ENOMEM;
++              goto error;
++      }
++      buffer->alloc.sg_table = sgt;
+       fd = dma_buf_fd(dmabuf, O_CLOEXEC);
+       if (fd < 0)
+@@ -1250,11 +1272,19 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+       return 0;
+ error:
+-      if (buffer) {
+-              pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
+-                     ret);
++      pr_err("[%s]: something failed - cleanup. ret %d\n", __func__, ret);
++      if (dmabuf) {
++              /* dmabuf has been exported, therefore allow dmabuf cleanup to
++               * deal with this
++               */
+               dma_buf_put(dmabuf);
++      } else {
++              /* No dmabuf, therefore just free the buffer here */
++              if (buffer->cookie)
++                      dma_free_coherent(&sm_state->pdev->dev, buffer->size,
++                                        buffer->cookie, buffer->dma_addr);
++              kfree(buffer);
+       }
+       return ret;
+ }
+@@ -1527,13 +1557,6 @@ static void vc_sm_connected_init(void)
+       pr_info("[%s]: start\n", __func__);
+-      vc_sm_cma_add_heaps(&sm_state->cma_heap);
+-      if (!sm_state->cma_heap) {
+-              pr_err("[%s]: failed to initialise CMA heap\n",
+-                     __func__);
+-              return;
+-      }
+-
+       /*
+        * Initialize and create a VCHI connection for the shared memory service
+        * running on videocore.
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+@@ -21,8 +21,6 @@
+ #include <linux/types.h>
+ #include <linux/miscdevice.h>
+-#include "vc_sm_cma.h"
+-
+ #define VC_SM_MAX_NAME_LEN 32
+ enum vc_sm_vpu_mapping_state {
+@@ -31,6 +29,12 @@ enum vc_sm_vpu_mapping_state {
+       VPU_UNMAPPING
+ };
++struct vc_sm_alloc_data {
++      unsigned long num_pages;
++      void *priv_virt;
++      struct sg_table *sg_table;
++};
++
+ struct vc_sm_imported {
+       struct dma_buf *dma_buf;
+       struct dma_buf_attachment *attach;
+@@ -56,8 +60,6 @@ struct vc_sm_buffer {
+       int in_use:1;   /* Kernel is still using this resource */
+       int imported:1; /* Imported dmabuf */
+-      struct sg_table *sg_table;
+-
+       enum vc_sm_vpu_mapping_state vpu_state;
+       u32 vc_handle;  /* VideoCore handle for this buffer */
+       int vpu_allocated;      /*
+@@ -69,11 +71,12 @@ struct vc_sm_buffer {
+       /* DMABUF related fields */
+       struct dma_buf *dma_buf;
+       dma_addr_t dma_addr;
++      void *cookie;
+       struct vc_sm_privdata_t *private;
+       union {
+-              struct vc_sm_cma_alloc_data alloc;
++              struct vc_sm_alloc_data alloc;
+               struct vc_sm_imported import;
+       };
+ };
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * VideoCore Shared Memory CMA allocator
+- *
+- * Copyright: 2018, Raspberry Pi (Trading) Ltd
+- *
+- * Based on the Android ION allocator
+- * Copyright (C) Linaro 2012
+- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
+- *
+- */
+-
+-#include <linux/slab.h>
+-#include <linux/errno.h>
+-#include <linux/err.h>
+-#include <linux/cma.h>
+-#include <linux/scatterlist.h>
+-
+-#include "vc_sm_cma.h"
+-
+-/* CMA heap operations functions */
+-int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
+-                            struct vc_sm_cma_alloc_data *buffer,
+-                            unsigned long len)
+-{
+-      /* len should already be page aligned */
+-      unsigned long num_pages = len / PAGE_SIZE;
+-      struct sg_table *table;
+-      struct page *pages;
+-      int ret;
+-
+-      pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
+-      if (!pages)
+-              return -ENOMEM;
+-
+-      table = kmalloc(sizeof(*table), GFP_KERNEL);
+-      if (!table)
+-              goto err;
+-
+-      ret = sg_alloc_table(table, 1, GFP_KERNEL);
+-      if (ret)
+-              goto free_mem;
+-
+-      sg_set_page(table->sgl, pages, len, 0);
+-
+-      buffer->priv_virt = pages;
+-      buffer->sg_table = table;
+-      buffer->cma_heap = cma_heap;
+-      buffer->num_pages = num_pages;
+-      return 0;
+-
+-free_mem:
+-      kfree(table);
+-err:
+-      cma_release(cma_heap, pages, num_pages);
+-      return -ENOMEM;
+-}
+-
+-void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
+-{
+-      struct cma *cma_heap = buffer->cma_heap;
+-      struct page *pages = buffer->priv_virt;
+-
+-      /* release memory */
+-      if (cma_heap)
+-              cma_release(cma_heap, pages, buffer->num_pages);
+-
+-      /* release sg table */
+-      if (buffer->sg_table) {
+-              sg_free_table(buffer->sg_table);
+-              kfree(buffer->sg_table);
+-              buffer->sg_table = NULL;
+-      }
+-}
+-
+-int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
+-{
+-      struct cma **heap = (struct cma **)priv;
+-      const char *name = cma_get_name(cma);
+-
+-      if (!(*heap)) {
+-              phys_addr_t phys_addr = cma_get_base(cma);
+-
+-              pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
+-                       __func__, name, &phys_addr, cma_get_size(cma));
+-              *heap = cma;
+-      } else {
+-              pr_err("%s: Ignoring heap %s as already set\n",
+-                     __func__, name);
+-      }
+-
+-      return 0;
+-}
+-
+-void vc_sm_cma_add_heaps(struct cma **cma_heap)
+-{
+-      cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
+-}
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-
+-/*
+- * VideoCore Shared Memory CMA allocator
+- *
+- * Copyright: 2018, Raspberry Pi (Trading) Ltd
+- *
+- * Based on the Android ION allocator
+- * Copyright (C) Linaro 2012
+- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
+- *
+- * This software is licensed under the terms of the GNU General Public
+- * License version 2, as published by the Free Software Foundation, and
+- * may be copied, distributed, and modified under those terms.
+- *
+- * 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.
+- *
+- */
+-#ifndef VC_SM_CMA_H
+-#define VC_SM_CMA_H
+-
+-struct vc_sm_cma_alloc_data {
+-      struct cma *cma_heap;
+-      unsigned long num_pages;
+-      void *priv_virt;
+-      struct sg_table *sg_table;
+-};
+-
+-int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
+-                            struct vc_sm_cma_alloc_data *buffer,
+-                            unsigned long len);
+-void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
+-
+-void vc_sm_cma_add_heaps(struct cma **cma_heap);
+-
+-#endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0599-staging-vc-sm-cma-Fix-the-few-remaining-coding-style.patch b/target/linux/brcm2708/patches-4.19/950-0599-staging-vc-sm-cma-Fix-the-few-remaining-coding-style.patch
new file mode 100644 (file)
index 0000000..6c61023
--- /dev/null
@@ -0,0 +1,188 @@
+From 38ae4957840ff9578a497422a8ca758549f734d5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 2 Jul 2019 17:19:04 +0100
+Subject: [PATCH] staging: vc-sm-cma: Fix the few remaining coding
+ style issues
+
+Fix a few minor checkpatch complaints to make the driver clean
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   |   6 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  | 128 +++++++++---------
+ 2 files changed, 65 insertions(+), 69 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -325,7 +325,6 @@ static void vc_sm_release_resource(struc
+                                 buffer->cookie, buffer->dma_addr);
+       }
+-
+       /* Free our buffer. Start by removing it from the list */
+       mutex_lock(&sm_state->map_lock);
+       list_del(&buffer->global_buffer_list);
+@@ -1365,7 +1364,8 @@ static int vc_sm_cma_clean_invalid2(unsi
+       }
+       for (i = 0; i < ioparam.op_count; i++) {
+-              const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
++              const struct vc_sm_cma_ioctl_clean_invalid_block * const op =
++                                                              block + i;
+               if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
+                       continue;
+@@ -1637,8 +1637,6 @@ err_remove_misc_dev:
+ err_remove_debugfs:
+       debugfs_remove_recursive(sm_state->dir_root);
+       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+-
+-      return;
+ }
+ /* Driver loading. */
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -188,79 +188,77 @@ static int vc_sm_cma_vchi_videocore_io(v
+               if (svc_use)
+                       vchi_service_release(instance->vchi_handle[0]);
+               svc_use = 0;
+-              if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
+-                      vchi_service_use(instance->vchi_handle[0]);
+-                      svc_use = 1;
+-
+-                      do {
+-                              /*
+-                               * Get new command and move it to response list
+-                               */
+-                              mutex_lock(&instance->lock);
+-                              if (list_empty(&instance->cmd_list)) {
+-                                      /* no more commands to process */
+-                                      mutex_unlock(&instance->lock);
+-                                      break;
+-                              }
+-                              cmd =
+-                                  list_first_entry(&instance->cmd_list,
+-                                                   struct sm_cmd_rsp_blk,
+-                                                   head);
+-                              list_move(&cmd->head, &instance->rsp_list);
+-                              cmd->sent = 1;
+-                              mutex_unlock(&instance->lock);
+-                              /* Send the command */
+-                              status = bcm2835_vchi_msg_queue(
+-                                              instance->vchi_handle[0],
+-                                              cmd->msg, cmd->length);
+-                              if (status) {
+-                                      pr_err("%s: failed to queue message (%d)",
+-                                             __func__, status);
+-                              }
+-
+-                              /* If no reply is needed then we're done */
+-                              if (!cmd->wait) {
+-                                      mutex_lock(&instance->lock);
+-                                      list_del(&cmd->head);
+-                                      mutex_unlock(&instance->lock);
+-                                      vc_vchi_cmd_delete(instance, cmd);
+-                                      continue;
+-                              }
+-
+-                              if (status) {
+-                                      complete(&cmd->cmplt);
+-                                      continue;
+-                              }
+-
+-                      } while (1);
+-
+-                      while (!vchi_msg_peek(instance->vchi_handle[0],
+-                                            (void **)&reply, &reply_len,
+-                                            VCHI_FLAGS_NONE)) {
+-                              if (reply->trans_id & 0x80000000) {
+-                                      /* Async event or cmd from the VPU */
+-                                      if (instance->vpu_event)
+-                                              instance->vpu_event(
+-                                                      instance, reply,
+-                                                      reply_len);
+-                              } else {
+-                                      vc_sm_cma_vchi_rx_ack(instance, cmd,
+-                                                            reply, reply_len);
+-                              }
++              if (wait_for_completion_interruptible(&instance->io_cmplt))
++                      continue;
+-                              vchi_msg_remove(instance->vchi_handle[0]);
+-                      }
++              vchi_service_use(instance->vchi_handle[0]);
++              svc_use = 1;
+-                      /* Go through the dead list and free them */
++              do {
++                      /*
++                       * Get new command and move it to response list
++                       */
+                       mutex_lock(&instance->lock);
+-                      list_for_each_entry_safe(cmd, cmd_tmp,
+-                                               &instance->dead_list, head) {
++                      if (list_empty(&instance->cmd_list)) {
++                              /* no more commands to process */
++                              mutex_unlock(&instance->lock);
++                              break;
++                      }
++                      cmd = list_first_entry(&instance->cmd_list,
++                                             struct sm_cmd_rsp_blk, head);
++                      list_move(&cmd->head, &instance->rsp_list);
++                      cmd->sent = 1;
++                      mutex_unlock(&instance->lock);
++
++                      /* Send the command */
++                      status =
++                              bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++                                                     cmd->msg, cmd->length);
++                      if (status) {
++                              pr_err("%s: failed to queue message (%d)",
++                                     __func__, status);
++                      }
++
++                      /* If no reply is needed then we're done */
++                      if (!cmd->wait) {
++                              mutex_lock(&instance->lock);
+                               list_del(&cmd->head);
++                              mutex_unlock(&instance->lock);
+                               vc_vchi_cmd_delete(instance, cmd);
++                              continue;
+                       }
+-                      mutex_unlock(&instance->lock);
++
++                      if (status) {
++                              complete(&cmd->cmplt);
++                              continue;
++                      }
++
++              } while (1);
++
++              while (!vchi_msg_peek(instance->vchi_handle[0], (void **)&reply,
++                                    &reply_len, VCHI_FLAGS_NONE)) {
++                      if (reply->trans_id & 0x80000000) {
++                              /* Async event or cmd from the VPU */
++                              if (instance->vpu_event)
++                                      instance->vpu_event(instance, reply,
++                                                          reply_len);
++                      } else {
++                              vc_sm_cma_vchi_rx_ack(instance, cmd, reply,
++                                                    reply_len);
++                      }
++
++                      vchi_msg_remove(instance->vchi_handle[0]);
++              }
++
++              /* Go through the dead list and free them */
++              mutex_lock(&instance->lock);
++              list_for_each_entry_safe(cmd, cmd_tmp, &instance->dead_list,
++                                       head) {
++                      list_del(&cmd->head);
++                      vc_vchi_cmd_delete(instance, cmd);
+               }
++              mutex_unlock(&instance->lock);
+       }
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0599-staging-vcsm-cma-Remove-cache-manipulation-ioctl-fro.patch b/target/linux/brcm2708/patches-4.19/950-0599-staging-vcsm-cma-Remove-cache-manipulation-ioctl-fro.patch
deleted file mode 100644 (file)
index 38bff7a..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-From b30537425b4bf90311b8d43c95484d9d339be25f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Jun 2019 00:29:44 +0100
-Subject: [PATCH] staging: vcsm-cma: Remove cache manipulation ioctl
- from ARM64
-
-The cache flushing ioctls are used by the Pi3 HEVC hw-assisted
-decoder as it needs finer grained flushing control than dma_ops
-allow.
-These cache calls are not present for ARM64, therefore disable
-them. We are not actively supporting 64bit kernels at present,
-and the use case of the HEVC decoder is fairly limited.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -1259,6 +1259,7 @@ error:
-       return ret;
- }
-+#ifndef CONFIG_ARM64
- /* Converts VCSM_CACHE_OP_* to an operating function. */
- static void (*cache_op_to_func(const unsigned int cache_op))
-                                               (const void*, const void*)
-@@ -1351,6 +1352,7 @@ out:
-       return ret;
- }
-+#endif
- static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
-                           unsigned long arg)
-@@ -1448,6 +1450,7 @@ static long vc_sm_cma_ioctl(struct file
-               break;
-       }
-+#ifndef CONFIG_ARM64
-       /*
-        * Flush/Invalidate the cache for a given mapping.
-        * Blocks must be pinned (i.e. accessed) before this call.
-@@ -1455,6 +1458,7 @@ static long vc_sm_cma_ioctl(struct file
-       case VC_SM_CMA_CMD_CLEAN_INVALID2:
-               ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
-               break;
-+#endif
-       default:
-               pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
-@@ -1467,6 +1471,7 @@ static long vc_sm_cma_ioctl(struct file
-       return ret;
- }
-+#ifndef CONFIG_ARM64
- #ifdef CONFIG_COMPAT
- struct vc_sm_cma_ioctl_clean_invalid2_32 {
-       u32 op_count;
-@@ -1496,14 +1501,17 @@ static long vc_sm_cma_compat_ioctl(struc
-       }
- }
- #endif
-+#endif
- /* Device operations that we managed in this driver. */
- static const struct file_operations vc_sm_ops = {
-       .owner = THIS_MODULE,
-       .unlocked_ioctl = vc_sm_cma_ioctl,
-+#ifndef CONFIG_ARM64
- #ifdef CONFIG_COMPAT
-       .compat_ioctl = vc_sm_cma_compat_ioctl,
- #endif
-+#endif
-       .open = vc_sm_cma_open,
-       .release = vc_sm_cma_release,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0600-media-videodev2.h-add-new-capabilities-for-buffer-ty.patch b/target/linux/brcm2708/patches-4.19/950-0600-media-videodev2.h-add-new-capabilities-for-buffer-ty.patch
new file mode 100644 (file)
index 0000000..8f3e72c
--- /dev/null
@@ -0,0 +1,136 @@
+From ebd995296afa99a5c53f164e595f7a6d41d32a01 Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hansverk@cisco.com>
+Date: Thu, 23 Aug 2018 09:56:22 -0400
+Subject: [PATCH] media: videodev2.h: add new capabilities for buffer
+ types
+
+Upstream commit f35f5d72e70e6b91389eb98fcabf43b79f40587f
+
+VIDIOC_REQBUFS and VIDIOC_CREATE_BUFFERS will return capabilities
+telling userspace what the given buffer type is capable of.
+
+Signed-off-by: Hans Verkuil <hansverk@cisco.com>
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+---
+ .../media/uapi/v4l/vidioc-create-bufs.rst     | 14 ++++++-
+ .../media/uapi/v4l/vidioc-reqbufs.rst         | 42 ++++++++++++++++++-
+ include/uapi/linux/videodev2.h                | 13 +++++-
+ 3 files changed, 65 insertions(+), 4 deletions(-)
+
+--- a/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
++++ b/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
+@@ -102,7 +102,19 @@ than the number requested.
+       - ``format``
+       - Filled in by the application, preserved by the driver.
+     * - __u32
+-      - ``reserved``\ [8]
++      - ``capabilities``
++      - Set by the driver. If 0, then the driver doesn't support
++        capabilities. In that case all you know is that the driver is
++      guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
++      other :c:type:`v4l2_memory` types. It will not support any others
++      capabilities. See :ref:`here <v4l2-buf-capabilities>` for a list of the
++      capabilities.
++
++      If you want to just query the capabilities without making any
++      other changes, then set ``count`` to 0, ``memory`` to
++      ``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
++    * - __u32
++      - ``reserved``\ [7]
+       - A place holder for future extensions. Drivers and applications
+       must set the array to zero.
+--- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
++++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
+@@ -88,10 +88,50 @@ any DMA in progress, an implicit
+       ``V4L2_MEMORY_DMABUF`` or ``V4L2_MEMORY_USERPTR``. See
+       :c:type:`v4l2_memory`.
+     * - __u32
+-      - ``reserved``\ [2]
++      - ``capabilities``
++      - Set by the driver. If 0, then the driver doesn't support
++        capabilities. In that case all you know is that the driver is
++      guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
++      other :c:type:`v4l2_memory` types. It will not support any others
++      capabilities.
++
++      If you want to query the capabilities with a minimum of side-effects,
++      then this can be called with ``count`` set to 0, ``memory`` set to
++      ``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will
++      free any previously allocated buffers, so this is typically something
++      that will be done at the start of the application.
++    * - __u32
++      - ``reserved``\ [1]
+       - A place holder for future extensions. Drivers and applications
+       must set the array to zero.
++.. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}|
++
++.. _v4l2-buf-capabilities:
++.. _V4L2-BUF-CAP-SUPPORTS-MMAP:
++.. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
++.. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
++.. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
++
++.. cssclass:: longtable
++
++.. flat-table:: V4L2 Buffer Capabilities Flags
++    :header-rows:  0
++    :stub-columns: 0
++    :widths:       3 1 4
++
++    * - ``V4L2_BUF_CAP_SUPPORTS_MMAP``
++      - 0x00000001
++      - This buffer type supports the ``V4L2_MEMORY_MMAP`` streaming mode.
++    * - ``V4L2_BUF_CAP_SUPPORTS_USERPTR``
++      - 0x00000002
++      - This buffer type supports the ``V4L2_MEMORY_USERPTR`` streaming mode.
++    * - ``V4L2_BUF_CAP_SUPPORTS_DMABUF``
++      - 0x00000004
++      - This buffer type supports the ``V4L2_MEMORY_DMABUF`` streaming mode.
++    * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
++      - 0x00000008
++      - This buffer type supports :ref:`requests <media-request-api>`.
+ Return Value
+ ============
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -872,9 +872,16 @@ struct v4l2_requestbuffers {
+       __u32                   count;
+       __u32                   type;           /* enum v4l2_buf_type */
+       __u32                   memory;         /* enum v4l2_memory */
+-      __u32                   reserved[2];
++      __u32                   capabilities;
++      __u32                   reserved[1];
+ };
++/* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
++#define V4L2_BUF_CAP_SUPPORTS_MMAP    (1 << 0)
++#define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
++#define V4L2_BUF_CAP_SUPPORTS_DMABUF  (1 << 2)
++#define V4L2_BUF_CAP_SUPPORTS_REQUESTS        (1 << 3)
++
+ /**
+  * struct v4l2_plane - plane info for multi-planar buffers
+  * @bytesused:                number of bytes occupied by data in the plane (payload)
+@@ -2318,6 +2325,7 @@ struct v4l2_dbg_chip_info {
+  *            return: number of created buffers
+  * @memory:   enum v4l2_memory; buffer memory type
+  * @format:   frame format, for which buffers are requested
++ * @capabilities: capabilities of this buffer type.
+  * @reserved: future extensions
+  */
+ struct v4l2_create_buffers {
+@@ -2325,7 +2333,8 @@ struct v4l2_create_buffers {
+       __u32                   count;
+       __u32                   memory;
+       struct v4l2_format      format;
+-      __u32                   reserved[8];
++      __u32                   capabilities;
++      __u32                   reserved[7];
+ };
+ /*
diff --git a/target/linux/brcm2708/patches-4.19/950-0600-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch b/target/linux/brcm2708/patches-4.19/950-0600-staging-vcsm-cma-Rework-to-use-dma-APIs-not-CMA.patch
deleted file mode 100644 (file)
index e8896c0..0000000
+++ /dev/null
@@ -1,758 +0,0 @@
-From e4cb138abe457a6ab9b98458660a1c8e548fab7f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 1 Jul 2019 11:57:25 +0100
-Subject: [PATCH] staging: vcsm-cma: Rework to use dma APIs, not CMA
-
-Due to a misunderstanding of the DMA mapping APIs, I made
-the wrong decision on how to implement this.
-
-Rework to use dma_alloc_coherent instead of the CMA
-API. This also allows it to be built as a module easily.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/Kconfig   |   4 +-
- .../staging/vc04_services/vc-sm-cma/Makefile  |   2 +-
- .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 291 ++++++++++--------
- .../staging/vc04_services/vc-sm-cma/vc_sm.h   |  13 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma.c       |  98 ------
- .../vc04_services/vc-sm-cma/vc_sm_cma.h       |  39 ---
- 6 files changed, 168 insertions(+), 279 deletions(-)
- delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
- delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-
---- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-@@ -1,6 +1,6 @@
- config BCM_VC_SM_CMA
--      bool "VideoCore Shared Memory (CMA) driver"
--      depends on BCM2835_VCHIQ && DMA_CMA
-+      tristate "VideoCore Shared Memory (CMA) driver"
-+      depends on BCM2835_VCHIQ
-       select RBTREE
-       select DMA_SHARED_BUFFER
-       help
---- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
-@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
- ccflags-y += -D__VCCOREVER__=0
- vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
--      vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
-+      vc_sm.o vc_sm_cma_vchi.o
- obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -6,8 +6,8 @@
-  * Dave Stevenson <dave.stevenson@raspberrypi.org>
-  *
-  * Based on vmcs_sm driver from Broadcom Corporation for some API,
-- * and taking some code for CMA/dmabuf handling from the Android Ion
-- * driver (Google/Linaro).
-+ * and taking some code for buffer allocation and dmabuf handling from
-+ * videobuf2.
-  *
-  *
-  * This driver has 3 main uses:
-@@ -52,7 +52,6 @@
- #include "vc_sm_cma_vchi.h"
- #include "vc_sm.h"
--#include "vc_sm_cma.h"
- #include "vc_sm_knl.h"
- #include <linux/broadcom/vc_sm_cma_ioctl.h>
-@@ -89,7 +88,6 @@ struct sm_state_t {
-       struct miscdevice misc_dev;
-       struct sm_instance *sm_handle;  /* Handle for videocore service. */
--      struct cma *cma_heap;
-       spinlock_t kernelid_map_lock;   /* Spinlock protecting kernelid_map */
-       struct idr kernelid_map;
-@@ -110,8 +108,9 @@ struct sm_state_t {
- struct vc_sm_dma_buf_attachment {
-       struct device *dev;
--      struct sg_table *table;
-+      struct sg_table sg_table;
-       struct list_head list;
-+      enum dma_data_direction dma_dir;
- };
- /* ---- Private Variables ----------------------------------------------- */
-@@ -202,9 +201,10 @@ static int vc_sm_cma_global_state_show(s
-                                          resource->import.attach);
-                               seq_printf(s, "           SGT          %p\n",
-                                          resource->import.sgt);
-+                      } else {
-+                              seq_printf(s, "           SGT          %p\n",
-+                                         resource->alloc.sg_table);
-                       }
--                      seq_printf(s, "           SG_TABLE     %p\n",
--                                 resource->sg_table);
-                       seq_printf(s, "           DMA_ADDR     %pad\n",
-                                  &resource->dma_addr);
-                       seq_printf(s, "           VC_HANDLE     %08x\n",
-@@ -296,8 +296,9 @@ static void vc_sm_vpu_free(struct vc_sm_
-  */
- static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
- {
--      pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
--               __func__, buffer, buffer->name, buffer->size);
-+      pr_debug("[%s]: buffer %p (name %s, size %zu), imported %u\n",
-+               __func__, buffer, buffer->name, buffer->size,
-+               buffer->imported);
-       if (buffer->vc_handle) {
-               /* We've sent the unmap request but not had the response. */
-@@ -313,8 +314,6 @@ static void vc_sm_release_resource(struc
-       /* Release the allocation (whether imported dmabuf or CMA allocation) */
-       if (buffer->imported) {
--              pr_debug("%s: Release imported dmabuf %p\n", __func__,
--                       buffer->import.dma_buf);
-               if (buffer->import.dma_buf)
-                       dma_buf_put(buffer->import.dma_buf);
-               else
-@@ -322,16 +321,8 @@ static void vc_sm_release_resource(struc
-                              __func__, buffer);
-               buffer->import.dma_buf = NULL;
-       } else {
--              if (buffer->sg_table) {
--                      /* Our own allocation that we need to dma_unmap_sg */
--                      dma_unmap_sg(&sm_state->pdev->dev,
--                                   buffer->sg_table->sgl,
--                                   buffer->sg_table->nents,
--                                   DMA_BIDIRECTIONAL);
--              }
--              pr_debug("%s: Release our allocation\n", __func__);
--              vc_sm_cma_buffer_free(&buffer->alloc);
--              pr_debug("%s: Release our allocation - done\n", __func__);
-+              dma_free_coherent(&sm_state->pdev->dev, buffer->size,
-+                                buffer->cookie, buffer->dma_addr);
-       }
-@@ -371,38 +362,6 @@ static struct vc_sm_privdata_t *vc_sm_cm
-       return file_data;
- }
--static struct sg_table *dup_sg_table(struct sg_table *table)
--{
--      struct sg_table *new_table;
--      int ret, i;
--      struct scatterlist *sg, *new_sg;
--
--      new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
--      if (!new_table)
--              return ERR_PTR(-ENOMEM);
--
--      ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
--      if (ret) {
--              kfree(new_table);
--              return ERR_PTR(ret);
--      }
--
--      new_sg = new_table->sgl;
--      for_each_sg(table->sgl, sg, table->nents, i) {
--              memcpy(new_sg, sg, sizeof(*sg));
--              sg->dma_address = 0;
--              new_sg = sg_next(new_sg);
--      }
--
--      return new_table;
--}
--
--static void free_duped_table(struct sg_table *table)
--{
--      sg_free_table(table);
--      kfree(table);
--}
--
- /* Dma buf operations for use with our own allocations */
- static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
-@@ -410,28 +369,45 @@ static int vc_sm_dma_buf_attach(struct d
- {
-       struct vc_sm_dma_buf_attachment *a;
--      struct sg_table *table;
-+      struct sg_table *sgt;
-       struct vc_sm_buffer *buf = dmabuf->priv;
-+      struct scatterlist *rd, *wr;
-+      int ret, i;
-       a = kzalloc(sizeof(*a), GFP_KERNEL);
-       if (!a)
-               return -ENOMEM;
--      table = dup_sg_table(buf->sg_table);
--      if (IS_ERR(table)) {
-+      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-+
-+      mutex_lock(&buf->lock);
-+
-+      INIT_LIST_HEAD(&a->list);
-+
-+      sgt = &a->sg_table;
-+
-+      /* Copy the buf->base_sgt scatter list to the attachment, as we can't
-+       * map the same scatter list to multiple attachments at the same time.
-+       */
-+      ret = sg_alloc_table(sgt, buf->alloc.sg_table->orig_nents, GFP_KERNEL);
-+      if (ret) {
-               kfree(a);
--              return PTR_ERR(table);
-+              return -ENOMEM;
-       }
--      a->table = table;
--      INIT_LIST_HEAD(&a->list);
-+      rd = buf->alloc.sg_table->sgl;
-+      wr = sgt->sgl;
-+      for (i = 0; i < sgt->orig_nents; ++i) {
-+              sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
-+              rd = sg_next(rd);
-+              wr = sg_next(wr);
-+      }
-+      a->dma_dir = DMA_NONE;
-       attachment->priv = a;
--      mutex_lock(&buf->lock);
-       list_add(&a->list, &buf->attachments);
-       mutex_unlock(&buf->lock);
--      pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-       return 0;
- }
-@@ -441,9 +417,20 @@ static void vc_sm_dma_buf_detach(struct
- {
-       struct vc_sm_dma_buf_attachment *a = attachment->priv;
-       struct vc_sm_buffer *buf = dmabuf->priv;
-+      struct sg_table *sgt;
-       pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
--      free_duped_table(a->table);
-+      if (!a)
-+              return;
-+
-+      sgt = &a->sg_table;
-+
-+      /* release the scatterlist cache */
-+      if (a->dma_dir != DMA_NONE)
-+              dma_unmap_sg(attachment->dev, sgt->sgl, sgt->orig_nents,
-+                           a->dma_dir);
-+      sg_free_table(sgt);
-+
-       mutex_lock(&buf->lock);
-       list_del(&a->list);
-       mutex_unlock(&buf->lock);
-@@ -455,13 +442,38 @@ static struct sg_table *vc_sm_map_dma_bu
-                                         enum dma_data_direction direction)
- {
-       struct vc_sm_dma_buf_attachment *a = attachment->priv;
-+      /* stealing dmabuf mutex to serialize map/unmap operations */
-+      struct mutex *lock = &attachment->dmabuf->lock;
-       struct sg_table *table;
--      table = a->table;
-+      mutex_lock(lock);
-+      pr_debug("%s attachment %p\n", __func__, attachment);
-+      table = &a->sg_table;
-+
-+      /* return previously mapped sg table */
-+      if (a->dma_dir == direction) {
-+              mutex_unlock(lock);
-+              return table;
-+      }
-+
-+      /* release any previous cache */
-+      if (a->dma_dir != DMA_NONE) {
-+              dma_unmap_sg(attachment->dev, table->sgl, table->orig_nents,
-+                           a->dma_dir);
-+              a->dma_dir = DMA_NONE;
-+      }
-+
-+      /* mapping to the client with new direction */
-+      table->nents = dma_map_sg(attachment->dev, table->sgl,
-+                                table->orig_nents, direction);
-+      if (!table->nents) {
-+              pr_err("failed to map scatterlist\n");
-+              mutex_unlock(lock);
-+              return ERR_PTR(-EIO);
-+      }
--      if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
--                      direction))
--              return ERR_PTR(-ENOMEM);
-+      a->dma_dir = direction;
-+      mutex_unlock(lock);
-       pr_debug("%s attachment %p\n", __func__, attachment);
-       return table;
-@@ -478,41 +490,26 @@ static void vc_sm_unmap_dma_buf(struct d
- static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
- {
-       struct vc_sm_buffer *buf = dmabuf->priv;
--      struct sg_table *table = buf->sg_table;
--      unsigned long addr = vma->vm_start;
--      unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
--      struct scatterlist *sg;
--      int i;
--      int ret = 0;
-+      int ret;
-       pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
--               buf, addr);
-+               buf, vma->vm_start);
-       mutex_lock(&buf->lock);
-       /* now map it to userspace */
--      for_each_sg(table->sgl, sg, table->nents, i) {
--              struct page *page = sg_page(sg);
--              unsigned long remainder = vma->vm_end - addr;
--              unsigned long len = sg->length;
-+      vma->vm_pgoff = 0;
--              if (offset >= sg->length) {
--                      offset -= sg->length;
--                      continue;
--              } else if (offset) {
--                      page += offset / PAGE_SIZE;
--                      len = sg->length - offset;
--                      offset = 0;
--              }
--              len = min(len, remainder);
--              ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
--                                    vma->vm_page_prot);
--              if (ret)
--                      break;
--              addr += len;
--              if (addr >= vma->vm_end)
--                      break;
-+      ret = dma_mmap_coherent(&sm_state->pdev->dev, vma, buf->cookie,
-+                              buf->dma_addr, buf->size);
-+
-+      if (ret) {
-+              pr_err("Remapping memory failed, error: %d\n", ret);
-+              return ret;
-       }
-+
-+      vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
-+
-       mutex_unlock(&buf->lock);
-       if (ret)
-@@ -570,8 +567,8 @@ static int vc_sm_dma_buf_begin_cpu_acces
-       mutex_lock(&buf->lock);
-       list_for_each_entry(a, &buf->attachments, list) {
--              dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
--                                  direction);
-+              dma_sync_sg_for_cpu(a->dev, a->sg_table.sgl,
-+                                  a->sg_table.nents, direction);
-       }
-       mutex_unlock(&buf->lock);
-@@ -593,8 +590,8 @@ static int vc_sm_dma_buf_end_cpu_access(
-       mutex_lock(&buf->lock);
-       list_for_each_entry(a, &buf->attachments, list) {
--              dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
--                                     direction);
-+              dma_sync_sg_for_device(a->dev, a->sg_table.sgl,
-+                                     a->sg_table.nents, direction);
-       }
-       mutex_unlock(&buf->lock);
-@@ -625,7 +622,9 @@ static const struct dma_buf_ops dma_buf_
-       .map = vc_sm_dma_buf_kmap,
-       .unmap = vc_sm_dma_buf_kunmap,
- };
-+
- /* Dma_buf operations for chaining through to an imported dma_buf */
-+
- static
- int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
-                               struct dma_buf_attachment *attachment)
-@@ -819,7 +818,7 @@ vc_sm_cma_import_dmabuf_internal(struct
-       import.type = VC_SM_ALLOC_NON_CACHED;
-       dma_addr = sg_dma_address(sgt->sgl);
--      import.addr = (uint32_t)dma_addr;
-+      import.addr = (u32)dma_addr;
-       if ((import.addr & 0xC0000000) != 0xC0000000) {
-               pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
-                      __func__, &dma_addr);
-@@ -911,11 +910,12 @@ error:
-       return ret;
- }
--static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
-+static int vc_sm_cma_vpu_alloc(u32 size, u32 align, const char *name,
-                              u32 mem_handle, struct vc_sm_buffer **ret_buffer)
- {
-       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-       struct vc_sm_buffer *buffer = NULL;
-+      struct sg_table *sgt;
-       int aligned_size;
-       int ret = 0;
-@@ -938,23 +938,34 @@ static int vc_sm_cma_vpu_alloc(u32 size,
-        */
-       mutex_lock(&buffer->lock);
--      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
--                                    aligned_size)) {
--              pr_err("[%s]: cma alloc of %d bytes failed\n",
-+      buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
-+                                          aligned_size, &buffer->dma_addr,
-+                                          GFP_KERNEL);
-+      if (!buffer->cookie) {
-+              pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
-                      __func__, aligned_size);
-               ret = -ENOMEM;
-               goto error;
-       }
--      buffer->sg_table = buffer->alloc.sg_table;
--      pr_debug("[%s]: cma alloc of %d bytes success\n",
-+      pr_debug("[%s]: alloc of %d bytes success\n",
-                __func__, aligned_size);
--      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
--                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
--              pr_err("[%s]: dma_map_sg failed\n", __func__);
-+      sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-+      if (!sgt) {
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
-+                            buffer->dma_addr, buffer->size);
-+      if (ret < 0) {
-+              pr_err("failed to get scatterlist from DMA API\n");
-+              kfree(sgt);
-+              ret = -ENOMEM;
-               goto error;
-       }
-+      buffer->alloc.sg_table = sgt;
-       INIT_LIST_HEAD(&buffer->attachments);
-@@ -971,10 +982,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
-               ret = PTR_ERR(buffer->dma_buf);
-               goto error;
-       }
--      buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+      buffer->dma_addr = (u32)sg_dma_address(buffer->alloc.sg_table->sgl);
-       if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
--              pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
--                     __func__, &buffer->dma_addr);
-+              pr_warn_once("%s: Expecting an uncached alias for dma_addr %pad\n",
-+                           __func__, &buffer->dma_addr);
-               buffer->dma_addr |= 0xC0000000;
-       }
-       buffer->private = sm_state->vpu_allocs;
-@@ -1145,6 +1156,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-       struct vc_sm_import import = { 0 };
-       struct vc_sm_import_result result = { 0 };
-       struct dma_buf *dmabuf = NULL;
-+      struct sg_table *sgt;
-       int aligned_size;
-       int ret = 0;
-       int status;
-@@ -1162,18 +1174,13 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-               goto error;
-       }
--      if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
--                                    aligned_size)) {
--              pr_err("[%s]: cma alloc of %d bytes failed\n",
-+      buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
-+                                          aligned_size,
-+                                          &buffer->dma_addr,
-+                                          GFP_KERNEL);
-+      if (!buffer->cookie) {
-+              pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
-                      __func__, aligned_size);
--              kfree(buffer);
--              return -ENOMEM;
--      }
--      buffer->sg_table = buffer->alloc.sg_table;
--
--      if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
--                     buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
--              pr_err("[%s]: dma_map_sg failed\n", __func__);
-               ret = -ENOMEM;
-               goto error;
-       }
-@@ -1204,7 +1211,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-       }
-       buffer->dma_buf = dmabuf;
--      import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+      import.addr = buffer->dma_addr;
-       import.size = aligned_size;
-       import.kernel_id = get_kernel_id(buffer);
-@@ -1229,10 +1236,25 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-       buffer->private = private;
-       buffer->vc_handle = result.res_handle;
-       buffer->size = import.size;
--      buffer->dma_addr = import.addr;
-       buffer->vpu_state = VPU_MAPPED;
-       buffer->kernel_id = import.kernel_id;
--      //buffer->res_cached = ioparam->cached;
-+
-+      sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-+      if (!sgt) {
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+
-+      ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
-+                            buffer->dma_addr, buffer->size);
-+      if (ret < 0) {
-+              /* FIXME: error handling */
-+              pr_err("failed to get scatterlist from DMA API\n");
-+              kfree(sgt);
-+              ret = -ENOMEM;
-+              goto error;
-+      }
-+      buffer->alloc.sg_table = sgt;
-       fd = dma_buf_fd(dmabuf, O_CLOEXEC);
-       if (fd < 0)
-@@ -1250,11 +1272,19 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-       return 0;
- error:
--      if (buffer) {
--              pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
--                     ret);
-+      pr_err("[%s]: something failed - cleanup. ret %d\n", __func__, ret);
-+      if (dmabuf) {
-+              /* dmabuf has been exported, therefore allow dmabuf cleanup to
-+               * deal with this
-+               */
-               dma_buf_put(dmabuf);
-+      } else {
-+              /* No dmabuf, therefore just free the buffer here */
-+              if (buffer->cookie)
-+                      dma_free_coherent(&sm_state->pdev->dev, buffer->size,
-+                                        buffer->cookie, buffer->dma_addr);
-+              kfree(buffer);
-       }
-       return ret;
- }
-@@ -1527,13 +1557,6 @@ static void vc_sm_connected_init(void)
-       pr_info("[%s]: start\n", __func__);
--      vc_sm_cma_add_heaps(&sm_state->cma_heap);
--      if (!sm_state->cma_heap) {
--              pr_err("[%s]: failed to initialise CMA heap\n",
--                     __func__);
--              return;
--      }
--
-       /*
-        * Initialize and create a VCHI connection for the shared memory service
-        * running on videocore.
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-@@ -21,8 +21,6 @@
- #include <linux/types.h>
- #include <linux/miscdevice.h>
--#include "vc_sm_cma.h"
--
- #define VC_SM_MAX_NAME_LEN 32
- enum vc_sm_vpu_mapping_state {
-@@ -31,6 +29,12 @@ enum vc_sm_vpu_mapping_state {
-       VPU_UNMAPPING
- };
-+struct vc_sm_alloc_data {
-+      unsigned long num_pages;
-+      void *priv_virt;
-+      struct sg_table *sg_table;
-+};
-+
- struct vc_sm_imported {
-       struct dma_buf *dma_buf;
-       struct dma_buf_attachment *attach;
-@@ -56,8 +60,6 @@ struct vc_sm_buffer {
-       int in_use:1;   /* Kernel is still using this resource */
-       int imported:1; /* Imported dmabuf */
--      struct sg_table *sg_table;
--
-       enum vc_sm_vpu_mapping_state vpu_state;
-       u32 vc_handle;  /* VideoCore handle for this buffer */
-       int vpu_allocated;      /*
-@@ -69,11 +71,12 @@ struct vc_sm_buffer {
-       /* DMABUF related fields */
-       struct dma_buf *dma_buf;
-       dma_addr_t dma_addr;
-+      void *cookie;
-       struct vc_sm_privdata_t *private;
-       union {
--              struct vc_sm_cma_alloc_data alloc;
-+              struct vc_sm_alloc_data alloc;
-               struct vc_sm_imported import;
-       };
- };
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-+++ /dev/null
-@@ -1,98 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0
--/*
-- * VideoCore Shared Memory CMA allocator
-- *
-- * Copyright: 2018, Raspberry Pi (Trading) Ltd
-- *
-- * Based on the Android ION allocator
-- * Copyright (C) Linaro 2012
-- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-- *
-- */
--
--#include <linux/slab.h>
--#include <linux/errno.h>
--#include <linux/err.h>
--#include <linux/cma.h>
--#include <linux/scatterlist.h>
--
--#include "vc_sm_cma.h"
--
--/* CMA heap operations functions */
--int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
--                            struct vc_sm_cma_alloc_data *buffer,
--                            unsigned long len)
--{
--      /* len should already be page aligned */
--      unsigned long num_pages = len / PAGE_SIZE;
--      struct sg_table *table;
--      struct page *pages;
--      int ret;
--
--      pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
--      if (!pages)
--              return -ENOMEM;
--
--      table = kmalloc(sizeof(*table), GFP_KERNEL);
--      if (!table)
--              goto err;
--
--      ret = sg_alloc_table(table, 1, GFP_KERNEL);
--      if (ret)
--              goto free_mem;
--
--      sg_set_page(table->sgl, pages, len, 0);
--
--      buffer->priv_virt = pages;
--      buffer->sg_table = table;
--      buffer->cma_heap = cma_heap;
--      buffer->num_pages = num_pages;
--      return 0;
--
--free_mem:
--      kfree(table);
--err:
--      cma_release(cma_heap, pages, num_pages);
--      return -ENOMEM;
--}
--
--void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
--{
--      struct cma *cma_heap = buffer->cma_heap;
--      struct page *pages = buffer->priv_virt;
--
--      /* release memory */
--      if (cma_heap)
--              cma_release(cma_heap, pages, buffer->num_pages);
--
--      /* release sg table */
--      if (buffer->sg_table) {
--              sg_free_table(buffer->sg_table);
--              kfree(buffer->sg_table);
--              buffer->sg_table = NULL;
--      }
--}
--
--int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
--{
--      struct cma **heap = (struct cma **)priv;
--      const char *name = cma_get_name(cma);
--
--      if (!(*heap)) {
--              phys_addr_t phys_addr = cma_get_base(cma);
--
--              pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
--                       __func__, name, &phys_addr, cma_get_size(cma));
--              *heap = cma;
--      } else {
--              pr_err("%s: Ignoring heap %s as already set\n",
--                     __func__, name);
--      }
--
--      return 0;
--}
--
--void vc_sm_cma_add_heaps(struct cma **cma_heap)
--{
--      cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
--}
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-+++ /dev/null
-@@ -1,39 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--
--/*
-- * VideoCore Shared Memory CMA allocator
-- *
-- * Copyright: 2018, Raspberry Pi (Trading) Ltd
-- *
-- * Based on the Android ION allocator
-- * Copyright (C) Linaro 2012
-- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-- *
-- * This software is licensed under the terms of the GNU General Public
-- * License version 2, as published by the Free Software Foundation, and
-- * may be copied, distributed, and modified under those terms.
-- *
-- * 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.
-- *
-- */
--#ifndef VC_SM_CMA_H
--#define VC_SM_CMA_H
--
--struct vc_sm_cma_alloc_data {
--      struct cma *cma_heap;
--      unsigned long num_pages;
--      void *priv_virt;
--      struct sg_table *sg_table;
--};
--
--int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
--                            struct vc_sm_cma_alloc_data *buffer,
--                            unsigned long len);
--void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
--
--void vc_sm_cma_add_heaps(struct cma **cma_heap);
--
--#endif
diff --git a/target/linux/brcm2708/patches-4.19/950-0601-media-vb2-set-reqbufs-create_bufs-capabilities.patch b/target/linux/brcm2708/patches-4.19/950-0601-media-vb2-set-reqbufs-create_bufs-capabilities.patch
new file mode 100644 (file)
index 0000000..bd99cba
--- /dev/null
@@ -0,0 +1,190 @@
+From 7410e35a4936b89f2e227c52058c11f1574bbfca Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hansverk@cisco.com>
+Date: Thu, 23 Aug 2018 10:18:35 -0400
+Subject: [PATCH] media: vb2: set reqbufs/create_bufs capabilities
+
+Upstream commit e5079cf11373e4cc98be8b1072aece429eb2d4d2.
+
+Set the capabilities field of v4l2_requestbuffers and v4l2_create_buffers.
+
+The various mapping modes were easy, but for signaling the request capability
+a new 'supports_requests' bitfield was added to videobuf2-core.h (and set in
+vim2m and vivid). Drivers have to set this bitfield for any queue where
+requests are supported.
+
+Signed-off-by: Hans Verkuil <hansverk@cisco.com>
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+
+Minor modifications required on the backport
+---
+ drivers/media/common/videobuf2/videobuf2-v4l2.c | 17 +++++++++++++++++
+ drivers/media/platform/vim2m.c                  |  1 +
+ drivers/media/platform/vivid/vivid-core.c       |  5 +++++
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c   |  4 +++-
+ drivers/media/v4l2-core/v4l2-ioctl.c            |  4 ++--
+ include/media/videobuf2-core.h                  |  2 ++
+ 6 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
++++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
+@@ -482,10 +482,24 @@ int vb2_querybuf(struct vb2_queue *q, st
+ }
+ EXPORT_SYMBOL(vb2_querybuf);
++static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
++{
++      *caps = 0;
++      if (q->io_modes & VB2_MMAP)
++              *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
++      if (q->io_modes & VB2_USERPTR)
++              *caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR;
++      if (q->io_modes & VB2_DMABUF)
++              *caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF;
++      if (q->supports_requests)
++              *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
++}
++
+ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+ {
+       int ret = vb2_verify_memory_type(q, req->memory, req->type);
++      fill_buf_caps(q, &req->capabilities);
+       return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
+ }
+ EXPORT_SYMBOL_GPL(vb2_reqbufs);
+@@ -513,6 +527,7 @@ int vb2_create_bufs(struct vb2_queue *q,
+       int ret = vb2_verify_memory_type(q, create->memory, f->type);
+       unsigned i;
++      fill_buf_caps(q, &create->capabilities);
+       create->index = q->num_buffers;
+       if (create->count == 0)
+               return ret != -EBUSY ? ret : 0;
+@@ -713,6 +728,7 @@ int vb2_ioctl_reqbufs(struct file *file,
+       struct video_device *vdev = video_devdata(file);
+       int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
++      fill_buf_caps(vdev->queue, &p->capabilities);
+       if (res)
+               return res;
+       if (vb2_queue_is_busy(vdev, file))
+@@ -734,6 +750,7 @@ int vb2_ioctl_create_bufs(struct file *f
+                       p->format.type);
+       p->index = vdev->queue->num_buffers;
++      fill_buf_caps(vdev->queue, &p->capabilities);
+       /*
+        * If count == 0, then just check if memory and type are valid.
+        * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
+--- a/drivers/media/platform/vim2m.c
++++ b/drivers/media/platform/vim2m.c
+@@ -840,6 +840,7 @@ static int queue_init(void *priv, struct
+       src_vq->mem_ops = &vb2_vmalloc_memops;
+       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->dev->dev_mutex;
++      src_vq->supports_requests = true;
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+--- a/drivers/media/platform/vivid/vivid-core.c
++++ b/drivers/media/platform/vivid/vivid-core.c
+@@ -1060,6 +1060,7 @@ static int vivid_create_instance(struct
+               q->min_buffers_needed = 2;
+               q->lock = &dev->mutex;
+               q->dev = dev->v4l2_dev.dev;
++              q->supports_requests = true;
+               ret = vb2_queue_init(q);
+               if (ret)
+@@ -1080,6 +1081,7 @@ static int vivid_create_instance(struct
+               q->min_buffers_needed = 2;
+               q->lock = &dev->mutex;
+               q->dev = dev->v4l2_dev.dev;
++              q->supports_requests = true;
+               ret = vb2_queue_init(q);
+               if (ret)
+@@ -1100,6 +1102,7 @@ static int vivid_create_instance(struct
+               q->min_buffers_needed = 2;
+               q->lock = &dev->mutex;
+               q->dev = dev->v4l2_dev.dev;
++              q->supports_requests = true;
+               ret = vb2_queue_init(q);
+               if (ret)
+@@ -1120,6 +1123,7 @@ static int vivid_create_instance(struct
+               q->min_buffers_needed = 2;
+               q->lock = &dev->mutex;
+               q->dev = dev->v4l2_dev.dev;
++              q->supports_requests = true;
+               ret = vb2_queue_init(q);
+               if (ret)
+@@ -1139,6 +1143,7 @@ static int vivid_create_instance(struct
+               q->min_buffers_needed = 8;
+               q->lock = &dev->mutex;
+               q->dev = dev->v4l2_dev.dev;
++              q->supports_requests = true;
+               ret = vb2_queue_init(q);
+               if (ret)
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -251,7 +251,8 @@ struct v4l2_create_buffers32 {
+       __u32                   count;
+       __u32                   memory; /* enum v4l2_memory */
+       struct v4l2_format32    format;
+-      __u32                   reserved[8];
++      __u32                   capabilities;
++      __u32                   reserved[7];
+ };
+ static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
+@@ -411,6 +412,7 @@ static int put_v4l2_create32(struct v4l2
+       if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+           copy_in_user(p32, p64,
+                        offsetof(struct v4l2_create_buffers32, format)) ||
++          assign_in_user(&p32->capabilities, &p64->capabilities) ||
+           copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
+               return -EFAULT;
+       return __put_v4l2_format32(&p64->format, &p32->format);
+--- a/drivers/media/v4l2-core/v4l2-ioctl.c
++++ b/drivers/media/v4l2-core/v4l2-ioctl.c
+@@ -1882,7 +1882,7 @@ static int v4l_reqbufs(const struct v4l2
+       if (ret)
+               return ret;
+-      CLEAR_AFTER_FIELD(p, memory);
++      CLEAR_AFTER_FIELD(p, capabilities);
+       return ops->vidioc_reqbufs(file, fh, p);
+ }
+@@ -1923,7 +1923,7 @@ static int v4l_create_bufs(const struct
+       if (ret)
+               return ret;
+-      CLEAR_AFTER_FIELD(create, format);
++      CLEAR_AFTER_FIELD(create, capabilities);
+       v4l_sanitize_format(&create->format);
+--- a/include/media/videobuf2-core.h
++++ b/include/media/videobuf2-core.h
+@@ -449,6 +449,7 @@ struct vb2_buf_ops {
+  * @quirk_poll_must_check_waiting_for_buffers: Return %EPOLLERR at poll when QBUF
+  *              has not been called. This is a vb1 idiom that has been adopted
+  *              also by vb2.
++ * @supports_requests: this queue supports the Request API.
+  * @lock:     pointer to a mutex that protects the &struct vb2_queue. The
+  *            driver can set this to a mutex to let the v4l2 core serialize
+  *            the queuing ioctls. If the driver wants to handle locking
+@@ -516,6 +517,7 @@ struct vb2_queue {
+       unsigned                        fileio_write_immediately:1;
+       unsigned                        allow_zero_bytesused:1;
+       unsigned                   quirk_poll_must_check_waiting_for_buffers:1;
++      unsigned                        supports_requests:1;
+       struct mutex                    *lock;
+       void                            *owner;
diff --git a/target/linux/brcm2708/patches-4.19/950-0601-staging-vc-sm-cma-Fix-the-few-remaining-coding-style.patch b/target/linux/brcm2708/patches-4.19/950-0601-staging-vc-sm-cma-Fix-the-few-remaining-coding-style.patch
deleted file mode 100644 (file)
index 6c61023..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-From 38ae4957840ff9578a497422a8ca758549f734d5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 2 Jul 2019 17:19:04 +0100
-Subject: [PATCH] staging: vc-sm-cma: Fix the few remaining coding
- style issues
-
-Fix a few minor checkpatch complaints to make the driver clean
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c   |   6 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c  | 128 +++++++++---------
- 2 files changed, 65 insertions(+), 69 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -325,7 +325,6 @@ static void vc_sm_release_resource(struc
-                                 buffer->cookie, buffer->dma_addr);
-       }
--
-       /* Free our buffer. Start by removing it from the list */
-       mutex_lock(&sm_state->map_lock);
-       list_del(&buffer->global_buffer_list);
-@@ -1365,7 +1364,8 @@ static int vc_sm_cma_clean_invalid2(unsi
-       }
-       for (i = 0; i < ioparam.op_count; i++) {
--              const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
-+              const struct vc_sm_cma_ioctl_clean_invalid_block * const op =
-+                                                              block + i;
-               if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
-                       continue;
-@@ -1637,8 +1637,6 @@ err_remove_misc_dev:
- err_remove_debugfs:
-       debugfs_remove_recursive(sm_state->dir_root);
-       vc_sm_cma_vchi_stop(&sm_state->sm_handle);
--
--      return;
- }
- /* Driver loading. */
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -188,79 +188,77 @@ static int vc_sm_cma_vchi_videocore_io(v
-               if (svc_use)
-                       vchi_service_release(instance->vchi_handle[0]);
-               svc_use = 0;
--              if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
--                      vchi_service_use(instance->vchi_handle[0]);
--                      svc_use = 1;
--
--                      do {
--                              /*
--                               * Get new command and move it to response list
--                               */
--                              mutex_lock(&instance->lock);
--                              if (list_empty(&instance->cmd_list)) {
--                                      /* no more commands to process */
--                                      mutex_unlock(&instance->lock);
--                                      break;
--                              }
--                              cmd =
--                                  list_first_entry(&instance->cmd_list,
--                                                   struct sm_cmd_rsp_blk,
--                                                   head);
--                              list_move(&cmd->head, &instance->rsp_list);
--                              cmd->sent = 1;
--                              mutex_unlock(&instance->lock);
--                              /* Send the command */
--                              status = bcm2835_vchi_msg_queue(
--                                              instance->vchi_handle[0],
--                                              cmd->msg, cmd->length);
--                              if (status) {
--                                      pr_err("%s: failed to queue message (%d)",
--                                             __func__, status);
--                              }
--
--                              /* If no reply is needed then we're done */
--                              if (!cmd->wait) {
--                                      mutex_lock(&instance->lock);
--                                      list_del(&cmd->head);
--                                      mutex_unlock(&instance->lock);
--                                      vc_vchi_cmd_delete(instance, cmd);
--                                      continue;
--                              }
--
--                              if (status) {
--                                      complete(&cmd->cmplt);
--                                      continue;
--                              }
--
--                      } while (1);
--
--                      while (!vchi_msg_peek(instance->vchi_handle[0],
--                                            (void **)&reply, &reply_len,
--                                            VCHI_FLAGS_NONE)) {
--                              if (reply->trans_id & 0x80000000) {
--                                      /* Async event or cmd from the VPU */
--                                      if (instance->vpu_event)
--                                              instance->vpu_event(
--                                                      instance, reply,
--                                                      reply_len);
--                              } else {
--                                      vc_sm_cma_vchi_rx_ack(instance, cmd,
--                                                            reply, reply_len);
--                              }
-+              if (wait_for_completion_interruptible(&instance->io_cmplt))
-+                      continue;
--                              vchi_msg_remove(instance->vchi_handle[0]);
--                      }
-+              vchi_service_use(instance->vchi_handle[0]);
-+              svc_use = 1;
--                      /* Go through the dead list and free them */
-+              do {
-+                      /*
-+                       * Get new command and move it to response list
-+                       */
-                       mutex_lock(&instance->lock);
--                      list_for_each_entry_safe(cmd, cmd_tmp,
--                                               &instance->dead_list, head) {
-+                      if (list_empty(&instance->cmd_list)) {
-+                              /* no more commands to process */
-+                              mutex_unlock(&instance->lock);
-+                              break;
-+                      }
-+                      cmd = list_first_entry(&instance->cmd_list,
-+                                             struct sm_cmd_rsp_blk, head);
-+                      list_move(&cmd->head, &instance->rsp_list);
-+                      cmd->sent = 1;
-+                      mutex_unlock(&instance->lock);
-+
-+                      /* Send the command */
-+                      status =
-+                              bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+                                                     cmd->msg, cmd->length);
-+                      if (status) {
-+                              pr_err("%s: failed to queue message (%d)",
-+                                     __func__, status);
-+                      }
-+
-+                      /* If no reply is needed then we're done */
-+                      if (!cmd->wait) {
-+                              mutex_lock(&instance->lock);
-                               list_del(&cmd->head);
-+                              mutex_unlock(&instance->lock);
-                               vc_vchi_cmd_delete(instance, cmd);
-+                              continue;
-                       }
--                      mutex_unlock(&instance->lock);
-+
-+                      if (status) {
-+                              complete(&cmd->cmplt);
-+                              continue;
-+                      }
-+
-+              } while (1);
-+
-+              while (!vchi_msg_peek(instance->vchi_handle[0], (void **)&reply,
-+                                    &reply_len, VCHI_FLAGS_NONE)) {
-+                      if (reply->trans_id & 0x80000000) {
-+                              /* Async event or cmd from the VPU */
-+                              if (instance->vpu_event)
-+                                      instance->vpu_event(instance, reply,
-+                                                          reply_len);
-+                      } else {
-+                              vc_sm_cma_vchi_rx_ack(instance, cmd, reply,
-+                                                    reply_len);
-+                      }
-+
-+                      vchi_msg_remove(instance->vchi_handle[0]);
-+              }
-+
-+              /* Go through the dead list and free them */
-+              mutex_lock(&instance->lock);
-+              list_for_each_entry_safe(cmd, cmd_tmp, &instance->dead_list,
-+                                       head) {
-+                      list_del(&cmd->head);
-+                      vc_vchi_cmd_delete(instance, cmd);
-               }
-+              mutex_unlock(&instance->lock);
-       }
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0602-media-vb2-Allow-reqbufs-0-with-in-use-MMAP-buffers.patch b/target/linux/brcm2708/patches-4.19/950-0602-media-vb2-Allow-reqbufs-0-with-in-use-MMAP-buffers.patch
new file mode 100644 (file)
index 0000000..755ca34
--- /dev/null
@@ -0,0 +1,130 @@
+From 16cf378051d7fff6772a7acaecbacddec7822330 Mon Sep 17 00:00:00 2001
+From: John Sheu <sheu@chromium.org>
+Date: Thu, 15 Nov 2018 10:57:16 -0500
+Subject: [PATCH] media: vb2: Allow reqbufs(0) with "in use" MMAP
+ buffers
+
+Upstream commit d644cca50f366cd109845ae92e37c09ed79adf81
+
+Videobuf2 presently does not allow VIDIOC_REQBUFS to destroy outstanding
+buffers if the queue is of type V4L2_MEMORY_MMAP, and if the buffers are
+considered "in use".  This is different behavior than for other memory
+types and prevents us from deallocating buffers in following two cases:
+
+1) There are outstanding mmap()ed views on the buffer. However even if
+   we put the buffer in reqbufs(0), there will be remaining references,
+   due to vma .open/close() adjusting vb2 buffer refcount appropriately.
+   This means that the buffer will be in fact freed only when the last
+   mmap()ed view is unmapped.
+
+2) Buffer has been exported as a DMABUF. Refcount of the vb2 buffer
+   is managed properly by VB2 DMABUF ops, i.e. incremented on DMABUF
+   get and decremented on DMABUF release. This means that the buffer
+   will be alive until all importers release it.
+
+Considering both cases above, there does not seem to be any need to
+prevent reqbufs(0) operation, because buffer lifetime is already
+properly managed by both mmap() and DMABUF code paths. Let's remove it
+and allow userspace freeing the queue (and potentially allocating a new
+one) even though old buffers might be still in processing.
+
+To let userspace know that the kernel now supports orphaning buffers
+that are still in use, add a new V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS
+to be set by reqbufs and create_bufs.
+
+[p.zabel@pengutronix.de: added V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS,
+ updated documentation, and added back debug message]
+
+Signed-off-by: John Sheu <sheu@chromium.org>
+Reviewed-by: Pawel Osciak <posciak@chromium.org>
+Signed-off-by: Tomasz Figa <tfiga@chromium.org>
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+[hverkuil-cisco@xs4all.nl: added V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS ref]
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+---
+ Documentation/media/uapi/v4l/vidioc-reqbufs.rst | 17 ++++++++++++++---
+ drivers/media/common/videobuf2/videobuf2-core.c |  8 +++-----
+ drivers/media/common/videobuf2/videobuf2-v4l2.c |  2 +-
+ include/uapi/linux/videodev2.h                  |  1 +
+ 4 files changed, 19 insertions(+), 9 deletions(-)
+
+--- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
++++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
+@@ -59,9 +59,14 @@ When the I/O method is not supported the
+ code.
+ Applications can call :ref:`VIDIOC_REQBUFS` again to change the number of
+-buffers, however this cannot succeed when any buffers are still mapped.
+-A ``count`` value of zero frees all buffers, after aborting or finishing
+-any DMA in progress, an implicit
++buffers. Note that if any buffers are still mapped or exported via DMABUF,
++then :ref:`VIDIOC_REQBUFS` can only succeed if the
++``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` capability is set. Otherwise
++:ref:`VIDIOC_REQBUFS` will return the ``EBUSY`` error code.
++If ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` is set, then these buffers are
++orphaned and will be freed when they are unmapped or when the exported DMABUF
++fds are closed. A ``count`` value of zero frees or orphans all buffers, after
++aborting or finishing any DMA in progress, an implicit
+ :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`.
+@@ -112,6 +117,7 @@ any DMA in progress, an implicit
+ .. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
+ .. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
+ .. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
++.. _V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS:
+ .. cssclass:: longtable
+@@ -132,6 +138,11 @@ any DMA in progress, an implicit
+     * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
+       - 0x00000008
+       - This buffer type supports :ref:`requests <media-request-api>`.
++    * - ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS``
++      - 0x00000010
++      - The kernel allows calling :ref:`VIDIOC_REQBUFS` while buffers are still
++        mapped or exported via DMABUF. These orphaned buffers will be freed
++        when they are unmapped or when the exported DMABUF fds are closed.
+ Return Value
+ ============
+--- a/drivers/media/common/videobuf2/videobuf2-core.c
++++ b/drivers/media/common/videobuf2/videobuf2-core.c
+@@ -684,11 +684,9 @@ int vb2_core_reqbufs(struct vb2_queue *q
+                * are not in use and can be freed.
+                */
+               mutex_lock(&q->mmap_lock);
+-              if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
+-                      mutex_unlock(&q->mmap_lock);
+-                      dprintk(1, "memory in use, cannot free\n");
+-                      return -EBUSY;
+-              }
++              if (debug && q->memory == VB2_MEMORY_MMAP &&
++                  __buffers_in_use(q))
++                      dprintk(1, "memory in use, orphaning buffers\n");
+               /*
+                * Call queue_cancel to clean up any buffers in the PREPARED or
+--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
++++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
+@@ -484,7 +484,7 @@ EXPORT_SYMBOL(vb2_querybuf);
+ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
+ {
+-      *caps = 0;
++      *caps = V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
+       if (q->io_modes & VB2_MMAP)
+               *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
+       if (q->io_modes & VB2_USERPTR)
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -881,6 +881,7 @@ struct v4l2_requestbuffers {
+ #define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
+ #define V4L2_BUF_CAP_SUPPORTS_DMABUF  (1 << 2)
+ #define V4L2_BUF_CAP_SUPPORTS_REQUESTS        (1 << 3)
++#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4)
+ /**
+  * struct v4l2_plane - plane info for multi-planar buffers
diff --git a/target/linux/brcm2708/patches-4.19/950-0602-media-videodev2.h-add-new-capabilities-for-buffer-ty.patch b/target/linux/brcm2708/patches-4.19/950-0602-media-videodev2.h-add-new-capabilities-for-buffer-ty.patch
deleted file mode 100644 (file)
index 8f3e72c..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-From ebd995296afa99a5c53f164e595f7a6d41d32a01 Mon Sep 17 00:00:00 2001
-From: Hans Verkuil <hansverk@cisco.com>
-Date: Thu, 23 Aug 2018 09:56:22 -0400
-Subject: [PATCH] media: videodev2.h: add new capabilities for buffer
- types
-
-Upstream commit f35f5d72e70e6b91389eb98fcabf43b79f40587f
-
-VIDIOC_REQBUFS and VIDIOC_CREATE_BUFFERS will return capabilities
-telling userspace what the given buffer type is capable of.
-
-Signed-off-by: Hans Verkuil <hansverk@cisco.com>
-Reviewed-by: Tomasz Figa <tfiga@chromium.org>
-Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
-Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
----
- .../media/uapi/v4l/vidioc-create-bufs.rst     | 14 ++++++-
- .../media/uapi/v4l/vidioc-reqbufs.rst         | 42 ++++++++++++++++++-
- include/uapi/linux/videodev2.h                | 13 +++++-
- 3 files changed, 65 insertions(+), 4 deletions(-)
-
---- a/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
-+++ b/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
-@@ -102,7 +102,19 @@ than the number requested.
-       - ``format``
-       - Filled in by the application, preserved by the driver.
-     * - __u32
--      - ``reserved``\ [8]
-+      - ``capabilities``
-+      - Set by the driver. If 0, then the driver doesn't support
-+        capabilities. In that case all you know is that the driver is
-+      guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
-+      other :c:type:`v4l2_memory` types. It will not support any others
-+      capabilities. See :ref:`here <v4l2-buf-capabilities>` for a list of the
-+      capabilities.
-+
-+      If you want to just query the capabilities without making any
-+      other changes, then set ``count`` to 0, ``memory`` to
-+      ``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
-+    * - __u32
-+      - ``reserved``\ [7]
-       - A place holder for future extensions. Drivers and applications
-       must set the array to zero.
---- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-+++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-@@ -88,10 +88,50 @@ any DMA in progress, an implicit
-       ``V4L2_MEMORY_DMABUF`` or ``V4L2_MEMORY_USERPTR``. See
-       :c:type:`v4l2_memory`.
-     * - __u32
--      - ``reserved``\ [2]
-+      - ``capabilities``
-+      - Set by the driver. If 0, then the driver doesn't support
-+        capabilities. In that case all you know is that the driver is
-+      guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
-+      other :c:type:`v4l2_memory` types. It will not support any others
-+      capabilities.
-+
-+      If you want to query the capabilities with a minimum of side-effects,
-+      then this can be called with ``count`` set to 0, ``memory`` set to
-+      ``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will
-+      free any previously allocated buffers, so this is typically something
-+      that will be done at the start of the application.
-+    * - __u32
-+      - ``reserved``\ [1]
-       - A place holder for future extensions. Drivers and applications
-       must set the array to zero.
-+.. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}|
-+
-+.. _v4l2-buf-capabilities:
-+.. _V4L2-BUF-CAP-SUPPORTS-MMAP:
-+.. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
-+.. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
-+.. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
-+
-+.. cssclass:: longtable
-+
-+.. flat-table:: V4L2 Buffer Capabilities Flags
-+    :header-rows:  0
-+    :stub-columns: 0
-+    :widths:       3 1 4
-+
-+    * - ``V4L2_BUF_CAP_SUPPORTS_MMAP``
-+      - 0x00000001
-+      - This buffer type supports the ``V4L2_MEMORY_MMAP`` streaming mode.
-+    * - ``V4L2_BUF_CAP_SUPPORTS_USERPTR``
-+      - 0x00000002
-+      - This buffer type supports the ``V4L2_MEMORY_USERPTR`` streaming mode.
-+    * - ``V4L2_BUF_CAP_SUPPORTS_DMABUF``
-+      - 0x00000004
-+      - This buffer type supports the ``V4L2_MEMORY_DMABUF`` streaming mode.
-+    * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
-+      - 0x00000008
-+      - This buffer type supports :ref:`requests <media-request-api>`.
- Return Value
- ============
---- a/include/uapi/linux/videodev2.h
-+++ b/include/uapi/linux/videodev2.h
-@@ -872,9 +872,16 @@ struct v4l2_requestbuffers {
-       __u32                   count;
-       __u32                   type;           /* enum v4l2_buf_type */
-       __u32                   memory;         /* enum v4l2_memory */
--      __u32                   reserved[2];
-+      __u32                   capabilities;
-+      __u32                   reserved[1];
- };
-+/* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
-+#define V4L2_BUF_CAP_SUPPORTS_MMAP    (1 << 0)
-+#define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
-+#define V4L2_BUF_CAP_SUPPORTS_DMABUF  (1 << 2)
-+#define V4L2_BUF_CAP_SUPPORTS_REQUESTS        (1 << 3)
-+
- /**
-  * struct v4l2_plane - plane info for multi-planar buffers
-  * @bytesused:                number of bytes occupied by data in the plane (payload)
-@@ -2318,6 +2325,7 @@ struct v4l2_dbg_chip_info {
-  *            return: number of created buffers
-  * @memory:   enum v4l2_memory; buffer memory type
-  * @format:   frame format, for which buffers are requested
-+ * @capabilities: capabilities of this buffer type.
-  * @reserved: future extensions
-  */
- struct v4l2_create_buffers {
-@@ -2325,7 +2333,8 @@ struct v4l2_create_buffers {
-       __u32                   count;
-       __u32                   memory;
-       struct v4l2_format      format;
--      __u32                   reserved[8];
-+      __u32                   capabilities;
-+      __u32                   reserved[7];
- };
- /*
diff --git a/target/linux/brcm2708/patches-4.19/950-0603-media-vb2-set-reqbufs-create_bufs-capabilities.patch b/target/linux/brcm2708/patches-4.19/950-0603-media-vb2-set-reqbufs-create_bufs-capabilities.patch
deleted file mode 100644 (file)
index bd99cba..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-From 7410e35a4936b89f2e227c52058c11f1574bbfca Mon Sep 17 00:00:00 2001
-From: Hans Verkuil <hansverk@cisco.com>
-Date: Thu, 23 Aug 2018 10:18:35 -0400
-Subject: [PATCH] media: vb2: set reqbufs/create_bufs capabilities
-
-Upstream commit e5079cf11373e4cc98be8b1072aece429eb2d4d2.
-
-Set the capabilities field of v4l2_requestbuffers and v4l2_create_buffers.
-
-The various mapping modes were easy, but for signaling the request capability
-a new 'supports_requests' bitfield was added to videobuf2-core.h (and set in
-vim2m and vivid). Drivers have to set this bitfield for any queue where
-requests are supported.
-
-Signed-off-by: Hans Verkuil <hansverk@cisco.com>
-Reviewed-by: Tomasz Figa <tfiga@chromium.org>
-Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
-Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-
-Minor modifications required on the backport
----
- drivers/media/common/videobuf2/videobuf2-v4l2.c | 17 +++++++++++++++++
- drivers/media/platform/vim2m.c                  |  1 +
- drivers/media/platform/vivid/vivid-core.c       |  5 +++++
- drivers/media/v4l2-core/v4l2-compat-ioctl32.c   |  4 +++-
- drivers/media/v4l2-core/v4l2-ioctl.c            |  4 ++--
- include/media/videobuf2-core.h                  |  2 ++
- 6 files changed, 30 insertions(+), 3 deletions(-)
-
---- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
-+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
-@@ -482,10 +482,24 @@ int vb2_querybuf(struct vb2_queue *q, st
- }
- EXPORT_SYMBOL(vb2_querybuf);
-+static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
-+{
-+      *caps = 0;
-+      if (q->io_modes & VB2_MMAP)
-+              *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
-+      if (q->io_modes & VB2_USERPTR)
-+              *caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR;
-+      if (q->io_modes & VB2_DMABUF)
-+              *caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF;
-+      if (q->supports_requests)
-+              *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
-+}
-+
- int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
- {
-       int ret = vb2_verify_memory_type(q, req->memory, req->type);
-+      fill_buf_caps(q, &req->capabilities);
-       return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
- }
- EXPORT_SYMBOL_GPL(vb2_reqbufs);
-@@ -513,6 +527,7 @@ int vb2_create_bufs(struct vb2_queue *q,
-       int ret = vb2_verify_memory_type(q, create->memory, f->type);
-       unsigned i;
-+      fill_buf_caps(q, &create->capabilities);
-       create->index = q->num_buffers;
-       if (create->count == 0)
-               return ret != -EBUSY ? ret : 0;
-@@ -713,6 +728,7 @@ int vb2_ioctl_reqbufs(struct file *file,
-       struct video_device *vdev = video_devdata(file);
-       int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
-+      fill_buf_caps(vdev->queue, &p->capabilities);
-       if (res)
-               return res;
-       if (vb2_queue_is_busy(vdev, file))
-@@ -734,6 +750,7 @@ int vb2_ioctl_create_bufs(struct file *f
-                       p->format.type);
-       p->index = vdev->queue->num_buffers;
-+      fill_buf_caps(vdev->queue, &p->capabilities);
-       /*
-        * If count == 0, then just check if memory and type are valid.
-        * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
---- a/drivers/media/platform/vim2m.c
-+++ b/drivers/media/platform/vim2m.c
-@@ -840,6 +840,7 @@ static int queue_init(void *priv, struct
-       src_vq->mem_ops = &vb2_vmalloc_memops;
-       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       src_vq->lock = &ctx->dev->dev_mutex;
-+      src_vq->supports_requests = true;
-       ret = vb2_queue_init(src_vq);
-       if (ret)
---- a/drivers/media/platform/vivid/vivid-core.c
-+++ b/drivers/media/platform/vivid/vivid-core.c
-@@ -1060,6 +1060,7 @@ static int vivid_create_instance(struct
-               q->min_buffers_needed = 2;
-               q->lock = &dev->mutex;
-               q->dev = dev->v4l2_dev.dev;
-+              q->supports_requests = true;
-               ret = vb2_queue_init(q);
-               if (ret)
-@@ -1080,6 +1081,7 @@ static int vivid_create_instance(struct
-               q->min_buffers_needed = 2;
-               q->lock = &dev->mutex;
-               q->dev = dev->v4l2_dev.dev;
-+              q->supports_requests = true;
-               ret = vb2_queue_init(q);
-               if (ret)
-@@ -1100,6 +1102,7 @@ static int vivid_create_instance(struct
-               q->min_buffers_needed = 2;
-               q->lock = &dev->mutex;
-               q->dev = dev->v4l2_dev.dev;
-+              q->supports_requests = true;
-               ret = vb2_queue_init(q);
-               if (ret)
-@@ -1120,6 +1123,7 @@ static int vivid_create_instance(struct
-               q->min_buffers_needed = 2;
-               q->lock = &dev->mutex;
-               q->dev = dev->v4l2_dev.dev;
-+              q->supports_requests = true;
-               ret = vb2_queue_init(q);
-               if (ret)
-@@ -1139,6 +1143,7 @@ static int vivid_create_instance(struct
-               q->min_buffers_needed = 8;
-               q->lock = &dev->mutex;
-               q->dev = dev->v4l2_dev.dev;
-+              q->supports_requests = true;
-               ret = vb2_queue_init(q);
-               if (ret)
---- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
-+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
-@@ -251,7 +251,8 @@ struct v4l2_create_buffers32 {
-       __u32                   count;
-       __u32                   memory; /* enum v4l2_memory */
-       struct v4l2_format32    format;
--      __u32                   reserved[8];
-+      __u32                   capabilities;
-+      __u32                   reserved[7];
- };
- static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
-@@ -411,6 +412,7 @@ static int put_v4l2_create32(struct v4l2
-       if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
-           copy_in_user(p32, p64,
-                        offsetof(struct v4l2_create_buffers32, format)) ||
-+          assign_in_user(&p32->capabilities, &p64->capabilities) ||
-           copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
-               return -EFAULT;
-       return __put_v4l2_format32(&p64->format, &p32->format);
---- a/drivers/media/v4l2-core/v4l2-ioctl.c
-+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
-@@ -1882,7 +1882,7 @@ static int v4l_reqbufs(const struct v4l2
-       if (ret)
-               return ret;
--      CLEAR_AFTER_FIELD(p, memory);
-+      CLEAR_AFTER_FIELD(p, capabilities);
-       return ops->vidioc_reqbufs(file, fh, p);
- }
-@@ -1923,7 +1923,7 @@ static int v4l_create_bufs(const struct
-       if (ret)
-               return ret;
--      CLEAR_AFTER_FIELD(create, format);
-+      CLEAR_AFTER_FIELD(create, capabilities);
-       v4l_sanitize_format(&create->format);
---- a/include/media/videobuf2-core.h
-+++ b/include/media/videobuf2-core.h
-@@ -449,6 +449,7 @@ struct vb2_buf_ops {
-  * @quirk_poll_must_check_waiting_for_buffers: Return %EPOLLERR at poll when QBUF
-  *              has not been called. This is a vb1 idiom that has been adopted
-  *              also by vb2.
-+ * @supports_requests: this queue supports the Request API.
-  * @lock:     pointer to a mutex that protects the &struct vb2_queue. The
-  *            driver can set this to a mutex to let the v4l2 core serialize
-  *            the queuing ioctls. If the driver wants to handle locking
-@@ -516,6 +517,7 @@ struct vb2_queue {
-       unsigned                        fileio_write_immediately:1;
-       unsigned                        allow_zero_bytesused:1;
-       unsigned                   quirk_poll_must_check_waiting_for_buffers:1;
-+      unsigned                        supports_requests:1;
-       struct mutex                    *lock;
-       void                            *owner;
diff --git a/target/linux/brcm2708/patches-4.19/950-0603-overlays-Add-real-parameters-to-the-rpi-poe-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0603-overlays-Add-real-parameters-to-the-rpi-poe-overlay.patch
new file mode 100644 (file)
index 0000000..51dd1d7
--- /dev/null
@@ -0,0 +1,33 @@
+From a11b6221e69ba4177ee428e2cb6fb4e4bd68c5f4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 5 Jul 2019 09:22:10 +0100
+Subject: [PATCH] overlays: Add real parameters to the rpi-poe overlay
+
+As a result of being loaded by the POE HAT EEPROM, the rpi-poe overlay
+doesn't expose parameters in the usual way; instead it adds them to
+the base Device Tree, and the user is expected to use "dtparam=..."
+to access them.
+
+To make the documentation correct and to protect users who load the
+overlay explicitly, expecting to be able to use the parameters, add
+real parameters to the overlay as well.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
+@@ -60,4 +60,11 @@
+                       poe_fan_temp1_hyst =    <&trip1>,"hysteresis:0";
+               };
+       };
++
++      __overrides__ {
++              poe_fan_temp0 =         <&trip0>,"temperature:0";
++              poe_fan_temp0_hyst =    <&trip0>,"hysteresis:0";
++              poe_fan_temp1 =         <&trip1>,"temperature:0";
++              poe_fan_temp1_hyst =    <&trip1>,"hysteresis:0";
++      };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0604-media-vb2-Allow-reqbufs-0-with-in-use-MMAP-buffers.patch b/target/linux/brcm2708/patches-4.19/950-0604-media-vb2-Allow-reqbufs-0-with-in-use-MMAP-buffers.patch
deleted file mode 100644 (file)
index 755ca34..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-From 16cf378051d7fff6772a7acaecbacddec7822330 Mon Sep 17 00:00:00 2001
-From: John Sheu <sheu@chromium.org>
-Date: Thu, 15 Nov 2018 10:57:16 -0500
-Subject: [PATCH] media: vb2: Allow reqbufs(0) with "in use" MMAP
- buffers
-
-Upstream commit d644cca50f366cd109845ae92e37c09ed79adf81
-
-Videobuf2 presently does not allow VIDIOC_REQBUFS to destroy outstanding
-buffers if the queue is of type V4L2_MEMORY_MMAP, and if the buffers are
-considered "in use".  This is different behavior than for other memory
-types and prevents us from deallocating buffers in following two cases:
-
-1) There are outstanding mmap()ed views on the buffer. However even if
-   we put the buffer in reqbufs(0), there will be remaining references,
-   due to vma .open/close() adjusting vb2 buffer refcount appropriately.
-   This means that the buffer will be in fact freed only when the last
-   mmap()ed view is unmapped.
-
-2) Buffer has been exported as a DMABUF. Refcount of the vb2 buffer
-   is managed properly by VB2 DMABUF ops, i.e. incremented on DMABUF
-   get and decremented on DMABUF release. This means that the buffer
-   will be alive until all importers release it.
-
-Considering both cases above, there does not seem to be any need to
-prevent reqbufs(0) operation, because buffer lifetime is already
-properly managed by both mmap() and DMABUF code paths. Let's remove it
-and allow userspace freeing the queue (and potentially allocating a new
-one) even though old buffers might be still in processing.
-
-To let userspace know that the kernel now supports orphaning buffers
-that are still in use, add a new V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS
-to be set by reqbufs and create_bufs.
-
-[p.zabel@pengutronix.de: added V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS,
- updated documentation, and added back debug message]
-
-Signed-off-by: John Sheu <sheu@chromium.org>
-Reviewed-by: Pawel Osciak <posciak@chromium.org>
-Signed-off-by: Tomasz Figa <tfiga@chromium.org>
-Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
-Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-[hverkuil-cisco@xs4all.nl: added V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS ref]
-Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
----
- Documentation/media/uapi/v4l/vidioc-reqbufs.rst | 17 ++++++++++++++---
- drivers/media/common/videobuf2/videobuf2-core.c |  8 +++-----
- drivers/media/common/videobuf2/videobuf2-v4l2.c |  2 +-
- include/uapi/linux/videodev2.h                  |  1 +
- 4 files changed, 19 insertions(+), 9 deletions(-)
-
---- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-+++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-@@ -59,9 +59,14 @@ When the I/O method is not supported the
- code.
- Applications can call :ref:`VIDIOC_REQBUFS` again to change the number of
--buffers, however this cannot succeed when any buffers are still mapped.
--A ``count`` value of zero frees all buffers, after aborting or finishing
--any DMA in progress, an implicit
-+buffers. Note that if any buffers are still mapped or exported via DMABUF,
-+then :ref:`VIDIOC_REQBUFS` can only succeed if the
-+``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` capability is set. Otherwise
-+:ref:`VIDIOC_REQBUFS` will return the ``EBUSY`` error code.
-+If ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` is set, then these buffers are
-+orphaned and will be freed when they are unmapped or when the exported DMABUF
-+fds are closed. A ``count`` value of zero frees or orphans all buffers, after
-+aborting or finishing any DMA in progress, an implicit
- :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`.
-@@ -112,6 +117,7 @@ any DMA in progress, an implicit
- .. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
- .. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
- .. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
-+.. _V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS:
- .. cssclass:: longtable
-@@ -132,6 +138,11 @@ any DMA in progress, an implicit
-     * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
-       - 0x00000008
-       - This buffer type supports :ref:`requests <media-request-api>`.
-+    * - ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS``
-+      - 0x00000010
-+      - The kernel allows calling :ref:`VIDIOC_REQBUFS` while buffers are still
-+        mapped or exported via DMABUF. These orphaned buffers will be freed
-+        when they are unmapped or when the exported DMABUF fds are closed.
- Return Value
- ============
---- a/drivers/media/common/videobuf2/videobuf2-core.c
-+++ b/drivers/media/common/videobuf2/videobuf2-core.c
-@@ -684,11 +684,9 @@ int vb2_core_reqbufs(struct vb2_queue *q
-                * are not in use and can be freed.
-                */
-               mutex_lock(&q->mmap_lock);
--              if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
--                      mutex_unlock(&q->mmap_lock);
--                      dprintk(1, "memory in use, cannot free\n");
--                      return -EBUSY;
--              }
-+              if (debug && q->memory == VB2_MEMORY_MMAP &&
-+                  __buffers_in_use(q))
-+                      dprintk(1, "memory in use, orphaning buffers\n");
-               /*
-                * Call queue_cancel to clean up any buffers in the PREPARED or
---- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
-+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
-@@ -484,7 +484,7 @@ EXPORT_SYMBOL(vb2_querybuf);
- static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
- {
--      *caps = 0;
-+      *caps = V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
-       if (q->io_modes & VB2_MMAP)
-               *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
-       if (q->io_modes & VB2_USERPTR)
---- a/include/uapi/linux/videodev2.h
-+++ b/include/uapi/linux/videodev2.h
-@@ -881,6 +881,7 @@ struct v4l2_requestbuffers {
- #define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
- #define V4L2_BUF_CAP_SUPPORTS_DMABUF  (1 << 2)
- #define V4L2_BUF_CAP_SUPPORTS_REQUESTS        (1 << 3)
-+#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4)
- /**
-  * struct v4l2_plane - plane info for multi-planar buffers
diff --git a/target/linux/brcm2708/patches-4.19/950-0604-overlays-Rename-pi3-overlays-to-be-less-model-specif.patch b/target/linux/brcm2708/patches-4.19/950-0604-overlays-Rename-pi3-overlays-to-be-less-model-specif.patch
new file mode 100644 (file)
index 0000000..669306d
--- /dev/null
@@ -0,0 +1,587 @@
+From c46811a3b0e0fb76015ac956172e40bce4e6d9b3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <pelwell@users.noreply.github.com>
+Date: Fri, 5 Jul 2019 14:49:22 +0100
+Subject: [PATCH] overlays: Rename pi3- overlays to be less
+ model-specific (#3052)
+
+Rename the various pi3- overlays to be more generic, listing
+the devices they apply to in the README. The original names are
+retained for backwards compatibility as files that just include
+the new versions - the README marks them as being deprecated.
+
+See: https://github.com/raspberrypi/firmware/issues/1174
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  4 +
+ arch/arm/boot/dts/overlays/README             | 97 ++++++++++++-------
+ .../arm/boot/dts/overlays/act-led-overlay.dts | 27 ++++++
+ .../boot/dts/overlays/disable-bt-overlay.dts  | 55 +++++++++++
+ .../dts/overlays/disable-wifi-overlay.dts     | 20 ++++
+ .../boot/dts/overlays/miniuart-bt-overlay.dts | 74 ++++++++++++++
+ .../boot/dts/overlays/pi3-act-led-overlay.dts | 28 +-----
+ .../dts/overlays/pi3-disable-bt-overlay.dts   | 56 +----------
+ .../dts/overlays/pi3-disable-wifi-overlay.dts | 21 +---
+ .../dts/overlays/pi3-miniuart-bt-overlay.dts  | 75 +-------------
+ 10 files changed, 246 insertions(+), 211 deletions(-)
+ create mode 100644 arch/arm/boot/dts/overlays/act-led-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/disable-bt-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -1,6 +1,7 @@
+ # Overlays for the Raspberry Pi platform
+ dtbo-$(CONFIG_ARCH_BCM2835) += \
++      act-led.dtbo \
+       adau1977-adc.dtbo \
+       adau7002-simple.dtbo \
+       ads1015.dtbo \
+@@ -26,6 +27,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       dht11.dtbo \
+       dionaudio-loco.dtbo \
+       dionaudio-loco-v2.dtbo \
++      disable-bt.dtbo \
++      disable-wifi.dtbo \
+       dpi18.dtbo \
+       dpi24.dtbo \
+       draws.dtbo \
+@@ -91,6 +94,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       media-center.dtbo \
+       midi-uart0.dtbo \
+       midi-uart1.dtbo \
++      miniuart-bt.dtbo \
+       mmc.dtbo \
+       mpu6050.dtbo \
+       mz61581.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -180,14 +180,16 @@ Params:
+         act_led_activelow       Set to "on" to invert the sense of the LED
+                                 (default "off")
+-                                N.B. For Pi3 see pi3-act-led overlay.
++                                N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
++                                overlay.
+         act_led_gpio            Set which GPIO to use for the activity LED
+                                 (in case you want to connect it to an external
+                                 device)
+                                 (default "16" on a non-Plus board, "47" on a
+                                 Plus or Pi 2)
+-                                N.B. For Pi3 see pi3-act-led overlay.
++                                N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
++                                overlay.
+         pwr_led_trigger
+         pwr_led_activelow
+@@ -205,6 +207,23 @@ Params:
+         and the other i2c baudrate parameters.
++Name:   act-led
++Info:   Pi 3B, 3B+, 3A+ and 4B use a GPIO expander to drive the LEDs which can
++        only be accessed from the VPU. There is a special driver for this with a
++        separate DT node, which has the unfortunate consequence of breaking the
++        act_led_gpio and act_led_activelow dtparams.
++        This overlay changes the GPIO controller back to the standard one and
++        restores the dtparams.
++Load:   dtoverlay=act-led,<param>=<val>
++Params: activelow               Set to "on" to invert the sense of the LED
++                                (default "off")
++
++        gpio                    Set which GPIO to use for the activity LED
++                                (in case you want to connect it to an external
++                                device)
++                                REQUIRED
++
++
+ Name:   adau1977-adc
+ Info:   Overlay for activation of ADAU1977 ADC codec over I2C for control
+         and I2S for data.
+@@ -509,6 +528,21 @@ Params: 24db_digital_gain       Allow ga
+                                 that does not result in clipping/distortion!)
++Name:   disable-bt
++Info:   Disable onboard Bluetooth on Pi 3B, 3B+, 3A+, 4B and Zero W, restoring
++        UART0/ttyAMA0 over GPIOs 14 & 15.
++        N.B. To disable the systemd service that initialises the modem so it
++        doesn't use the UART, use 'sudo systemctl disable hciuart'.
++Load:   dtoverlay=disable-bt
++Params: <None>
++
++
++Name:   disable-wifi
++Info:   Disable onboard WiFi on Pi 3B, 3B+, 3A+, 4B and Zero W.
++Load:   dtoverlay=disable-wifi
++Params: <None>
++
++
+ Name:   dpi18
+ Info:   Overlay for a generic 18-bit DPI display
+         This uses GPIOs 0-21 (so no I2C, uart etc.), and activates the output
+@@ -1447,6 +1481,20 @@ Load:   dtoverlay=midi-uart1
+ Params: <None>
++Name:   miniuart-bt
++Info:   Switch the onboard Bluetooth function on Pi 3B, 3B+, 3A+, 4B and Zero W
++        to use the mini-UART (ttyS0) and restore UART0/ttyAMA0 over GPIOs 14 &
++        15. Note that this may reduce the maximum usable baudrate.
++        N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
++        and replace ttyAMA0 with ttyS0, unless using Raspbian or another
++        distribution with udev rules that create /dev/serial0 and /dev/serial1,
++        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>
++
++
+ Name:   mmc
+ Info:   Selects the bcm2835-mmc SD/MMC driver, optionally with overclock
+ Load:   dtoverlay=mmc,<param>=<val>
+@@ -1509,48 +1557,27 @@ Params: panel                   Display
+ Name:   pi3-act-led
+-Info:   Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
+-        from the VPU. There is a special driver for this with a separate DT
+-        node, which has the unfortunate consequence of breaking the
+-        act_led_gpio and act_led_activelow dtparams.
+-        This overlay changes the GPIO controller back to the standard one and
+-        restores the dtparams.
+-Load:   dtoverlay=pi3-act-led,<param>=<val>
+-Params: activelow               Set to "on" to invert the sense of the LED
+-                                (default "off")
+-
+-        gpio                    Set which GPIO to use for the activity LED
+-                                (in case you want to connect it to an external
+-                                device)
+-                                REQUIRED
++Info:   This overlay has been renamed act-led, keeping pi3-act-led as an alias
++        for backwards compatibility.
++Load:   <Deprecated>
+ Name:   pi3-disable-bt
+-Info:   Disable Pi3 Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15
+-        N.B. To disable the systemd service that initialises the modem so it
+-        doesn't use the UART, use 'sudo systemctl disable hciuart'.
+-Load:   dtoverlay=pi3-disable-bt
+-Params: <None>
++Info:   This overlay has been renamed disable-bt, keeping pi3-disable-bt as an
++        alias for backwards compatibility.
++Load:   <Deprecated>
+ Name:   pi3-disable-wifi
+-Info:   Disable Pi3 onboard WiFi
+-Load:   dtoverlay=pi3-disable-wifi
+-Params: <None>
++Info:   This overlay has been renamed disable-wifi, keeping pi3-disable-wifi as
++        an alias for backwards compatibility.
++Load:   <Deprecated>
+ Name:   pi3-miniuart-bt
+-Info:   Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore
+-        UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum
+-        usable baudrate.
+-        N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
+-        and replace ttyAMA0 with ttyS0, unless you have a system with udev rules
+-        that create /dev/serial0 and /dev/serial1, in which case use
+-        /dev/serial1 instead because it will always be correct. Furthermore,
+-        you must also set core_freq=250 in config.txt or the miniuart will not
+-        work.
+-Load:   dtoverlay=pi3-miniuart-bt
+-Params: <None>
++Info:   This overlay has been renamed miniuart-bt, keeping pi3-miniuart-bt as
++        an alias for backwards compatibility.
++Load:   <Deprecated>
+ Name:   pibell
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/act-led-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
++   from the VPU. There is a special driver for this with a separate DT node,
++   which has the unfortunate consequence of breaking the act_led_gpio and
++   act_led_activelow dtparams.
++
++   This overlay changes the GPIO controller back to the standard one and
++   restores the dtparams.
++*/
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&act_led>;
++              frag0: __overlay__ {
++                      gpios = <&gpio 0 0>;
++              };
++      };
++
++      __overrides__ {
++              gpio = <&frag0>,"gpios:4";
++              activelow = <&frag0>,"gpios:8";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/disable-bt-overlay.dts
+@@ -0,0 +1,55 @@
++/dts-v1/;
++/plugin/;
++
++/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
++   To disable the systemd service that initialises the modem so it doesn't use
++   the UART:
++
++       sudo systemctl disable hciuart
++*/
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&uart1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@1 {
++              target = <&uart0>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&uart0_pins>;
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&uart0_pins>;
++              __overlay__ {
++                      brcm,pins;
++                      brcm,function;
++                      brcm,pull;
++              };
++      };
++
++      fragment@3 {
++              target = <&bt_pins>;
++              __overlay__ {
++                      brcm,pins;
++                      brcm,function;
++                      brcm,pull;
++              };
++      };
++
++      fragment@4 {
++              target-path = "/aliases";
++              __overlay__ {
++                      serial0 = "/soc/serial@7e201000";
++                      serial1 = "/soc/serial@7e215040";
++              };
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
+@@ -0,0 +1,20 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&mmc>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@1 {
++              target = <&mmcnr>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
+@@ -0,0 +1,74 @@
++/dts-v1/;
++/plugin/;
++
++/* Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore
++   UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum
++   usable baudrate.
++
++   It is also necessary to edit /lib/systemd/system/hciuart.service and
++   replace ttyAMA0 with ttyS0, unless you have a system with udev rules
++   that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
++   instead because it will always be correct.
++
++   If cmdline.txt uses the alias serial0 to refer to the user-accessable port
++   then the firmware will replace with the appropriate port whether or not
++   this overlay is used.
++*/
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&uart0>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&uart0_pins>;
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&uart1>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&uart0_pins>;
++              __overlay__ {
++                      brcm,pins;
++                      brcm,function;
++                      brcm,pull;
++              };
++      };
++
++      fragment@3 {
++              target = <&uart1_pins>;
++              __overlay__ {
++                      brcm,pins = <32 33>;
++                      brcm,function = <2>; /* alt5=UART1 */
++                      brcm,pull = <0 2>;
++              };
++      };
++
++      fragment@4 {
++              target = <&gpio>;
++              __overlay__ {
++                      fake_bt_cts: fake_bt_cts {
++                              brcm,pins = <31>;
++                              brcm,function = <1>; /* output */
++                      };
++              };
++      };
++
++      fragment@5 {
++              target-path = "/aliases";
++              __overlay__ {
++                      serial0 = "/soc/serial@7e201000";
++                      serial1 = "/soc/serial@7e215040";
++              };
++      };
++};
+--- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
+@@ -1,27 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
+-   from the VPU. There is a special driver for this with a separate DT node,
+-   which has the unfortunate consequence of breaking the act_led_gpio and
+-   act_led_activelow dtparams.
+-
+-   This overlay changes the GPIO controller back to the standard one and
+-   restores the dtparams.
+-*/
+-
+-/{
+-      compatible = "brcm,bcm2835";
+-
+-      fragment@0 {
+-              target = <&act_led>;
+-              frag0: __overlay__ {
+-                      gpios = <&gpio 0 0>;
+-              };
+-      };
+-
+-      __overrides__ {
+-              gpio = <&frag0>,"gpios:4";
+-              activelow = <&frag0>,"gpios:8";
+-      };
+-};
++#include "act-led-overlay.dts"
+--- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
+@@ -1,55 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
+-   To disable the systemd service that initialises the modem so it doesn't use
+-   the UART:
+-
+-       sudo systemctl disable hciuart
+-*/
+-
+-/{
+-      compatible = "brcm,bcm2835";
+-
+-      fragment@0 {
+-              target = <&uart1>;
+-              __overlay__ {
+-                      status = "disabled";
+-              };
+-      };
+-
+-      fragment@1 {
+-              target = <&uart0>;
+-              __overlay__ {
+-                      pinctrl-names = "default";
+-                      pinctrl-0 = <&uart0_pins>;
+-                      status = "okay";
+-              };
+-      };
+-
+-      fragment@2 {
+-              target = <&uart0_pins>;
+-              __overlay__ {
+-                      brcm,pins;
+-                      brcm,function;
+-                      brcm,pull;
+-              };
+-      };
+-
+-      fragment@3 {
+-              target = <&bt_pins>;
+-              __overlay__ {
+-                      brcm,pins;
+-                      brcm,function;
+-                      brcm,pull;
+-              };
+-      };
+-
+-      fragment@4 {
+-              target-path = "/aliases";
+-              __overlay__ {
+-                      serial0 = "/soc/serial@7e201000";
+-                      serial1 = "/soc/serial@7e215040";
+-              };
+-      };
+-};
++#include "disable-bt-overlay.dts"
+--- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
+@@ -1,20 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/{
+-      compatible = "brcm,bcm2835";
+-
+-      fragment@0 {
+-              target = <&mmc>;
+-              __overlay__ {
+-                      status = "disabled";
+-              };
+-      };
+-
+-      fragment@1 {
+-              target = <&mmcnr>;
+-              __overlay__ {
+-                      status = "disabled";
+-              };
+-      };
+-};
++#include "disable-wifi-overlay.dts"
+--- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
+@@ -1,74 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore
+-   UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum
+-   usable baudrate.
+-
+-   It is also necessary to edit /lib/systemd/system/hciuart.service and
+-   replace ttyAMA0 with ttyS0, unless you have a system with udev rules
+-   that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
+-   instead because it will always be correct.
+-
+-   If cmdline.txt uses the alias serial0 to refer to the user-accessable port
+-   then the firmware will replace with the appropriate port whether or not
+-   this overlay is used.
+-*/
+-
+-/{
+-      compatible = "brcm,bcm2835";
+-
+-      fragment@0 {
+-              target = <&uart0>;
+-              __overlay__ {
+-                      pinctrl-names = "default";
+-                      pinctrl-0 = <&uart0_pins>;
+-                      status = "okay";
+-              };
+-      };
+-
+-      fragment@1 {
+-              target = <&uart1>;
+-              __overlay__ {
+-                      pinctrl-names = "default";
+-                      pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
+-                      status = "okay";
+-              };
+-      };
+-
+-      fragment@2 {
+-              target = <&uart0_pins>;
+-              __overlay__ {
+-                      brcm,pins;
+-                      brcm,function;
+-                      brcm,pull;
+-              };
+-      };
+-
+-      fragment@3 {
+-              target = <&uart1_pins>;
+-              __overlay__ {
+-                      brcm,pins = <32 33>;
+-                      brcm,function = <2>; /* alt5=UART1 */
+-                      brcm,pull = <0 2>;
+-              };
+-      };
+-
+-      fragment@4 {
+-              target = <&gpio>;
+-              __overlay__ {
+-                      fake_bt_cts: fake_bt_cts {
+-                              brcm,pins = <31>;
+-                              brcm,function = <1>; /* output */
+-                      };
+-              };
+-      };
+-
+-      fragment@5 {
+-              target-path = "/aliases";
+-              __overlay__ {
+-                      serial0 = "/soc/serial@7e201000";
+-                      serial1 = "/soc/serial@7e215040";
+-              };
+-      };
+-};
++#include "miniuart-bt-overlay.dts"
diff --git a/target/linux/brcm2708/patches-4.19/950-0605-i2c-bcm2835-Move-IRQ-request-after-clock-code-in-pro.patch b/target/linux/brcm2708/patches-4.19/950-0605-i2c-bcm2835-Move-IRQ-request-after-clock-code-in-pro.patch
new file mode 100644 (file)
index 0000000..b363e75
--- /dev/null
@@ -0,0 +1,66 @@
+From 614cade3a68f7214939e1c72acd5fcc9d49beeef Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Fri, 21 Jun 2019 03:52:49 -0700
+Subject: [PATCH] i2c: bcm2835: Move IRQ request after clock code in
+ probe
+
+Commit 4a5cfa39465cad25dd736d7ceba8a5d32eea4ecc upstream.
+
+If any of the clock code in the probe fails and returns, the IRQ
+will not be freed.  Moving the IRQ request to last allows it to
+be freed on any errors further up in the probe function.  devm_
+calls can apparently not be used because there are some potential
+race conditions that will arise.
+
+Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Acked-by: Stefan Wahren <wahrenst@gmx.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -521,20 +521,6 @@ static int bcm2835_i2c_probe(struct plat
+       if (IS_ERR(i2c_dev->regs))
+               return PTR_ERR(i2c_dev->regs);
+-      irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+-      if (!irq) {
+-              dev_err(&pdev->dev, "No IRQ resource\n");
+-              return -ENODEV;
+-      }
+-      i2c_dev->irq = irq->start;
+-
+-      ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
+-                        dev_name(&pdev->dev), i2c_dev);
+-      if (ret) {
+-              dev_err(&pdev->dev, "Could not request IRQ\n");
+-              return -ENODEV;
+-      }
+-
+       mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
+       bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
+@@ -564,6 +550,20 @@ static int bcm2835_i2c_probe(struct plat
+               return ret;
+       }
++      irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++      if (!irq) {
++              dev_err(&pdev->dev, "No IRQ resource\n");
++              return -ENODEV;
++      }
++      i2c_dev->irq = irq->start;
++
++      ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
++                        dev_name(&pdev->dev), i2c_dev);
++      if (ret) {
++              dev_err(&pdev->dev, "Could not request IRQ\n");
++              return -ENODEV;
++      }
++
+       adap = &i2c_dev->adapter;
+       i2c_set_adapdata(adap, i2c_dev);
+       adap->owner = THIS_MODULE;
diff --git a/target/linux/brcm2708/patches-4.19/950-0605-overlays-Add-real-parameters-to-the-rpi-poe-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0605-overlays-Add-real-parameters-to-the-rpi-poe-overlay.patch
deleted file mode 100644 (file)
index 51dd1d7..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From a11b6221e69ba4177ee428e2cb6fb4e4bd68c5f4 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 5 Jul 2019 09:22:10 +0100
-Subject: [PATCH] overlays: Add real parameters to the rpi-poe overlay
-
-As a result of being loaded by the POE HAT EEPROM, the rpi-poe overlay
-doesn't expose parameters in the usual way; instead it adds them to
-the base Device Tree, and the user is expected to use "dtparam=..."
-to access them.
-
-To make the documentation correct and to protect users who load the
-overlay explicitly, expecting to be able to use the parameters, add
-real parameters to the overlay as well.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-@@ -60,4 +60,11 @@
-                       poe_fan_temp1_hyst =    <&trip1>,"hysteresis:0";
-               };
-       };
-+
-+      __overrides__ {
-+              poe_fan_temp0 =         <&trip0>,"temperature:0";
-+              poe_fan_temp0_hyst =    <&trip0>,"hysteresis:0";
-+              poe_fan_temp1 =         <&trip1>,"temperature:0";
-+              poe_fan_temp1_hyst =    <&trip1>,"hysteresis:0";
-+      };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0606-i2c-bcm2835-Ensure-clock-exists-when-probing.patch b/target/linux/brcm2708/patches-4.19/950-0606-i2c-bcm2835-Ensure-clock-exists-when-probing.patch
new file mode 100644 (file)
index 0000000..4a468f0
--- /dev/null
@@ -0,0 +1,72 @@
+From 1a5122f1756ef4fc5779324ad26b6a04142166b5 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Fri, 21 Jun 2019 03:52:50 -0700
+Subject: [PATCH] i2c: bcm2835: Ensure clock exists when probing
+
+Commit 9de93b04df16b055824e3f1f13fedb90fbcf2e4f upstream.
+
+Probe function fails to recognize that upstream clock actually
+doesn't yet exist because clock driver has not been initialized.
+Actually try to go get the clock and test for its existence
+before trying to set up a downstream clock based upon it.
+
+This fixes a bug that causes the i2c driver not to work with
+monolithic kernels.
+
+Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Acked-by: Stefan Wahren <wahrenst@gmx.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -244,15 +244,18 @@ static const struct clk_ops clk_bcm2835_
+ };
+ static struct clk *bcm2835_i2c_register_div(struct device *dev,
+-                                      const char *mclk_name,
++                                      struct clk *mclk,
+                                       struct bcm2835_i2c_dev *i2c_dev)
+ {
+       struct clk_init_data init;
+       struct clk_bcm2835_i2c *priv;
+       char name[32];
++      const char *mclk_name;
+       snprintf(name, sizeof(name), "%s_div", dev_name(dev));
++      mclk_name = __clk_get_name(mclk);
++
+       init.ops = &clk_bcm2835_i2c_ops;
+       init.name = name;
+       init.parent_names = (const char* []) { mclk_name };
+@@ -505,8 +508,8 @@ static int bcm2835_i2c_probe(struct plat
+       struct resource *mem, *irq;
+       int ret;
+       struct i2c_adapter *adap;
+-      const char *mclk_name;
+       struct clk *bus_clk;
++      struct clk *mclk;
+       u32 bus_clk_rate;
+       i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+@@ -521,9 +524,14 @@ static int bcm2835_i2c_probe(struct plat
+       if (IS_ERR(i2c_dev->regs))
+               return PTR_ERR(i2c_dev->regs);
+-      mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
++      mclk = devm_clk_get(&pdev->dev, NULL);
++      if (IS_ERR(mclk)) {
++              if (PTR_ERR(mclk) != -EPROBE_DEFER)
++                      dev_err(&pdev->dev, "Could not get clock\n");
++              return PTR_ERR(mclk);
++      }
+-      bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
++      bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
+       if (IS_ERR(bus_clk)) {
+               dev_err(&pdev->dev, "Could not register clock\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0606-overlays-Rename-pi3-overlays-to-be-less-model-specif.patch b/target/linux/brcm2708/patches-4.19/950-0606-overlays-Rename-pi3-overlays-to-be-less-model-specif.patch
deleted file mode 100644 (file)
index 669306d..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-From c46811a3b0e0fb76015ac956172e40bce4e6d9b3 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <pelwell@users.noreply.github.com>
-Date: Fri, 5 Jul 2019 14:49:22 +0100
-Subject: [PATCH] overlays: Rename pi3- overlays to be less
- model-specific (#3052)
-
-Rename the various pi3- overlays to be more generic, listing
-the devices they apply to in the README. The original names are
-retained for backwards compatibility as files that just include
-the new versions - the README marks them as being deprecated.
-
-See: https://github.com/raspberrypi/firmware/issues/1174
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile           |  4 +
- arch/arm/boot/dts/overlays/README             | 97 ++++++++++++-------
- .../arm/boot/dts/overlays/act-led-overlay.dts | 27 ++++++
- .../boot/dts/overlays/disable-bt-overlay.dts  | 55 +++++++++++
- .../dts/overlays/disable-wifi-overlay.dts     | 20 ++++
- .../boot/dts/overlays/miniuart-bt-overlay.dts | 74 ++++++++++++++
- .../boot/dts/overlays/pi3-act-led-overlay.dts | 28 +-----
- .../dts/overlays/pi3-disable-bt-overlay.dts   | 56 +----------
- .../dts/overlays/pi3-disable-wifi-overlay.dts | 21 +---
- .../dts/overlays/pi3-miniuart-bt-overlay.dts  | 75 +-------------
- 10 files changed, 246 insertions(+), 211 deletions(-)
- create mode 100644 arch/arm/boot/dts/overlays/act-led-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/disable-bt-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -1,6 +1,7 @@
- # Overlays for the Raspberry Pi platform
- dtbo-$(CONFIG_ARCH_BCM2835) += \
-+      act-led.dtbo \
-       adau1977-adc.dtbo \
-       adau7002-simple.dtbo \
-       ads1015.dtbo \
-@@ -26,6 +27,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       dht11.dtbo \
-       dionaudio-loco.dtbo \
-       dionaudio-loco-v2.dtbo \
-+      disable-bt.dtbo \
-+      disable-wifi.dtbo \
-       dpi18.dtbo \
-       dpi24.dtbo \
-       draws.dtbo \
-@@ -91,6 +94,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       media-center.dtbo \
-       midi-uart0.dtbo \
-       midi-uart1.dtbo \
-+      miniuart-bt.dtbo \
-       mmc.dtbo \
-       mpu6050.dtbo \
-       mz61581.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -180,14 +180,16 @@ Params:
-         act_led_activelow       Set to "on" to invert the sense of the LED
-                                 (default "off")
--                                N.B. For Pi3 see pi3-act-led overlay.
-+                                N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
-+                                overlay.
-         act_led_gpio            Set which GPIO to use for the activity LED
-                                 (in case you want to connect it to an external
-                                 device)
-                                 (default "16" on a non-Plus board, "47" on a
-                                 Plus or Pi 2)
--                                N.B. For Pi3 see pi3-act-led overlay.
-+                                N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
-+                                overlay.
-         pwr_led_trigger
-         pwr_led_activelow
-@@ -205,6 +207,23 @@ Params:
-         and the other i2c baudrate parameters.
-+Name:   act-led
-+Info:   Pi 3B, 3B+, 3A+ and 4B use a GPIO expander to drive the LEDs which can
-+        only be accessed from the VPU. There is a special driver for this with a
-+        separate DT node, which has the unfortunate consequence of breaking the
-+        act_led_gpio and act_led_activelow dtparams.
-+        This overlay changes the GPIO controller back to the standard one and
-+        restores the dtparams.
-+Load:   dtoverlay=act-led,<param>=<val>
-+Params: activelow               Set to "on" to invert the sense of the LED
-+                                (default "off")
-+
-+        gpio                    Set which GPIO to use for the activity LED
-+                                (in case you want to connect it to an external
-+                                device)
-+                                REQUIRED
-+
-+
- Name:   adau1977-adc
- Info:   Overlay for activation of ADAU1977 ADC codec over I2C for control
-         and I2S for data.
-@@ -509,6 +528,21 @@ Params: 24db_digital_gain       Allow ga
-                                 that does not result in clipping/distortion!)
-+Name:   disable-bt
-+Info:   Disable onboard Bluetooth on Pi 3B, 3B+, 3A+, 4B and Zero W, restoring
-+        UART0/ttyAMA0 over GPIOs 14 & 15.
-+        N.B. To disable the systemd service that initialises the modem so it
-+        doesn't use the UART, use 'sudo systemctl disable hciuart'.
-+Load:   dtoverlay=disable-bt
-+Params: <None>
-+
-+
-+Name:   disable-wifi
-+Info:   Disable onboard WiFi on Pi 3B, 3B+, 3A+, 4B and Zero W.
-+Load:   dtoverlay=disable-wifi
-+Params: <None>
-+
-+
- Name:   dpi18
- Info:   Overlay for a generic 18-bit DPI display
-         This uses GPIOs 0-21 (so no I2C, uart etc.), and activates the output
-@@ -1447,6 +1481,20 @@ Load:   dtoverlay=midi-uart1
- Params: <None>
-+Name:   miniuart-bt
-+Info:   Switch the onboard Bluetooth function on Pi 3B, 3B+, 3A+, 4B and Zero W
-+        to use the mini-UART (ttyS0) and restore UART0/ttyAMA0 over GPIOs 14 &
-+        15. Note that this may reduce the maximum usable baudrate.
-+        N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
-+        and replace ttyAMA0 with ttyS0, unless using Raspbian or another
-+        distribution with udev rules that create /dev/serial0 and /dev/serial1,
-+        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>
-+
-+
- Name:   mmc
- Info:   Selects the bcm2835-mmc SD/MMC driver, optionally with overclock
- Load:   dtoverlay=mmc,<param>=<val>
-@@ -1509,48 +1557,27 @@ Params: panel                   Display
- Name:   pi3-act-led
--Info:   Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
--        from the VPU. There is a special driver for this with a separate DT
--        node, which has the unfortunate consequence of breaking the
--        act_led_gpio and act_led_activelow dtparams.
--        This overlay changes the GPIO controller back to the standard one and
--        restores the dtparams.
--Load:   dtoverlay=pi3-act-led,<param>=<val>
--Params: activelow               Set to "on" to invert the sense of the LED
--                                (default "off")
--
--        gpio                    Set which GPIO to use for the activity LED
--                                (in case you want to connect it to an external
--                                device)
--                                REQUIRED
-+Info:   This overlay has been renamed act-led, keeping pi3-act-led as an alias
-+        for backwards compatibility.
-+Load:   <Deprecated>
- Name:   pi3-disable-bt
--Info:   Disable Pi3 Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15
--        N.B. To disable the systemd service that initialises the modem so it
--        doesn't use the UART, use 'sudo systemctl disable hciuart'.
--Load:   dtoverlay=pi3-disable-bt
--Params: <None>
-+Info:   This overlay has been renamed disable-bt, keeping pi3-disable-bt as an
-+        alias for backwards compatibility.
-+Load:   <Deprecated>
- Name:   pi3-disable-wifi
--Info:   Disable Pi3 onboard WiFi
--Load:   dtoverlay=pi3-disable-wifi
--Params: <None>
-+Info:   This overlay has been renamed disable-wifi, keeping pi3-disable-wifi as
-+        an alias for backwards compatibility.
-+Load:   <Deprecated>
- Name:   pi3-miniuart-bt
--Info:   Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore
--        UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum
--        usable baudrate.
--        N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
--        and replace ttyAMA0 with ttyS0, unless you have a system with udev rules
--        that create /dev/serial0 and /dev/serial1, in which case use
--        /dev/serial1 instead because it will always be correct. Furthermore,
--        you must also set core_freq=250 in config.txt or the miniuart will not
--        work.
--Load:   dtoverlay=pi3-miniuart-bt
--Params: <None>
-+Info:   This overlay has been renamed miniuart-bt, keeping pi3-miniuart-bt as
-+        an alias for backwards compatibility.
-+Load:   <Deprecated>
- Name:   pibell
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/act-led-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
-+   from the VPU. There is a special driver for this with a separate DT node,
-+   which has the unfortunate consequence of breaking the act_led_gpio and
-+   act_led_activelow dtparams.
-+
-+   This overlay changes the GPIO controller back to the standard one and
-+   restores the dtparams.
-+*/
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&act_led>;
-+              frag0: __overlay__ {
-+                      gpios = <&gpio 0 0>;
-+              };
-+      };
-+
-+      __overrides__ {
-+              gpio = <&frag0>,"gpios:4";
-+              activelow = <&frag0>,"gpios:8";
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/disable-bt-overlay.dts
-@@ -0,0 +1,55 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
-+   To disable the systemd service that initialises the modem so it doesn't use
-+   the UART:
-+
-+       sudo systemctl disable hciuart
-+*/
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&uart1>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&uart0>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&uart0_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&uart0_pins>;
-+              __overlay__ {
-+                      brcm,pins;
-+                      brcm,function;
-+                      brcm,pull;
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&bt_pins>;
-+              __overlay__ {
-+                      brcm,pins;
-+                      brcm,function;
-+                      brcm,pull;
-+              };
-+      };
-+
-+      fragment@4 {
-+              target-path = "/aliases";
-+              __overlay__ {
-+                      serial0 = "/soc/serial@7e201000";
-+                      serial1 = "/soc/serial@7e215040";
-+              };
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
-@@ -0,0 +1,20 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&mmc>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&mmcnr>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
-@@ -0,0 +1,74 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/* Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore
-+   UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum
-+   usable baudrate.
-+
-+   It is also necessary to edit /lib/systemd/system/hciuart.service and
-+   replace ttyAMA0 with ttyS0, unless you have a system with udev rules
-+   that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
-+   instead because it will always be correct.
-+
-+   If cmdline.txt uses the alias serial0 to refer to the user-accessable port
-+   then the firmware will replace with the appropriate port whether or not
-+   this overlay is used.
-+*/
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&uart0>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&uart0_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&uart1>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&uart0_pins>;
-+              __overlay__ {
-+                      brcm,pins;
-+                      brcm,function;
-+                      brcm,pull;
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&uart1_pins>;
-+              __overlay__ {
-+                      brcm,pins = <32 33>;
-+                      brcm,function = <2>; /* alt5=UART1 */
-+                      brcm,pull = <0 2>;
-+              };
-+      };
-+
-+      fragment@4 {
-+              target = <&gpio>;
-+              __overlay__ {
-+                      fake_bt_cts: fake_bt_cts {
-+                              brcm,pins = <31>;
-+                              brcm,function = <1>; /* output */
-+                      };
-+              };
-+      };
-+
-+      fragment@5 {
-+              target-path = "/aliases";
-+              __overlay__ {
-+                      serial0 = "/soc/serial@7e201000";
-+                      serial1 = "/soc/serial@7e215040";
-+              };
-+      };
-+};
---- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-@@ -1,27 +1 @@
--/dts-v1/;
--/plugin/;
--
--/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
--   from the VPU. There is a special driver for this with a separate DT node,
--   which has the unfortunate consequence of breaking the act_led_gpio and
--   act_led_activelow dtparams.
--
--   This overlay changes the GPIO controller back to the standard one and
--   restores the dtparams.
--*/
--
--/{
--      compatible = "brcm,bcm2835";
--
--      fragment@0 {
--              target = <&act_led>;
--              frag0: __overlay__ {
--                      gpios = <&gpio 0 0>;
--              };
--      };
--
--      __overrides__ {
--              gpio = <&frag0>,"gpios:4";
--              activelow = <&frag0>,"gpios:8";
--      };
--};
-+#include "act-led-overlay.dts"
---- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-@@ -1,55 +1 @@
--/dts-v1/;
--/plugin/;
--
--/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
--   To disable the systemd service that initialises the modem so it doesn't use
--   the UART:
--
--       sudo systemctl disable hciuart
--*/
--
--/{
--      compatible = "brcm,bcm2835";
--
--      fragment@0 {
--              target = <&uart1>;
--              __overlay__ {
--                      status = "disabled";
--              };
--      };
--
--      fragment@1 {
--              target = <&uart0>;
--              __overlay__ {
--                      pinctrl-names = "default";
--                      pinctrl-0 = <&uart0_pins>;
--                      status = "okay";
--              };
--      };
--
--      fragment@2 {
--              target = <&uart0_pins>;
--              __overlay__ {
--                      brcm,pins;
--                      brcm,function;
--                      brcm,pull;
--              };
--      };
--
--      fragment@3 {
--              target = <&bt_pins>;
--              __overlay__ {
--                      brcm,pins;
--                      brcm,function;
--                      brcm,pull;
--              };
--      };
--
--      fragment@4 {
--              target-path = "/aliases";
--              __overlay__ {
--                      serial0 = "/soc/serial@7e201000";
--                      serial1 = "/soc/serial@7e215040";
--              };
--      };
--};
-+#include "disable-bt-overlay.dts"
---- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-@@ -1,20 +1 @@
--/dts-v1/;
--/plugin/;
--
--/{
--      compatible = "brcm,bcm2835";
--
--      fragment@0 {
--              target = <&mmc>;
--              __overlay__ {
--                      status = "disabled";
--              };
--      };
--
--      fragment@1 {
--              target = <&mmcnr>;
--              __overlay__ {
--                      status = "disabled";
--              };
--      };
--};
-+#include "disable-wifi-overlay.dts"
---- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-@@ -1,74 +1 @@
--/dts-v1/;
--/plugin/;
--
--/* Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore
--   UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum
--   usable baudrate.
--
--   It is also necessary to edit /lib/systemd/system/hciuart.service and
--   replace ttyAMA0 with ttyS0, unless you have a system with udev rules
--   that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
--   instead because it will always be correct.
--
--   If cmdline.txt uses the alias serial0 to refer to the user-accessable port
--   then the firmware will replace with the appropriate port whether or not
--   this overlay is used.
--*/
--
--/{
--      compatible = "brcm,bcm2835";
--
--      fragment@0 {
--              target = <&uart0>;
--              __overlay__ {
--                      pinctrl-names = "default";
--                      pinctrl-0 = <&uart0_pins>;
--                      status = "okay";
--              };
--      };
--
--      fragment@1 {
--              target = <&uart1>;
--              __overlay__ {
--                      pinctrl-names = "default";
--                      pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
--                      status = "okay";
--              };
--      };
--
--      fragment@2 {
--              target = <&uart0_pins>;
--              __overlay__ {
--                      brcm,pins;
--                      brcm,function;
--                      brcm,pull;
--              };
--      };
--
--      fragment@3 {
--              target = <&uart1_pins>;
--              __overlay__ {
--                      brcm,pins = <32 33>;
--                      brcm,function = <2>; /* alt5=UART1 */
--                      brcm,pull = <0 2>;
--              };
--      };
--
--      fragment@4 {
--              target = <&gpio>;
--              __overlay__ {
--                      fake_bt_cts: fake_bt_cts {
--                              brcm,pins = <31>;
--                              brcm,function = <1>; /* output */
--                      };
--              };
--      };
--
--      fragment@5 {
--              target-path = "/aliases";
--              __overlay__ {
--                      serial0 = "/soc/serial@7e201000";
--                      serial1 = "/soc/serial@7e215040";
--              };
--      };
--};
-+#include "miniuart-bt-overlay.dts"
diff --git a/target/linux/brcm2708/patches-4.19/950-0607-i2c-bcm2835-Move-IRQ-request-after-clock-code-in-pro.patch b/target/linux/brcm2708/patches-4.19/950-0607-i2c-bcm2835-Move-IRQ-request-after-clock-code-in-pro.patch
deleted file mode 100644 (file)
index b363e75..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-From 614cade3a68f7214939e1c72acd5fcc9d49beeef Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Fri, 21 Jun 2019 03:52:49 -0700
-Subject: [PATCH] i2c: bcm2835: Move IRQ request after clock code in
- probe
-
-Commit 4a5cfa39465cad25dd736d7ceba8a5d32eea4ecc upstream.
-
-If any of the clock code in the probe fails and returns, the IRQ
-will not be freed.  Moving the IRQ request to last allows it to
-be freed on any errors further up in the probe function.  devm_
-calls can apparently not be used because there are some potential
-race conditions that will arise.
-
-Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Acked-by: Stefan Wahren <wahrenst@gmx.net>
-Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
----
- drivers/i2c/busses/i2c-bcm2835.c | 28 ++++++++++++++--------------
- 1 file changed, 14 insertions(+), 14 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -521,20 +521,6 @@ static int bcm2835_i2c_probe(struct plat
-       if (IS_ERR(i2c_dev->regs))
-               return PTR_ERR(i2c_dev->regs);
--      irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
--      if (!irq) {
--              dev_err(&pdev->dev, "No IRQ resource\n");
--              return -ENODEV;
--      }
--      i2c_dev->irq = irq->start;
--
--      ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
--                        dev_name(&pdev->dev), i2c_dev);
--      if (ret) {
--              dev_err(&pdev->dev, "Could not request IRQ\n");
--              return -ENODEV;
--      }
--
-       mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
-       bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
-@@ -564,6 +550,20 @@ static int bcm2835_i2c_probe(struct plat
-               return ret;
-       }
-+      irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+      if (!irq) {
-+              dev_err(&pdev->dev, "No IRQ resource\n");
-+              return -ENODEV;
-+      }
-+      i2c_dev->irq = irq->start;
-+
-+      ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
-+                        dev_name(&pdev->dev), i2c_dev);
-+      if (ret) {
-+              dev_err(&pdev->dev, "Could not request IRQ\n");
-+              return -ENODEV;
-+      }
-+
-       adap = &i2c_dev->adapter;
-       i2c_set_adapdata(adap, i2c_dev);
-       adap->owner = THIS_MODULE;
diff --git a/target/linux/brcm2708/patches-4.19/950-0607-overlays-i2c-gpio-Fix-the-bus-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0607-overlays-i2c-gpio-Fix-the-bus-parameter.patch
new file mode 100644 (file)
index 0000000..9a6d155
--- /dev/null
@@ -0,0 +1,35 @@
+From d562b2187263b40aacc1a50d3f25db2cf28696d6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 9 Jul 2019 10:32:40 +0100
+Subject: [PATCH] overlays: i2c-gpio: Fix the "bus" parameter
+
+The "bus" parameter has two functions - providing unique names for
+multiple instances of the overlay, and allowing the number of the bus
+(i.e. "i2c-<bus>") to be specified. The second function hasn't worked
+as intended because the overlay doesn't include a "reg" property and
+the firmware intentionally won't create a "reg" property if one doesn't
+already exist.
+
+Allow the bus numbering scheme to work as intended by providing a "reg"
+with a default value that means "the next available one".
+
+See: https://github.com/raspberrypi/linux/issues/3062
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ 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
+@@ -7,8 +7,10 @@
+       fragment@0 {
+               target-path = "/";
++
+               __overlay__ {
+                       i2c_gpio: i2c@0 {
++                              reg = <0xffffffff>;
+                               compatible = "i2c-gpio";
+                               gpios = <&gpio 23 0 /* sda */
+                                        &gpio 24 0 /* scl */
diff --git a/target/linux/brcm2708/patches-4.19/950-0608-i2c-bcm2835-Ensure-clock-exists-when-probing.patch b/target/linux/brcm2708/patches-4.19/950-0608-i2c-bcm2835-Ensure-clock-exists-when-probing.patch
deleted file mode 100644 (file)
index 4a468f0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-From 1a5122f1756ef4fc5779324ad26b6a04142166b5 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Fri, 21 Jun 2019 03:52:50 -0700
-Subject: [PATCH] i2c: bcm2835: Ensure clock exists when probing
-
-Commit 9de93b04df16b055824e3f1f13fedb90fbcf2e4f upstream.
-
-Probe function fails to recognize that upstream clock actually
-doesn't yet exist because clock driver has not been initialized.
-Actually try to go get the clock and test for its existence
-before trying to set up a downstream clock based upon it.
-
-This fixes a bug that causes the i2c driver not to work with
-monolithic kernels.
-
-Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Acked-by: Stefan Wahren <wahrenst@gmx.net>
-Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
----
- drivers/i2c/busses/i2c-bcm2835.c | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -244,15 +244,18 @@ static const struct clk_ops clk_bcm2835_
- };
- static struct clk *bcm2835_i2c_register_div(struct device *dev,
--                                      const char *mclk_name,
-+                                      struct clk *mclk,
-                                       struct bcm2835_i2c_dev *i2c_dev)
- {
-       struct clk_init_data init;
-       struct clk_bcm2835_i2c *priv;
-       char name[32];
-+      const char *mclk_name;
-       snprintf(name, sizeof(name), "%s_div", dev_name(dev));
-+      mclk_name = __clk_get_name(mclk);
-+
-       init.ops = &clk_bcm2835_i2c_ops;
-       init.name = name;
-       init.parent_names = (const char* []) { mclk_name };
-@@ -505,8 +508,8 @@ static int bcm2835_i2c_probe(struct plat
-       struct resource *mem, *irq;
-       int ret;
-       struct i2c_adapter *adap;
--      const char *mclk_name;
-       struct clk *bus_clk;
-+      struct clk *mclk;
-       u32 bus_clk_rate;
-       i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
-@@ -521,9 +524,14 @@ static int bcm2835_i2c_probe(struct plat
-       if (IS_ERR(i2c_dev->regs))
-               return PTR_ERR(i2c_dev->regs);
--      mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
-+      mclk = devm_clk_get(&pdev->dev, NULL);
-+      if (IS_ERR(mclk)) {
-+              if (PTR_ERR(mclk) != -EPROBE_DEFER)
-+                      dev_err(&pdev->dev, "Could not get clock\n");
-+              return PTR_ERR(mclk);
-+      }
--      bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
-+      bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
-       if (IS_ERR(bus_clk)) {
-               dev_err(&pdev->dev, "Could not register clock\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0608-tty-amba-pl011-Make-TX-optimisation-conditional.patch b/target/linux/brcm2708/patches-4.19/950-0608-tty-amba-pl011-Make-TX-optimisation-conditional.patch
new file mode 100644 (file)
index 0000000..8d40afb
--- /dev/null
@@ -0,0 +1,85 @@
+From 3e3c13488e4efa0236c47a98ee5e759bf1f7c757 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 11 Jul 2019 13:13:39 +0100
+Subject: [PATCH] tty: amba-pl011: Make TX optimisation conditional
+
+pl011_tx_chars takes a "from_irq" parameter to reduce the number of
+register accesses. When from_irq is true the function assumes that the
+FIFO is half empty and writes up to half a FIFO's worth of bytes
+without polling the FIFO status register, the reasoning being that
+the function is being called as a result of the TX interrupt being
+raised. This logic would work were it not for the fact that
+pl011_rx_chars, called from pl011_int before pl011_tx_chars, releases
+the spinlock before calling tty_flip_buffer_push.
+
+A user thread writing to the UART claims the spinlock and ultimately
+calls pl011_tx_chars with from_irq set to false. This reverts to the
+older logic that polls the FIFO status register before sending every
+byte. If this happen on an SMP system during the section of the IRQ
+handler where the spinlock has been released, then by the time the TX
+interrupt handler is called, the FIFO may already be full, and any
+further writes are likely to be lost.
+
+The fix involves adding a per-port flag that is true iff running from
+within the interrupt handler and the spinlock has not yet been released.
+This flag is then used as the value for the from_irq parameter of
+pl011_tx_chars, causing polling to be used in the unsafe case.
+
+Fixes: 1e84d22322ce ("serial/amba-pl011: Refactor and simplify TX FIFO handling")
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/tty/serial/amba-pl011.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -270,6 +270,7 @@ struct uart_amba_port {
+       unsigned int            old_cr;         /* state during shutdown */
+       unsigned int            fixed_baud;     /* vendor-set fixed baud rate */
+       char                    type[12];
++      bool                    irq_locked;     /* in irq, unreleased lock */
+ #ifdef CONFIG_DMA_ENGINE
+       /* DMA stuff */
+       bool                    using_tx_dma;
+@@ -813,6 +814,7 @@ __acquires(&uap->port.lock)
+       if (!uap->using_tx_dma)
+               return;
++      uap->irq_locked = 0;
+       dmaengine_terminate_async(uap->dmatx.chan);
+       if (uap->dmatx.queued) {
+@@ -939,6 +941,7 @@ static void pl011_dma_rx_chars(struct ua
+               fifotaken = pl011_fifo_to_tty(uap);
+       }
++      uap->irq_locked = 0;
+       spin_unlock(&uap->port.lock);
+       dev_vdbg(uap->port.dev,
+                "Took %d chars from DMA buffer and %d chars from the FIFO\n",
+@@ -1347,6 +1350,7 @@ __acquires(&uap->port.lock)
+ {
+       pl011_fifo_to_tty(uap);
++      uap->irq_locked = 0;
+       spin_unlock(&uap->port.lock);
+       tty_flip_buffer_push(&uap->port.state->port);
+       /*
+@@ -1482,6 +1486,7 @@ static irqreturn_t pl011_int(int irq, vo
+       int handled = 0;
+       spin_lock_irqsave(&uap->port.lock, flags);
++      uap->irq_locked = 1;
+       status = pl011_read(uap, REG_RIS) & uap->im;
+       if (status) {
+               do {
+@@ -1501,7 +1506,7 @@ static irqreturn_t pl011_int(int irq, vo
+                                     UART011_CTSMIS|UART011_RIMIS))
+                               pl011_modem_status(uap);
+                       if (status & UART011_TXIS)
+-                              pl011_tx_chars(uap, true);
++                              pl011_tx_chars(uap, uap->irq_locked);
+                       if (pass_counter-- == 0)
+                               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0609-overlays-i2c-gpio-Fix-the-bus-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0609-overlays-i2c-gpio-Fix-the-bus-parameter.patch
deleted file mode 100644 (file)
index 9a6d155..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From d562b2187263b40aacc1a50d3f25db2cf28696d6 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 9 Jul 2019 10:32:40 +0100
-Subject: [PATCH] overlays: i2c-gpio: Fix the "bus" parameter
-
-The "bus" parameter has two functions - providing unique names for
-multiple instances of the overlay, and allowing the number of the bus
-(i.e. "i2c-<bus>") to be specified. The second function hasn't worked
-as intended because the overlay doesn't include a "reg" property and
-the firmware intentionally won't create a "reg" property if one doesn't
-already exist.
-
-Allow the bus numbering scheme to work as intended by providing a "reg"
-with a default value that means "the next available one".
-
-See: https://github.com/raspberrypi/linux/issues/3062
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- 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
-@@ -7,8 +7,10 @@
-       fragment@0 {
-               target-path = "/";
-+
-               __overlay__ {
-                       i2c_gpio: i2c@0 {
-+                              reg = <0xffffffff>;
-                               compatible = "i2c-gpio";
-                               gpios = <&gpio 23 0 /* sda */
-                                        &gpio 24 0 /* scl */
diff --git a/target/linux/brcm2708/patches-4.19/950-0609-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch b/target/linux/brcm2708/patches-4.19/950-0609-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch
new file mode 100644 (file)
index 0000000..3e413c7
--- /dev/null
@@ -0,0 +1,90 @@
+From 705bc230789927f96d6c9c70dc5475ebaf08aa54 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 11 Jul 2019 17:55:43 +0100
+Subject: [PATCH] xhci: add quirk for host controllers that don't
+ update endpoint DCS
+
+Seen on a VLI VL805 PCIe to USB controller. For non-stream endpoints
+at least, if the xHC halts on a particular TRB due to an error then
+the DCS field in the Out Endpoint Context maintained by the hardware
+is not updated with the current cycle state.
+
+Using the quirk XHCI_EP_CTX_BROKEN_DCS and instead fetch the DCS bit
+from the TRB that the xHC stopped on.
+
+See: https://github.com/raspberrypi/linux/issues/3060
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/xhci-pci.c  |  4 +++-
+ drivers/usb/host/xhci-ring.c | 26 +++++++++++++++++++++++++-
+ drivers/usb/host/xhci.h      |  1 +
+ 3 files changed, 29 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -223,8 +223,10 @@ static void xhci_pci_quirks(struct devic
+               xhci->quirks |= XHCI_BROKEN_STREAMS;
+       if (pdev->vendor == PCI_VENDOR_ID_VIA &&
+-                      pdev->device == 0x3483)
++                      pdev->device == 0x3483) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
++              xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
++      }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+                       pdev->device == 0x1042)
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -520,7 +520,10 @@ void xhci_find_new_dequeue_state(struct
+       struct xhci_virt_ep *ep = &dev->eps[ep_index];
+       struct xhci_ring *ep_ring;
+       struct xhci_segment *new_seg;
++      struct xhci_segment *halted_seg = NULL;
+       union xhci_trb *new_deq;
++      union xhci_trb *halted_trb;
++      int index = 0;
+       dma_addr_t addr;
+       u64 hw_dequeue;
+       bool cycle_found = false;
+@@ -541,7 +544,28 @@ void xhci_find_new_dequeue_state(struct
+       hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
+       new_seg = ep_ring->deq_seg;
+       new_deq = ep_ring->dequeue;
+-      state->new_cycle_state = hw_dequeue & 0x1;
++
++      /*
++       * Quirk: xHC write-back of the DCS field in the hardware dequeue
++       * pointer is wrong - use the cycle state of the TRB pointed to by
++       * the dequeue pointer.
++       */
++      if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
++          !(ep->ep_state & EP_HAS_STREAMS))
++              halted_seg = trb_in_td(xhci, cur_td->start_seg,
++                                     cur_td->first_trb, cur_td->last_trb,
++                                     hw_dequeue & ~0xf, false);
++      if (halted_seg) {
++              index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
++                       sizeof(*halted_trb);
++              halted_trb = &halted_seg->trbs[index];
++              state->new_cycle_state = halted_trb->generic.field[3] & 0x1;
++              xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
++                       (u8)(hw_dequeue & 0x1), index,
++                       state->new_cycle_state);
++      } else {
++              state->new_cycle_state = hw_dequeue & 0x1;
++      }
+       state->stream_id = stream_id;
+       /*
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1865,6 +1865,7 @@ struct xhci_hcd {
+ #define XHCI_ZERO_64B_REGS    BIT_ULL(32)
+ #define XHCI_RESET_PLL_ON_DISCONNECT  BIT_ULL(34)
+ #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
++#define XHCI_EP_CTX_BROKEN_DCS        BIT_ULL(36)
+       unsigned int            num_active_eps;
+       unsigned int            limit_active_eps;
diff --git a/target/linux/brcm2708/patches-4.19/950-0610-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch b/target/linux/brcm2708/patches-4.19/950-0610-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch
new file mode 100644 (file)
index 0000000..280cddf
--- /dev/null
@@ -0,0 +1,47 @@
+From 8d453e2193951057db696e37b9c10e7e35c18cb0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 12 Jul 2019 15:38:35 +0100
+Subject: [PATCH] i2c: bcm2835: Set clock-stretch timeout to 35ms
+
+The BCM2835 I2C blocks have a register to set the clock-stretch
+timeout - how long the device is allowed to hold SCL low - in bus
+cycles. The current driver doesn't write to the register, therefore
+the default value of 64 cycles is being used for all devices.
+
+Set the timeout to the value recommended for SMBus - 35ms.
+
+See: https://github.com/raspberrypi/linux/issues/3064
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -194,6 +194,7 @@ static int clk_bcm2835_i2c_set_rate(stru
+ {
+       struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
+       u32 redl, fedl;
++      u32 clk_tout;
+       u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
+       if (divider == -EINVAL)
+@@ -217,6 +218,17 @@ static int clk_bcm2835_i2c_set_rate(stru
+       bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
+                          (fedl << BCM2835_I2C_FEDL_SHIFT) |
+                          (redl << BCM2835_I2C_REDL_SHIFT));
++
++      /*
++       * Set the clock stretch timeout to the SMBUs-recommended 35ms.
++       */
++      if (rate > 0xffff*1000/35)
++          clk_tout = 0xffff;
++      else
++          clk_tout = 35*rate/1000;
++
++      bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_CLKT, clk_tout);
++
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0610-tty-amba-pl011-Make-TX-optimisation-conditional.patch b/target/linux/brcm2708/patches-4.19/950-0610-tty-amba-pl011-Make-TX-optimisation-conditional.patch
deleted file mode 100644 (file)
index 8d40afb..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-From 3e3c13488e4efa0236c47a98ee5e759bf1f7c757 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 11 Jul 2019 13:13:39 +0100
-Subject: [PATCH] tty: amba-pl011: Make TX optimisation conditional
-
-pl011_tx_chars takes a "from_irq" parameter to reduce the number of
-register accesses. When from_irq is true the function assumes that the
-FIFO is half empty and writes up to half a FIFO's worth of bytes
-without polling the FIFO status register, the reasoning being that
-the function is being called as a result of the TX interrupt being
-raised. This logic would work were it not for the fact that
-pl011_rx_chars, called from pl011_int before pl011_tx_chars, releases
-the spinlock before calling tty_flip_buffer_push.
-
-A user thread writing to the UART claims the spinlock and ultimately
-calls pl011_tx_chars with from_irq set to false. This reverts to the
-older logic that polls the FIFO status register before sending every
-byte. If this happen on an SMP system during the section of the IRQ
-handler where the spinlock has been released, then by the time the TX
-interrupt handler is called, the FIFO may already be full, and any
-further writes are likely to be lost.
-
-The fix involves adding a per-port flag that is true iff running from
-within the interrupt handler and the spinlock has not yet been released.
-This flag is then used as the value for the from_irq parameter of
-pl011_tx_chars, causing polling to be used in the unsafe case.
-
-Fixes: 1e84d22322ce ("serial/amba-pl011: Refactor and simplify TX FIFO handling")
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/tty/serial/amba-pl011.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/tty/serial/amba-pl011.c
-+++ b/drivers/tty/serial/amba-pl011.c
-@@ -270,6 +270,7 @@ struct uart_amba_port {
-       unsigned int            old_cr;         /* state during shutdown */
-       unsigned int            fixed_baud;     /* vendor-set fixed baud rate */
-       char                    type[12];
-+      bool                    irq_locked;     /* in irq, unreleased lock */
- #ifdef CONFIG_DMA_ENGINE
-       /* DMA stuff */
-       bool                    using_tx_dma;
-@@ -813,6 +814,7 @@ __acquires(&uap->port.lock)
-       if (!uap->using_tx_dma)
-               return;
-+      uap->irq_locked = 0;
-       dmaengine_terminate_async(uap->dmatx.chan);
-       if (uap->dmatx.queued) {
-@@ -939,6 +941,7 @@ static void pl011_dma_rx_chars(struct ua
-               fifotaken = pl011_fifo_to_tty(uap);
-       }
-+      uap->irq_locked = 0;
-       spin_unlock(&uap->port.lock);
-       dev_vdbg(uap->port.dev,
-                "Took %d chars from DMA buffer and %d chars from the FIFO\n",
-@@ -1347,6 +1350,7 @@ __acquires(&uap->port.lock)
- {
-       pl011_fifo_to_tty(uap);
-+      uap->irq_locked = 0;
-       spin_unlock(&uap->port.lock);
-       tty_flip_buffer_push(&uap->port.state->port);
-       /*
-@@ -1482,6 +1486,7 @@ static irqreturn_t pl011_int(int irq, vo
-       int handled = 0;
-       spin_lock_irqsave(&uap->port.lock, flags);
-+      uap->irq_locked = 1;
-       status = pl011_read(uap, REG_RIS) & uap->im;
-       if (status) {
-               do {
-@@ -1501,7 +1506,7 @@ static irqreturn_t pl011_int(int irq, vo
-                                     UART011_CTSMIS|UART011_RIMIS))
-                               pl011_modem_status(uap);
-                       if (status & UART011_TXIS)
--                              pl011_tx_chars(uap, true);
-+                              pl011_tx_chars(uap, uap->irq_locked);
-                       if (pass_counter-- == 0)
-                               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0611-arm64-bcm2835-Add-missing-dependency-on-MFD_CORE.patch b/target/linux/brcm2708/patches-4.19/950-0611-arm64-bcm2835-Add-missing-dependency-on-MFD_CORE.patch
new file mode 100644 (file)
index 0000000..c82ac8d
--- /dev/null
@@ -0,0 +1,28 @@
+From 39964e4a3a2ea18b48be5c31d7980895f0bdd99c Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 8 Mar 2019 13:02:16 -0800
+Subject: [PATCH] arm64: bcm2835: Add missing dependency on MFD_CORE.
+
+commit 7a9b6be9fe58194d9a349159176e8cc0d8f10ef8 upstream.
+
+When adding the MFD dependency for power domains and WDT in bcm2835, I
+added it only on the arm32 side and missed it for arm64.
+
+Fixes: 5e6acc3e678e ("bcm2835-pm: Move bcm2835-watchdog's DT probe to an MFD.")
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reported-by: Stefan Wahren <stefan.wahren@i2se.com>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ arch/arm64/Kconfig.platforms | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/Kconfig.platforms
++++ b/arch/arm64/Kconfig.platforms
+@@ -20,6 +20,7 @@ config ARCH_BCM2835
+       bool "Broadcom BCM2835 family"
+       select TIMER_OF
+       select GPIOLIB
++      select MFD_CORE
+       select PINCTRL
+       select PINCTRL_BCM2835
+       select ARM_AMBA
diff --git a/target/linux/brcm2708/patches-4.19/950-0611-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch b/target/linux/brcm2708/patches-4.19/950-0611-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch
deleted file mode 100644 (file)
index 3e413c7..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-From 705bc230789927f96d6c9c70dc5475ebaf08aa54 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Thu, 11 Jul 2019 17:55:43 +0100
-Subject: [PATCH] xhci: add quirk for host controllers that don't
- update endpoint DCS
-
-Seen on a VLI VL805 PCIe to USB controller. For non-stream endpoints
-at least, if the xHC halts on a particular TRB due to an error then
-the DCS field in the Out Endpoint Context maintained by the hardware
-is not updated with the current cycle state.
-
-Using the quirk XHCI_EP_CTX_BROKEN_DCS and instead fetch the DCS bit
-from the TRB that the xHC stopped on.
-
-See: https://github.com/raspberrypi/linux/issues/3060
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/host/xhci-pci.c  |  4 +++-
- drivers/usb/host/xhci-ring.c | 26 +++++++++++++++++++++++++-
- drivers/usb/host/xhci.h      |  1 +
- 3 files changed, 29 insertions(+), 2 deletions(-)
-
---- a/drivers/usb/host/xhci-pci.c
-+++ b/drivers/usb/host/xhci-pci.c
-@@ -223,8 +223,10 @@ static void xhci_pci_quirks(struct devic
-               xhci->quirks |= XHCI_BROKEN_STREAMS;
-       if (pdev->vendor == PCI_VENDOR_ID_VIA &&
--                      pdev->device == 0x3483)
-+                      pdev->device == 0x3483) {
-               xhci->quirks |= XHCI_LPM_SUPPORT;
-+              xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
-+      }
-       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
-                       pdev->device == 0x1042)
---- a/drivers/usb/host/xhci-ring.c
-+++ b/drivers/usb/host/xhci-ring.c
-@@ -520,7 +520,10 @@ void xhci_find_new_dequeue_state(struct
-       struct xhci_virt_ep *ep = &dev->eps[ep_index];
-       struct xhci_ring *ep_ring;
-       struct xhci_segment *new_seg;
-+      struct xhci_segment *halted_seg = NULL;
-       union xhci_trb *new_deq;
-+      union xhci_trb *halted_trb;
-+      int index = 0;
-       dma_addr_t addr;
-       u64 hw_dequeue;
-       bool cycle_found = false;
-@@ -541,7 +544,28 @@ void xhci_find_new_dequeue_state(struct
-       hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
-       new_seg = ep_ring->deq_seg;
-       new_deq = ep_ring->dequeue;
--      state->new_cycle_state = hw_dequeue & 0x1;
-+
-+      /*
-+       * Quirk: xHC write-back of the DCS field in the hardware dequeue
-+       * pointer is wrong - use the cycle state of the TRB pointed to by
-+       * the dequeue pointer.
-+       */
-+      if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
-+          !(ep->ep_state & EP_HAS_STREAMS))
-+              halted_seg = trb_in_td(xhci, cur_td->start_seg,
-+                                     cur_td->first_trb, cur_td->last_trb,
-+                                     hw_dequeue & ~0xf, false);
-+      if (halted_seg) {
-+              index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
-+                       sizeof(*halted_trb);
-+              halted_trb = &halted_seg->trbs[index];
-+              state->new_cycle_state = halted_trb->generic.field[3] & 0x1;
-+              xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
-+                       (u8)(hw_dequeue & 0x1), index,
-+                       state->new_cycle_state);
-+      } else {
-+              state->new_cycle_state = hw_dequeue & 0x1;
-+      }
-       state->stream_id = stream_id;
-       /*
---- a/drivers/usb/host/xhci.h
-+++ b/drivers/usb/host/xhci.h
-@@ -1865,6 +1865,7 @@ struct xhci_hcd {
- #define XHCI_ZERO_64B_REGS    BIT_ULL(32)
- #define XHCI_RESET_PLL_ON_DISCONNECT  BIT_ULL(34)
- #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
-+#define XHCI_EP_CTX_BROKEN_DCS        BIT_ULL(36)
-       unsigned int            num_active_eps;
-       unsigned int            limit_active_eps;
diff --git a/target/linux/brcm2708/patches-4.19/950-0612-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch b/target/linux/brcm2708/patches-4.19/950-0612-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch
deleted file mode 100644 (file)
index 280cddf..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From 8d453e2193951057db696e37b9c10e7e35c18cb0 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 12 Jul 2019 15:38:35 +0100
-Subject: [PATCH] i2c: bcm2835: Set clock-stretch timeout to 35ms
-
-The BCM2835 I2C blocks have a register to set the clock-stretch
-timeout - how long the device is allowed to hold SCL low - in bus
-cycles. The current driver doesn't write to the register, therefore
-the default value of 64 cycles is being used for all devices.
-
-Set the timeout to the value recommended for SMBus - 35ms.
-
-See: https://github.com/raspberrypi/linux/issues/3064
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/i2c/busses/i2c-bcm2835.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -194,6 +194,7 @@ static int clk_bcm2835_i2c_set_rate(stru
- {
-       struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
-       u32 redl, fedl;
-+      u32 clk_tout;
-       u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
-       if (divider == -EINVAL)
-@@ -217,6 +218,17 @@ static int clk_bcm2835_i2c_set_rate(stru
-       bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
-                          (fedl << BCM2835_I2C_FEDL_SHIFT) |
-                          (redl << BCM2835_I2C_REDL_SHIFT));
-+
-+      /*
-+       * Set the clock stretch timeout to the SMBUs-recommended 35ms.
-+       */
-+      if (rate > 0xffff*1000/35)
-+          clk_tout = 0xffff;
-+      else
-+          clk_tout = 35*rate/1000;
-+
-+      bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_CLKT, clk_tout);
-+
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0612-overlays-Add-PCF2129-RTC.patch b/target/linux/brcm2708/patches-4.19/950-0612-overlays-Add-PCF2129-RTC.patch
new file mode 100644 (file)
index 0000000..7bddfdc
--- /dev/null
@@ -0,0 +1,187 @@
+From 2308f60bb68de69306c542de3983be0007cad37b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 15 Jul 2019 10:39:05 +0100
+Subject: [PATCH] overlays: Add PCF2129 RTC
+
+Add support for the PCF2129 RTC to i2c-rtc and i2c-rtc-gpio overlays.
+Also add rv3028 to i2c-rtc-gpio (it was missed previously), and don't
+attempt to set an alternate address for the PCF2127.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README             | 11 ++++-
+ .../dts/overlays/i2c-rtc-gpio-overlay.dts     | 41 +++++++++++++++++--
+ .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 19 ++++++++-
+ 3 files changed, 64 insertions(+), 7 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1022,6 +1022,8 @@ Params: abx80x                  Select o
+         pcf2127                 Select the PCF2127 device
++        pcf2129                 Select the PCF2129 device
++
+         pcf8523                 Select the PCF8523 device
+         pcf8563                 Select the PCF8563 device
+@@ -1067,10 +1069,14 @@ Params: abx80x                  Select o
+         pcf2127                 Select the PCF2127 device
++        pcf2129                 Select the PCF2129 device
++
+         pcf8523                 Select the PCF8523 device
+         pcf8563                 Select the PCF8563 device
++        rv3028                  Select the Micro Crystal RV3028 device
++
+         addr                    Sets the address for the RTC. Note that the
+                                 device must be configured to use the specified
+                                 address.
+@@ -1079,11 +1085,14 @@ Params: abx80x                  Select o
+                                 "schottky" (ABx80x only)
+         trickle-resistor-ohms   Resistor value for trickle charge (DS1339,
+-                                ABx80x)
++                                ABx80x, RV3028)
+         wakeup-source           Specify that the RTC can be used as a wakeup
+                                 source
++        backup-switchover-mode  Backup power supply switch mode. Must be 0 for
++                                off or 1 for Vdd < VBackup (RV3028 only)
++
+         i2c_gpio_sda            GPIO used for I2C data (default "23")
+         i2c_gpio_scl            GPIO used for I2C clock (default "24")
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -121,7 +121,7 @@
+                       #size-cells = <0>;
+                       status = "okay";
+-                      pcf2127: pcf2127@51 {
++                      pcf2127@51 {
+                               compatible = "nxp,pcf2127";
+                               reg = <0x51>;
+                               status = "okay";
+@@ -174,6 +174,36 @@
+               };
+       };
++      fragment@11 {
++              target = <&i2c_gpio>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      rv3028: rv3028@52 {
++                              compatible = "microcrystal,rv3028";
++                              reg = <0x52>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@12 {
++              target = <&i2c_gpio>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      pcf2129@51 {
++                              compatible = "nxp,pcf2129";
++                              reg = <0x51>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+1";
+               ds1307 = <0>,"+2";
+@@ -185,6 +215,8 @@
+               pcf8523 = <0>,"+8";
+               pcf8563 = <0>,"+9";
+               m41t62 = <0>,"+10";
++              rv3028 = <0>,"+11";
++              pcf2129 = <0>,"+12";
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
+@@ -192,18 +224,19 @@
+                      <&ds3231>, "reg:0",
+                      <&mcp7940x>, "reg:0",
+                      <&mcp7941x>, "reg:0",
+-                     <&pcf2127>, "reg:0",
+                      <&pcf8523>, "reg:0",
+                      <&pcf8563>, "reg:0",
+                      <&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",
++                                      <&rv3028>,"trickle-resistor-ohms:0";
++              backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+               wakeup-source = <&ds1339>,"wakeup-source?",
+                               <&ds3231>,"wakeup-source?",
+                               <&mcp7940x>,"wakeup-source?",
+-                                      <&mcp7941x>,"wakeup-source?";
++                              <&mcp7941x>,"wakeup-source?";
+               i2c_gpio_sda = <&i2c_gpio>,"gpios:4";
+               i2c_gpio_scl = <&i2c_gpio>,"gpios:16";
+               i2c_gpio_delay_us = <&i2c_gpio>,"i2c-gpio,delay-us:0";
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -105,7 +105,7 @@
+                       #size-cells = <0>;
+                       status = "okay";
+-                      pcf2127: pcf2127@51 {
++                      pcf2127@51 {
+                               compatible = "nxp,pcf2127";
+                               reg = <0x51>;
+                               status = "okay";
+@@ -173,6 +173,21 @@
+               };
+       };
++      fragment@11 {
++              target = <&i2c_arm>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      pcf2129@51 {
++                              compatible = "nxp,pcf2129";
++                              reg = <0x51>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+0";
+               ds1307 = <0>,"+1";
+@@ -185,6 +200,7 @@
+               pcf8563 = <0>,"+8";
+               m41t62 = <0>,"+9";
+               rv3028 = <0>,"+10";
++              pcf2129 = <0>,"+11";
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
+@@ -192,7 +208,6 @@
+                      <&ds3231>, "reg:0",
+                      <&mcp7940x>, "reg:0",
+                      <&mcp7941x>, "reg:0",
+-                     <&pcf2127>, "reg:0",
+                      <&pcf8523>, "reg:0",
+                      <&pcf8563>, "reg:0",
+                      <&m41t62>, "reg:0";
diff --git a/target/linux/brcm2708/patches-4.19/950-0613-arm64-bcm2835-Add-missing-dependency-on-MFD_CORE.patch b/target/linux/brcm2708/patches-4.19/950-0613-arm64-bcm2835-Add-missing-dependency-on-MFD_CORE.patch
deleted file mode 100644 (file)
index c82ac8d..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 39964e4a3a2ea18b48be5c31d7980895f0bdd99c Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 8 Mar 2019 13:02:16 -0800
-Subject: [PATCH] arm64: bcm2835: Add missing dependency on MFD_CORE.
-
-commit 7a9b6be9fe58194d9a349159176e8cc0d8f10ef8 upstream.
-
-When adding the MFD dependency for power domains and WDT in bcm2835, I
-added it only on the arm32 side and missed it for arm64.
-
-Fixes: 5e6acc3e678e ("bcm2835-pm: Move bcm2835-watchdog's DT probe to an MFD.")
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reported-by: Stefan Wahren <stefan.wahren@i2se.com>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- arch/arm64/Kconfig.platforms | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm64/Kconfig.platforms
-+++ b/arch/arm64/Kconfig.platforms
-@@ -20,6 +20,7 @@ config ARCH_BCM2835
-       bool "Broadcom BCM2835 family"
-       select TIMER_OF
-       select GPIOLIB
-+      select MFD_CORE
-       select PINCTRL
-       select PINCTRL_BCM2835
-       select ARM_AMBA
diff --git a/target/linux/brcm2708/patches-4.19/950-0613-overlays-dpi18-and-dpi24-vc4-compatibility.patch b/target/linux/brcm2708/patches-4.19/950-0613-overlays-dpi18-and-dpi24-vc4-compatibility.patch
new file mode 100644 (file)
index 0000000..0b3e8ec
--- /dev/null
@@ -0,0 +1,52 @@
+From a5e0d604116189331d5608c9d128f37df17db2e3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 16 Jul 2019 15:24:12 +0100
+Subject: [PATCH] overlays: dpi18 and dpi24 vc4 compatibility
+
+The dpi overlays use the fb device tree node as a place to hang the
+necessary pinctrl changes. With one of the VC4 overlays loaded, the
+fb node is disabled so the changes have no effect.
+
+Modify the overlays to also use the vc4 node, to cover both use
+cases.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/dpi18-overlay.dts | 8 ++++++++
+ arch/arm/boot/dts/overlays/dpi24-overlay.dts | 8 ++++++++
+ 2 files changed, 16 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
+@@ -17,6 +17,14 @@
+       };
+       fragment@1 {
++              target = <&vc4>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&dpi18_pins>;
++              };
++      };
++
++      fragment@2 {
+               target = <&gpio>;
+               __overlay__ {
+                       dpi18_pins: dpi18_pins {
+--- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
+@@ -17,6 +17,14 @@
+       };
+       fragment@1 {
++              target = <&vc4>;
++              __overlay__ {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&dpi24_pins>;
++              };
++      };
++
++      fragment@2 {
+               target = <&gpio>;
+               __overlay__ {
+                       dpi24_pins: dpi24_pins {
diff --git a/target/linux/brcm2708/patches-4.19/950-0614-overlays-Add-PCF2129-RTC.patch b/target/linux/brcm2708/patches-4.19/950-0614-overlays-Add-PCF2129-RTC.patch
deleted file mode 100644 (file)
index 7bddfdc..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-From 2308f60bb68de69306c542de3983be0007cad37b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 15 Jul 2019 10:39:05 +0100
-Subject: [PATCH] overlays: Add PCF2129 RTC
-
-Add support for the PCF2129 RTC to i2c-rtc and i2c-rtc-gpio overlays.
-Also add rv3028 to i2c-rtc-gpio (it was missed previously), and don't
-attempt to set an alternate address for the PCF2127.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README             | 11 ++++-
- .../dts/overlays/i2c-rtc-gpio-overlay.dts     | 41 +++++++++++++++++--
- .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 19 ++++++++-
- 3 files changed, 64 insertions(+), 7 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1022,6 +1022,8 @@ Params: abx80x                  Select o
-         pcf2127                 Select the PCF2127 device
-+        pcf2129                 Select the PCF2129 device
-+
-         pcf8523                 Select the PCF8523 device
-         pcf8563                 Select the PCF8563 device
-@@ -1067,10 +1069,14 @@ Params: abx80x                  Select o
-         pcf2127                 Select the PCF2127 device
-+        pcf2129                 Select the PCF2129 device
-+
-         pcf8523                 Select the PCF8523 device
-         pcf8563                 Select the PCF8563 device
-+        rv3028                  Select the Micro Crystal RV3028 device
-+
-         addr                    Sets the address for the RTC. Note that the
-                                 device must be configured to use the specified
-                                 address.
-@@ -1079,11 +1085,14 @@ Params: abx80x                  Select o
-                                 "schottky" (ABx80x only)
-         trickle-resistor-ohms   Resistor value for trickle charge (DS1339,
--                                ABx80x)
-+                                ABx80x, RV3028)
-         wakeup-source           Specify that the RTC can be used as a wakeup
-                                 source
-+        backup-switchover-mode  Backup power supply switch mode. Must be 0 for
-+                                off or 1 for Vdd < VBackup (RV3028 only)
-+
-         i2c_gpio_sda            GPIO used for I2C data (default "23")
-         i2c_gpio_scl            GPIO used for I2C clock (default "24")
---- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-@@ -121,7 +121,7 @@
-                       #size-cells = <0>;
-                       status = "okay";
--                      pcf2127: pcf2127@51 {
-+                      pcf2127@51 {
-                               compatible = "nxp,pcf2127";
-                               reg = <0x51>;
-                               status = "okay";
-@@ -174,6 +174,36 @@
-               };
-       };
-+      fragment@11 {
-+              target = <&i2c_gpio>;
-+              __dormant__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      rv3028: rv3028@52 {
-+                              compatible = "microcrystal,rv3028";
-+                              reg = <0x52>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@12 {
-+              target = <&i2c_gpio>;
-+              __dormant__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      pcf2129@51 {
-+                              compatible = "nxp,pcf2129";
-+                              reg = <0x51>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-       __overrides__ {
-               abx80x = <0>,"+1";
-               ds1307 = <0>,"+2";
-@@ -185,6 +215,8 @@
-               pcf8523 = <0>,"+8";
-               pcf8563 = <0>,"+9";
-               m41t62 = <0>,"+10";
-+              rv3028 = <0>,"+11";
-+              pcf2129 = <0>,"+12";
-               addr = <&abx80x>, "reg:0",
-                      <&ds1307>, "reg:0",
-@@ -192,18 +224,19 @@
-                      <&ds3231>, "reg:0",
-                      <&mcp7940x>, "reg:0",
-                      <&mcp7941x>, "reg:0",
--                     <&pcf2127>, "reg:0",
-                      <&pcf8523>, "reg:0",
-                      <&pcf8563>, "reg:0",
-                      <&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",
-+                                      <&rv3028>,"trickle-resistor-ohms:0";
-+              backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
-               wakeup-source = <&ds1339>,"wakeup-source?",
-                               <&ds3231>,"wakeup-source?",
-                               <&mcp7940x>,"wakeup-source?",
--                                      <&mcp7941x>,"wakeup-source?";
-+                              <&mcp7941x>,"wakeup-source?";
-               i2c_gpio_sda = <&i2c_gpio>,"gpios:4";
-               i2c_gpio_scl = <&i2c_gpio>,"gpios:16";
-               i2c_gpio_delay_us = <&i2c_gpio>,"i2c-gpio,delay-us:0";
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -105,7 +105,7 @@
-                       #size-cells = <0>;
-                       status = "okay";
--                      pcf2127: pcf2127@51 {
-+                      pcf2127@51 {
-                               compatible = "nxp,pcf2127";
-                               reg = <0x51>;
-                               status = "okay";
-@@ -173,6 +173,21 @@
-               };
-       };
-+      fragment@11 {
-+              target = <&i2c_arm>;
-+              __dormant__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      pcf2129@51 {
-+                              compatible = "nxp,pcf2129";
-+                              reg = <0x51>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-       __overrides__ {
-               abx80x = <0>,"+0";
-               ds1307 = <0>,"+1";
-@@ -185,6 +200,7 @@
-               pcf8563 = <0>,"+8";
-               m41t62 = <0>,"+9";
-               rv3028 = <0>,"+10";
-+              pcf2129 = <0>,"+11";
-               addr = <&abx80x>, "reg:0",
-                      <&ds1307>, "reg:0",
-@@ -192,7 +208,6 @@
-                      <&ds3231>, "reg:0",
-                      <&mcp7940x>, "reg:0",
-                      <&mcp7941x>, "reg:0",
--                     <&pcf2127>, "reg:0",
-                      <&pcf8523>, "reg:0",
-                      <&pcf8563>, "reg:0",
-                      <&m41t62>, "reg:0";
diff --git a/target/linux/brcm2708/patches-4.19/950-0614-overlays-Add-i2c0-and-i2c1-for-regularity.patch b/target/linux/brcm2708/patches-4.19/950-0614-overlays-Add-i2c0-and-i2c1-for-regularity.patch
new file mode 100644 (file)
index 0000000..5b2c17b
--- /dev/null
@@ -0,0 +1,340 @@
+From 9c0f4b3e3b197d5c81f4bd6679f2c2456ab45c9e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 17 Jul 2019 10:08:55 +0100
+Subject: [PATCH] overlays: Add i2c0 and i2c1 for regularity
+
+The new i2c overlays for pi4 (i2c3, i2c4, i2c5, i2c6) have a
+standardised interface that allows pin groups to be chosen
+atomically rather than as individual pins. Add i2c0 and i2c1
+overlays to fit the naming scheme and parameter usage, deprecating
+i2c0-bcm2708 and i2c1-bcm2708.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  2 +
+ arch/arm/boot/dts/overlays/README             | 33 +++++---
+ .../dts/overlays/i2c0-bcm2708-overlay.dts     | 77 +++----------------
+ arch/arm/boot/dts/overlays/i2c0-overlay.dts   | 61 +++++++++++++++
+ .../dts/overlays/i2c1-bcm2708-overlay.dts     | 46 ++---------
+ arch/arm/boot/dts/overlays/i2c1-overlay.dts   | 44 +++++++++++
+ 6 files changed, 147 insertions(+), 116 deletions(-)
+ create mode 100644 arch/arm/boot/dts/overlays/i2c0-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c1-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -66,7 +66,9 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       i2c-rtc.dtbo \
+       i2c-rtc-gpio.dtbo \
+       i2c-sensor.dtbo \
++      i2c0.dtbo \
+       i2c0-bcm2708.dtbo \
++      i2c1.dtbo \
+       i2c1-bcm2708.dtbo \
+       i2c3.dtbo \
+       i2c4.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1151,14 +1151,12 @@ Params: addr                    Set the
+                                 sensor
+-Name:   i2c0-bcm2708
++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.
+-Load:   dtoverlay=i2c0-bcm2708,<param>=<val>
+-Params: sda0_pin                GPIO pin for SDA0 (deprecated - use pins_*)
+-        scl0_pin                GPIO pin for SCL0 (deprecated - use pins_*)
+-        pins_0_1                Use pins 0 and 1 (default)
++Load:   dtoverlay=i2c0,<param>=<val>
++Params: pins_0_1                Use pins 0 and 1 (default)
+         pins_28_29              Use pins 28 and 29
+         pins_44_45              Use pins 44 and 45
+         pins_46_47              Use pins 46 and 47
+@@ -1166,18 +1164,33 @@ Params: sda0_pin                GPIO pin
+                                 "yes")
+-Name:   i2c1-bcm2708
++Name:   i2c0-bcm2708
++Info:   Deprecated, legacy version of i2c0, from which it inherits its
++        parameters, just adding the explicit individual pin specifiers.
++Load:   <Deprecated>
++Params: sda0_pin                GPIO pin for SDA0 (deprecated - use pins_*)
++        scl0_pin                GPIO pin for SCL0 (deprecated - use pins_*)
++
++
++Name:   i2c1
+ Info:   Change i2c1 pin usage. Not all pin combinations are usable on all
+         platforms - platforms other then Compute Modules can only use this
+         to disable transaction combining.
+-Info:   Enable the i2c_bcm2708 driver for the i2c1 bus
+-Load:   dtoverlay=i2c1-bcm2708,<param>=<val>
++Load:   dtoverlay=i2c1,<param>=<val>
++Params: pins_2_3                Use pins 2 and 3 (default)
++        pins_44_45              Use pins 44 and 45
++        combine                 Allow transactions to be combined (default
++                                "yes")
++
++
++Name:   i2c1-bcm2708
++Info:   Deprecated, legacy version of i2c1, from which it inherits its
++        parameters, just adding the explicit individual pin specifiers.
++Load:   <Deprecated>
+ Params: sda1_pin                GPIO pin for SDA1 (2 or 44 - default 2)
+         scl1_pin                GPIO pin for SCL1 (3 or 45 - default 3)
+         pin_func                Alternative pin function (4 (alt0), 6 (alt2) -
+                                 default 4)
+-        combine                 Allow transactions to be combined (default
+-                                "yes")
+ Name:   i2c3
+--- a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
+@@ -1,69 +1,14 @@
+-/*
+- * Device tree overlay for i2c_bcm2708, i2c0 bus
+- *
+- * Compile:
+- * dtc -@ -I dts -O dtb -o i2c0-bcm2708-overlay.dtb i2c0-bcm2708-overlay.dts
+- */
+-
+-/dts-v1/;
+-/plugin/;
++#include "i2c0-overlay.dts"
+ /{
+-   compatible = "brcm,bcm2835";
+-
+-   fragment@0 {
+-      target = <&i2c0>;
+-      __overlay__ {
+-         status = "okay";
+-      };
+-   };
+-
+-   fragment@1 {
+-      target = <&i2c0_pins>;
+-      frag1: __overlay__ {
+-         brcm,pins = <0 1>;
+-         brcm,function = <4>; /* alt0 */
+-      };
+-   };
+-
+-   fragment@2 {
+-      target = <&i2c0_pins>;
+-      __dormant__ {
+-         brcm,pins = <28 29>;
+-         brcm,function = <4>; /* alt0 */
+-      };
+-   };
+-
+-   fragment@3 {
+-      target = <&i2c0_pins>;
+-      __dormant__ {
+-         brcm,pins = <44 45>;
+-         brcm,function = <5>; /* alt1 */
+-      };
+-   };
+-
+-   fragment@4 {
+-      target = <&i2c0_pins>;
+-      __dormant__ {
+-         brcm,pins = <46 47>;
+-         brcm,function = <4>; /* alt0 */
+-      };
+-   };
+-
+-   fragment@5 {
+-      target = <&i2c0>;
+-      __dormant__ {
+-         compatible = "brcm,bcm2708-i2c";
+-      };
+-   };
+-
+-   __overrides__ {
+-      sda0_pin = <&frag1>,"brcm,pins:0";
+-      scl0_pin = <&frag1>,"brcm,pins:4";
+-      pins_0_1   = <0>,"+1-2-3-4";
+-      pins_28_29 = <0>,"-1+2-3-4";
+-      pins_44_45 = <0>,"-1-2+3-4";
+-      pins_46_47 = <0>,"-1-2-3+4";
+-      combine = <0>, "!5";
+-   };
++      __overrides__ {
++              sda0_pin = <&pins1>,"brcm,pins:0",
++                         <&pins2>,"brcm,pins:0",
++                         <&pins3>,"brcm,pins:0",
++                         <&pins4>,"brcm,pins:0";
++              scl0_pin = <&pins1>,"brcm,pins:4",
++                         <&pins2>,"brcm,pins:4",
++                         <&pins3>,"brcm,pins:4",
++                         <&pins4>,"brcm,pins:4";
++      };
+ };
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c0-overlay.dts
+@@ -0,0 +1,61 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c0>;
++              __overlay__ {
++                      status = "okay";
++                      pinctrl-0 = <&i2c0_pins>;
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c0_pins>;
++              pins1: __overlay__ {
++                      brcm,pins = <0 1>;
++                      brcm,function = <4>; /* alt0 */
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c0_pins>;
++              pins2: __dormant__ {
++                      brcm,pins = <28 29>;
++                      brcm,function = <4>; /* alt0 */
++              };
++      };
++
++      fragment@3 {
++              target = <&i2c0_pins>;
++              pins3: __dormant__ {
++                      brcm,pins = <44 45>;
++                      brcm,function = <5>; /* alt1 */
++              };
++      };
++
++      fragment@4 {
++              target = <&i2c0_pins>;
++              pins4: __dormant__ {
++                      brcm,pins = <46 47>;
++                      brcm,function = <4>; /* alt0 */
++              };
++      };
++
++      fragment@5 {
++              target = <&i2c0>;
++              __dormant__ {
++                      compatible = "brcm,bcm2708-i2c";
++              };
++      };
++
++      __overrides__ {
++              pins_0_1   = <0>,"+1-2-3-4";
++              pins_28_29 = <0>,"-1+2-3-4";
++              pins_44_45 = <0>,"-1-2+3-4";
++              pins_46_47 = <0>,"-1-2-3+4";
++              combine = <0>, "!5";
++      };
++};
+--- a/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
+@@ -1,43 +1,9 @@
+-/*
+- * Device tree overlay for i2c_bcm2708, i2c1 bus
+- *
+- * Compile:
+- * dtc -@ -I dts -O dtb -o i2c1-bcm2708-overlay.dtb i2c1-bcm2708-overlay.dts
+- */
+-
+-/dts-v1/;
+-/plugin/;
++#include "i2c1-overlay.dts"
+ /{
+-   compatible = "brcm,bcm2835";
+-
+-   fragment@0 {
+-      target = <&i2c1>;
+-      __overlay__ {
+-         pinctrl-0 = <&i2c1_pins>;
+-         status = "okay";
+-      };
+-   };
+-
+-   fragment@1 {
+-      target = <&i2c1_pins>;
+-         pins: __overlay__ {
+-         brcm,pins = <2 3>;
+-         brcm,function = <4>; /* alt 0 */
+-      };
+-   };
+-
+-   fragment@2 {
+-      target = <&i2c1>;
+-      __dormant__ {
+-         compatible = "brcm,bcm2708-i2c";
+-      };
+-   };
+-
+-   __overrides__ {
+-      sda1_pin = <&pins>,"brcm,pins:0";
+-      scl1_pin = <&pins>,"brcm,pins:4";
+-      pin_func = <&pins>,"brcm,function:0";
+-      combine = <0>, "!2";
+-   };
++      __overrides__ {
++              sda1_pin = <&pins1>,"brcm,pins:0", <&pins2>,"brcm,pins:0";
++              scl1_pin = <&pins1>,"brcm,pins:4", <&pins1>,"brcm,pins:4";
++              pin_func = <&pins1>,"brcm,function:0", <&pins2>,"brcm,function:0";
++      };
+ };
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c1-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c1>;
++              __overlay__ {
++                      status = "okay";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c1_pins>;
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c1_pins>;
++              pins1: __overlay__ {
++                      brcm,pins = <2 3>;
++                      brcm,function = <4>; /* alt 0 */
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c1_pins>;
++              pins2: __dormant__ {
++                      brcm,pins = <44 45>;
++                      brcm,function = <6>; /* alt 2 */
++              };
++      };
++
++      fragment@3 {
++              target = <&i2c1>;
++              __dormant__ {
++                      compatible = "brcm,bcm2708-i2c";
++              };
++      };
++
++      __overrides__ {
++              pins_2_3   = <0>,"=1!2";
++              pins_44_45 = <0>,"!1=2";
++              combine = <0>, "!3";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0615-Pisound-Remove-spinlock-usage-around-spi_sync.patch b/target/linux/brcm2708/patches-4.19/950-0615-Pisound-Remove-spinlock-usage-around-spi_sync.patch
new file mode 100644 (file)
index 0000000..5dee4cb
--- /dev/null
@@ -0,0 +1,31 @@
+From ace4e8240d581e6053f0165b2682a2db745d49dc Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Fri, 12 Jul 2019 17:45:55 +0300
+Subject: [PATCH] Pisound: Remove spinlock usage around spi_sync
+
+---
+ sound/soc/bcm/pisound.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/sound/soc/bcm/pisound.c
++++ b/sound/soc/bcm/pisound.c
+@@ -286,9 +286,6 @@ static irqreturn_t data_available_interr
+       return IRQ_HANDLED;
+ }
+-static DEFINE_SPINLOCK(spilock);
+-static unsigned long spilockflags;
+-
+ static uint16_t spi_transfer16(uint16_t val)
+ {
+       uint8_t txbuf[2];
+@@ -333,9 +330,7 @@ static void spi_transfer(const uint8_t *
+       transfer.delay_usecs = 10;
+       spi_message_add_tail(&transfer, &msg);
+-      spin_lock_irqsave(&spilock, spilockflags);
+       err = spi_sync(pisnd_spi_device, &msg);
+-      spin_unlock_irqrestore(&spilock, spilockflags);
+       if (err < 0) {
+               printe("spi_sync error %d\n", err);
diff --git a/target/linux/brcm2708/patches-4.19/950-0615-overlays-dpi18-and-dpi24-vc4-compatibility.patch b/target/linux/brcm2708/patches-4.19/950-0615-overlays-dpi18-and-dpi24-vc4-compatibility.patch
deleted file mode 100644 (file)
index 0b3e8ec..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From a5e0d604116189331d5608c9d128f37df17db2e3 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 16 Jul 2019 15:24:12 +0100
-Subject: [PATCH] overlays: dpi18 and dpi24 vc4 compatibility
-
-The dpi overlays use the fb device tree node as a place to hang the
-necessary pinctrl changes. With one of the VC4 overlays loaded, the
-fb node is disabled so the changes have no effect.
-
-Modify the overlays to also use the vc4 node, to cover both use
-cases.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/dpi18-overlay.dts | 8 ++++++++
- arch/arm/boot/dts/overlays/dpi24-overlay.dts | 8 ++++++++
- 2 files changed, 16 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-@@ -17,6 +17,14 @@
-       };
-       fragment@1 {
-+              target = <&vc4>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&dpi18_pins>;
-+              };
-+      };
-+
-+      fragment@2 {
-               target = <&gpio>;
-               __overlay__ {
-                       dpi18_pins: dpi18_pins {
---- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-@@ -17,6 +17,14 @@
-       };
-       fragment@1 {
-+              target = <&vc4>;
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&dpi24_pins>;
-+              };
-+      };
-+
-+      fragment@2 {
-               target = <&gpio>;
-               __overlay__ {
-                       dpi24_pins: dpi24_pins {
diff --git a/target/linux/brcm2708/patches-4.19/950-0616-arm64-mm-Limit-the-DMA-zone-for-arm64.patch b/target/linux/brcm2708/patches-4.19/950-0616-arm64-mm-Limit-the-DMA-zone-for-arm64.patch
new file mode 100644 (file)
index 0000000..41261cd
--- /dev/null
@@ -0,0 +1,25 @@
+From 2722f08c4c59901bd506184e2dcbbbd532aef0b3 Mon Sep 17 00:00:00 2001
+From: Andrei Gherzan <andrei@balena.io>
+Date: Tue, 16 Jul 2019 13:28:22 +0100
+Subject: [PATCH] arm64/mm: Limit the DMA zone for arm64
+
+On RaspberryPi, only the first 1Gb can be used for DMA[1].
+
+[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2019-July/665986.html
+
+Signed-off-by: Andrei Gherzan <andrei@balena.io>
+---
+ arch/arm64/mm/init.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/mm/init.c
++++ b/arch/arm64/mm/init.c
+@@ -224,7 +224,7 @@ static void __init reserve_elfcorehdr(vo
+ static phys_addr_t __init max_zone_dma_phys(void)
+ {
+       phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
+-      return min(offset + (1ULL << 32), memblock_end_of_DRAM());
++      return min(offset + (1ULL << 30), memblock_end_of_DRAM());
+ }
+ #ifdef CONFIG_NUMA
diff --git a/target/linux/brcm2708/patches-4.19/950-0616-overlays-Add-i2c0-and-i2c1-for-regularity.patch b/target/linux/brcm2708/patches-4.19/950-0616-overlays-Add-i2c0-and-i2c1-for-regularity.patch
deleted file mode 100644 (file)
index 5b2c17b..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-From 9c0f4b3e3b197d5c81f4bd6679f2c2456ab45c9e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 17 Jul 2019 10:08:55 +0100
-Subject: [PATCH] overlays: Add i2c0 and i2c1 for regularity
-
-The new i2c overlays for pi4 (i2c3, i2c4, i2c5, i2c6) have a
-standardised interface that allows pin groups to be chosen
-atomically rather than as individual pins. Add i2c0 and i2c1
-overlays to fit the naming scheme and parameter usage, deprecating
-i2c0-bcm2708 and i2c1-bcm2708.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile           |  2 +
- arch/arm/boot/dts/overlays/README             | 33 +++++---
- .../dts/overlays/i2c0-bcm2708-overlay.dts     | 77 +++----------------
- arch/arm/boot/dts/overlays/i2c0-overlay.dts   | 61 +++++++++++++++
- .../dts/overlays/i2c1-bcm2708-overlay.dts     | 46 ++---------
- arch/arm/boot/dts/overlays/i2c1-overlay.dts   | 44 +++++++++++
- 6 files changed, 147 insertions(+), 116 deletions(-)
- create mode 100644 arch/arm/boot/dts/overlays/i2c0-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/i2c1-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -66,7 +66,9 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       i2c-rtc.dtbo \
-       i2c-rtc-gpio.dtbo \
-       i2c-sensor.dtbo \
-+      i2c0.dtbo \
-       i2c0-bcm2708.dtbo \
-+      i2c1.dtbo \
-       i2c1-bcm2708.dtbo \
-       i2c3.dtbo \
-       i2c4.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1151,14 +1151,12 @@ Params: addr                    Set the
-                                 sensor
--Name:   i2c0-bcm2708
-+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.
--Load:   dtoverlay=i2c0-bcm2708,<param>=<val>
--Params: sda0_pin                GPIO pin for SDA0 (deprecated - use pins_*)
--        scl0_pin                GPIO pin for SCL0 (deprecated - use pins_*)
--        pins_0_1                Use pins 0 and 1 (default)
-+Load:   dtoverlay=i2c0,<param>=<val>
-+Params: pins_0_1                Use pins 0 and 1 (default)
-         pins_28_29              Use pins 28 and 29
-         pins_44_45              Use pins 44 and 45
-         pins_46_47              Use pins 46 and 47
-@@ -1166,18 +1164,33 @@ Params: sda0_pin                GPIO pin
-                                 "yes")
--Name:   i2c1-bcm2708
-+Name:   i2c0-bcm2708
-+Info:   Deprecated, legacy version of i2c0, from which it inherits its
-+        parameters, just adding the explicit individual pin specifiers.
-+Load:   <Deprecated>
-+Params: sda0_pin                GPIO pin for SDA0 (deprecated - use pins_*)
-+        scl0_pin                GPIO pin for SCL0 (deprecated - use pins_*)
-+
-+
-+Name:   i2c1
- Info:   Change i2c1 pin usage. Not all pin combinations are usable on all
-         platforms - platforms other then Compute Modules can only use this
-         to disable transaction combining.
--Info:   Enable the i2c_bcm2708 driver for the i2c1 bus
--Load:   dtoverlay=i2c1-bcm2708,<param>=<val>
-+Load:   dtoverlay=i2c1,<param>=<val>
-+Params: pins_2_3                Use pins 2 and 3 (default)
-+        pins_44_45              Use pins 44 and 45
-+        combine                 Allow transactions to be combined (default
-+                                "yes")
-+
-+
-+Name:   i2c1-bcm2708
-+Info:   Deprecated, legacy version of i2c1, from which it inherits its
-+        parameters, just adding the explicit individual pin specifiers.
-+Load:   <Deprecated>
- Params: sda1_pin                GPIO pin for SDA1 (2 or 44 - default 2)
-         scl1_pin                GPIO pin for SCL1 (3 or 45 - default 3)
-         pin_func                Alternative pin function (4 (alt0), 6 (alt2) -
-                                 default 4)
--        combine                 Allow transactions to be combined (default
--                                "yes")
- Name:   i2c3
---- a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
-@@ -1,69 +1,14 @@
--/*
-- * Device tree overlay for i2c_bcm2708, i2c0 bus
-- *
-- * Compile:
-- * dtc -@ -I dts -O dtb -o i2c0-bcm2708-overlay.dtb i2c0-bcm2708-overlay.dts
-- */
--
--/dts-v1/;
--/plugin/;
-+#include "i2c0-overlay.dts"
- /{
--   compatible = "brcm,bcm2835";
--
--   fragment@0 {
--      target = <&i2c0>;
--      __overlay__ {
--         status = "okay";
--      };
--   };
--
--   fragment@1 {
--      target = <&i2c0_pins>;
--      frag1: __overlay__ {
--         brcm,pins = <0 1>;
--         brcm,function = <4>; /* alt0 */
--      };
--   };
--
--   fragment@2 {
--      target = <&i2c0_pins>;
--      __dormant__ {
--         brcm,pins = <28 29>;
--         brcm,function = <4>; /* alt0 */
--      };
--   };
--
--   fragment@3 {
--      target = <&i2c0_pins>;
--      __dormant__ {
--         brcm,pins = <44 45>;
--         brcm,function = <5>; /* alt1 */
--      };
--   };
--
--   fragment@4 {
--      target = <&i2c0_pins>;
--      __dormant__ {
--         brcm,pins = <46 47>;
--         brcm,function = <4>; /* alt0 */
--      };
--   };
--
--   fragment@5 {
--      target = <&i2c0>;
--      __dormant__ {
--         compatible = "brcm,bcm2708-i2c";
--      };
--   };
--
--   __overrides__ {
--      sda0_pin = <&frag1>,"brcm,pins:0";
--      scl0_pin = <&frag1>,"brcm,pins:4";
--      pins_0_1   = <0>,"+1-2-3-4";
--      pins_28_29 = <0>,"-1+2-3-4";
--      pins_44_45 = <0>,"-1-2+3-4";
--      pins_46_47 = <0>,"-1-2-3+4";
--      combine = <0>, "!5";
--   };
-+      __overrides__ {
-+              sda0_pin = <&pins1>,"brcm,pins:0",
-+                         <&pins2>,"brcm,pins:0",
-+                         <&pins3>,"brcm,pins:0",
-+                         <&pins4>,"brcm,pins:0";
-+              scl0_pin = <&pins1>,"brcm,pins:4",
-+                         <&pins2>,"brcm,pins:4",
-+                         <&pins3>,"brcm,pins:4",
-+                         <&pins4>,"brcm,pins:4";
-+      };
- };
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c0-overlay.dts
-@@ -0,0 +1,61 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&i2c0>;
-+              __overlay__ {
-+                      status = "okay";
-+                      pinctrl-0 = <&i2c0_pins>;
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c0_pins>;
-+              pins1: __overlay__ {
-+                      brcm,pins = <0 1>;
-+                      brcm,function = <4>; /* alt0 */
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&i2c0_pins>;
-+              pins2: __dormant__ {
-+                      brcm,pins = <28 29>;
-+                      brcm,function = <4>; /* alt0 */
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&i2c0_pins>;
-+              pins3: __dormant__ {
-+                      brcm,pins = <44 45>;
-+                      brcm,function = <5>; /* alt1 */
-+              };
-+      };
-+
-+      fragment@4 {
-+              target = <&i2c0_pins>;
-+              pins4: __dormant__ {
-+                      brcm,pins = <46 47>;
-+                      brcm,function = <4>; /* alt0 */
-+              };
-+      };
-+
-+      fragment@5 {
-+              target = <&i2c0>;
-+              __dormant__ {
-+                      compatible = "brcm,bcm2708-i2c";
-+              };
-+      };
-+
-+      __overrides__ {
-+              pins_0_1   = <0>,"+1-2-3-4";
-+              pins_28_29 = <0>,"-1+2-3-4";
-+              pins_44_45 = <0>,"-1-2+3-4";
-+              pins_46_47 = <0>,"-1-2-3+4";
-+              combine = <0>, "!5";
-+      };
-+};
---- a/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
-@@ -1,43 +1,9 @@
--/*
-- * Device tree overlay for i2c_bcm2708, i2c1 bus
-- *
-- * Compile:
-- * dtc -@ -I dts -O dtb -o i2c1-bcm2708-overlay.dtb i2c1-bcm2708-overlay.dts
-- */
--
--/dts-v1/;
--/plugin/;
-+#include "i2c1-overlay.dts"
- /{
--   compatible = "brcm,bcm2835";
--
--   fragment@0 {
--      target = <&i2c1>;
--      __overlay__ {
--         pinctrl-0 = <&i2c1_pins>;
--         status = "okay";
--      };
--   };
--
--   fragment@1 {
--      target = <&i2c1_pins>;
--         pins: __overlay__ {
--         brcm,pins = <2 3>;
--         brcm,function = <4>; /* alt 0 */
--      };
--   };
--
--   fragment@2 {
--      target = <&i2c1>;
--      __dormant__ {
--         compatible = "brcm,bcm2708-i2c";
--      };
--   };
--
--   __overrides__ {
--      sda1_pin = <&pins>,"brcm,pins:0";
--      scl1_pin = <&pins>,"brcm,pins:4";
--      pin_func = <&pins>,"brcm,function:0";
--      combine = <0>, "!2";
--   };
-+      __overrides__ {
-+              sda1_pin = <&pins1>,"brcm,pins:0", <&pins2>,"brcm,pins:0";
-+              scl1_pin = <&pins1>,"brcm,pins:4", <&pins1>,"brcm,pins:4";
-+              pin_func = <&pins1>,"brcm,function:0", <&pins2>,"brcm,function:0";
-+      };
- };
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c1-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      status = "okay";
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&i2c1_pins>;
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c1_pins>;
-+              pins1: __overlay__ {
-+                      brcm,pins = <2 3>;
-+                      brcm,function = <4>; /* alt 0 */
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&i2c1_pins>;
-+              pins2: __dormant__ {
-+                      brcm,pins = <44 45>;
-+                      brcm,function = <6>; /* alt 2 */
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&i2c1>;
-+              __dormant__ {
-+                      compatible = "brcm,bcm2708-i2c";
-+              };
-+      };
-+
-+      __overrides__ {
-+              pins_2_3   = <0>,"=1!2";
-+              pins_44_45 = <0>,"!1=2";
-+              combine = <0>, "!3";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0617-Pisound-Remove-spinlock-usage-around-spi_sync.patch b/target/linux/brcm2708/patches-4.19/950-0617-Pisound-Remove-spinlock-usage-around-spi_sync.patch
deleted file mode 100644 (file)
index 5dee4cb..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From ace4e8240d581e6053f0165b2682a2db745d49dc Mon Sep 17 00:00:00 2001
-From: Giedrius <giedrius@blokas.io>
-Date: Fri, 12 Jul 2019 17:45:55 +0300
-Subject: [PATCH] Pisound: Remove spinlock usage around spi_sync
-
----
- sound/soc/bcm/pisound.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/sound/soc/bcm/pisound.c
-+++ b/sound/soc/bcm/pisound.c
-@@ -286,9 +286,6 @@ static irqreturn_t data_available_interr
-       return IRQ_HANDLED;
- }
--static DEFINE_SPINLOCK(spilock);
--static unsigned long spilockflags;
--
- static uint16_t spi_transfer16(uint16_t val)
- {
-       uint8_t txbuf[2];
-@@ -333,9 +330,7 @@ static void spi_transfer(const uint8_t *
-       transfer.delay_usecs = 10;
-       spi_message_add_tail(&transfer, &msg);
--      spin_lock_irqsave(&spilock, spilockflags);
-       err = spi_sync(pisnd_spi_device, &msg);
--      spin_unlock_irqrestore(&spilock, spilockflags);
-       if (err < 0) {
-               printe("spi_sync error %d\n", err);
diff --git a/target/linux/brcm2708/patches-4.19/950-0617-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch b/target/linux/brcm2708/patches-4.19/950-0617-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch
new file mode 100644 (file)
index 0000000..00d0252
--- /dev/null
@@ -0,0 +1,194 @@
+From 5620f5eda349027a6e00e23391bc59617d25b449 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 3 Jul 2019 17:44:53 +0100
+Subject: [PATCH] drm/vc4: Query firmware for custom HDMI mode
+
+Allow custom HDMI modes to be specified from config.txt,
+and these then override EDID parsing.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 142 ++++++++++++++-----------
+ 1 file changed, 81 insertions(+), 61 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1035,6 +1035,58 @@ vc4_fkms_connector_detect(struct drm_con
+       return connector_status_connected;
+ }
++/* Queries the firmware to populate a drm_mode structure for this display */
++static int vc4_fkms_get_fw_mode(struct vc4_fkms_connector *fkms_connector,
++                              struct drm_display_mode *mode)
++{
++      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
++      struct set_timings timings = { 0 };
++      int ret;
++
++      timings.display = fkms_connector->display_number;
++
++      ret = rpi_firmware_property(vc4->firmware,
++                                  RPI_FIRMWARE_GET_DISPLAY_TIMING, &timings,
++                                  sizeof(timings));
++      if (ret || !timings.clock)
++              /* No mode returned - abort */
++              return -1;
++
++      /* Equivalent to DRM_MODE macro. */
++      memset(mode, 0, sizeof(*mode));
++      strncpy(mode->name, "FIXED_MODE", sizeof(mode->name));
++      mode->status = 0;
++      mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
++      mode->clock = timings.clock;
++      mode->hdisplay = timings.hdisplay;
++      mode->hsync_start = timings.hsync_start;
++      mode->hsync_end = timings.hsync_end;
++      mode->htotal = timings.htotal;
++      mode->hskew = 0;
++      mode->vdisplay = timings.vdisplay;
++      mode->vsync_start = timings.vsync_start;
++      mode->vsync_end = timings.vsync_end;
++      mode->vtotal = timings.vtotal;
++      mode->vscan = timings.vscan;
++
++      if (timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
++              mode->flags |= DRM_MODE_FLAG_PHSYNC;
++      else
++              mode->flags |= DRM_MODE_FLAG_NHSYNC;
++
++      if (timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
++              mode->flags |= DRM_MODE_FLAG_PVSYNC;
++      else
++              mode->flags |= DRM_MODE_FLAG_NVSYNC;
++
++      if (timings.flags & TIMINGS_FLAGS_INTERLACE)
++              mode->flags |= DRM_MODE_FLAG_INTERLACE;
++
++      mode->base.type = DRM_MODE_OBJECT_MODE;
++
++      return 0;
++}
++
+ static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
+                                  size_t len)
+ {
+@@ -1063,30 +1115,40 @@ static int vc4_fkms_connector_get_modes(
+                                       to_vc4_fkms_connector(connector);
+       struct drm_encoder *encoder = fkms_connector->encoder;
+       struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
+-      int ret = 0;
++      struct drm_display_mode fw_mode;
++      struct drm_display_mode *mode;
+       struct edid *edid;
++      int num_modes;
+-      edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
+-                             fkms_connector);
++      if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode)) {
++              drm_mode_debug_printmodeline(&fw_mode);
++              mode = drm_mode_duplicate(connector->dev,
++                                        &fw_mode);
++              drm_mode_probed_add(connector, mode);
++              num_modes = 1;  /* 1 mode */
++      } else {
++              edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
++                                     fkms_connector);
+-      /* FIXME: Can we do CEC?
+-       * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
+-       * if (!edid)
+-       *      return -ENODEV;
+-       */
+-
+-      vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
+-
+-      if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+-              vc4_encoder->rgb_range_selectable =
+-                      drm_rgb_quant_range_selectable(edid);
++              /* FIXME: Can we do CEC?
++               * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
++               * if (!edid)
++               *      return -ENODEV;
++               */
++
++              vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
++
++              if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
++                      vc4_encoder->rgb_range_selectable =
++                              drm_rgb_quant_range_selectable(edid);
++              }
++
++              drm_connector_update_edid_property(connector, edid);
++              num_modes = drm_add_edid_modes(connector, edid);
++              kfree(edid);
+       }
+-      drm_connector_update_edid_property(connector, edid);
+-      ret = drm_add_edid_modes(connector, edid);
+-      kfree(edid);
+-
+-      return ret;
++      return num_modes;
+ }
+ /* This is the DSI panel resolution. Use this as a default should the firmware
+@@ -1104,57 +1166,15 @@ static int vc4_fkms_lcd_connector_get_mo
+ {
+       struct vc4_fkms_connector *fkms_connector =
+                                       to_vc4_fkms_connector(connector);
+-      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
+       struct drm_display_mode *mode;
+-      struct mailbox_set_mode mb = {
+-              .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
+-                        sizeof(struct set_timings), 0},
+-              .timings = { .display = fkms_connector->display_number },
+-      };
+       struct drm_display_mode fw_mode;
+-      int ret = 0;
+-
+-      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
+-      if (!ret) {
+-              /* Equivalent to DRM_MODE macro. */
+-              memset(&fw_mode, 0, sizeof(fw_mode));
+-              strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
+-              fw_mode.status = 0;
+-              fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+-              fw_mode.clock = mb.timings.clock;
+-              fw_mode.hdisplay = mb.timings.hdisplay;
+-              fw_mode.hsync_start = mb.timings.hsync_start;
+-              fw_mode.hsync_end = mb.timings.hsync_end;
+-              fw_mode.htotal = mb.timings.htotal;
+-              fw_mode.hskew = 0;
+-              fw_mode.vdisplay = mb.timings.vdisplay;
+-              fw_mode.vsync_start = mb.timings.vsync_start;
+-              fw_mode.vsync_end = mb.timings.vsync_end;
+-              fw_mode.vtotal = mb.timings.vtotal;
+-              fw_mode.vscan = mb.timings.vscan;
+-              if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
+-                      fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
+-              else
+-                      fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
+-              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
+-                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
+-              else
+-                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
+-              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
+-                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
+-              else
+-                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
+-              if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
+-                      fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
+-
+-              fw_mode.base.type = DRM_MODE_OBJECT_MODE;
++      if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode) && fw_mode.clock)
+               mode = drm_mode_duplicate(connector->dev,
+                                         &fw_mode);
+-      } else {
++      else
+               mode = drm_mode_duplicate(connector->dev,
+                                         &lcd_mode);
+-      }
+       if (!mode) {
+               DRM_ERROR("Failed to create a new display mode\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0618-arm64-mm-Limit-the-DMA-zone-for-arm64.patch b/target/linux/brcm2708/patches-4.19/950-0618-arm64-mm-Limit-the-DMA-zone-for-arm64.patch
deleted file mode 100644 (file)
index 41261cd..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 2722f08c4c59901bd506184e2dcbbbd532aef0b3 Mon Sep 17 00:00:00 2001
-From: Andrei Gherzan <andrei@balena.io>
-Date: Tue, 16 Jul 2019 13:28:22 +0100
-Subject: [PATCH] arm64/mm: Limit the DMA zone for arm64
-
-On RaspberryPi, only the first 1Gb can be used for DMA[1].
-
-[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2019-July/665986.html
-
-Signed-off-by: Andrei Gherzan <andrei@balena.io>
----
- arch/arm64/mm/init.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm64/mm/init.c
-+++ b/arch/arm64/mm/init.c
-@@ -224,7 +224,7 @@ static void __init reserve_elfcorehdr(vo
- static phys_addr_t __init max_zone_dma_phys(void)
- {
-       phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
--      return min(offset + (1ULL << 32), memblock_end_of_DRAM());
-+      return min(offset + (1ULL << 30), memblock_end_of_DRAM());
- }
- #ifdef CONFIG_NUMA
diff --git a/target/linux/brcm2708/patches-4.19/950-0618-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch b/target/linux/brcm2708/patches-4.19/950-0618-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch
new file mode 100644 (file)
index 0000000..9f5b9e1
--- /dev/null
@@ -0,0 +1,37 @@
+From 2c0bfade955e4e660941db287020d06c9e22267f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 11 Jul 2019 15:12:05 +0100
+Subject: [PATCH] drm/vc4: Pass the drm vrefresh to the firmware on
+ mode set
+
+More for completeness than need, but use drm_mode_vrefresh
+to compute the vrefresh value, and pass that down to the
+firmware on mode set.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -737,8 +737,8 @@ static void vc4_crtc_mode_set_nofb(struc
+                     mode->hdisplay, mode->hsync_start, mode->hsync_end,
+                     mode->htotal, mode->hskew, mode->vdisplay,
+                     mode->vsync_start, mode->vsync_end, mode->vtotal,
+-                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
+-                    mode->flags);
++                    mode->vscan, drm_mode_vrefresh(mode),
++                    mode->picture_aspect_ratio, mode->flags);
+       mb.timings.display = vc4_crtc->display_number;
+       mb.timings.video_id_code = frame.avi.video_code;
+@@ -754,7 +754,7 @@ static void vc4_crtc_mode_set_nofb(struc
+       mb.timings.vsync_end = mode->vsync_end;
+       mb.timings.vtotal = mode->vtotal;
+       mb.timings.vscan = mode->vscan;
+-      mb.timings.vrefresh = 0;
++      mb.timings.vrefresh = drm_mode_vrefresh(mode);
+       mb.timings.flags = 0;
+       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+               mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
diff --git a/target/linux/brcm2708/patches-4.19/950-0619-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch b/target/linux/brcm2708/patches-4.19/950-0619-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch
deleted file mode 100644 (file)
index 00d0252..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-From 5620f5eda349027a6e00e23391bc59617d25b449 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 3 Jul 2019 17:44:53 +0100
-Subject: [PATCH] drm/vc4: Query firmware for custom HDMI mode
-
-Allow custom HDMI modes to be specified from config.txt,
-and these then override EDID parsing.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 142 ++++++++++++++-----------
- 1 file changed, 81 insertions(+), 61 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1035,6 +1035,58 @@ vc4_fkms_connector_detect(struct drm_con
-       return connector_status_connected;
- }
-+/* Queries the firmware to populate a drm_mode structure for this display */
-+static int vc4_fkms_get_fw_mode(struct vc4_fkms_connector *fkms_connector,
-+                              struct drm_display_mode *mode)
-+{
-+      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
-+      struct set_timings timings = { 0 };
-+      int ret;
-+
-+      timings.display = fkms_connector->display_number;
-+
-+      ret = rpi_firmware_property(vc4->firmware,
-+                                  RPI_FIRMWARE_GET_DISPLAY_TIMING, &timings,
-+                                  sizeof(timings));
-+      if (ret || !timings.clock)
-+              /* No mode returned - abort */
-+              return -1;
-+
-+      /* Equivalent to DRM_MODE macro. */
-+      memset(mode, 0, sizeof(*mode));
-+      strncpy(mode->name, "FIXED_MODE", sizeof(mode->name));
-+      mode->status = 0;
-+      mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-+      mode->clock = timings.clock;
-+      mode->hdisplay = timings.hdisplay;
-+      mode->hsync_start = timings.hsync_start;
-+      mode->hsync_end = timings.hsync_end;
-+      mode->htotal = timings.htotal;
-+      mode->hskew = 0;
-+      mode->vdisplay = timings.vdisplay;
-+      mode->vsync_start = timings.vsync_start;
-+      mode->vsync_end = timings.vsync_end;
-+      mode->vtotal = timings.vtotal;
-+      mode->vscan = timings.vscan;
-+
-+      if (timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
-+              mode->flags |= DRM_MODE_FLAG_PHSYNC;
-+      else
-+              mode->flags |= DRM_MODE_FLAG_NHSYNC;
-+
-+      if (timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
-+              mode->flags |= DRM_MODE_FLAG_PVSYNC;
-+      else
-+              mode->flags |= DRM_MODE_FLAG_NVSYNC;
-+
-+      if (timings.flags & TIMINGS_FLAGS_INTERLACE)
-+              mode->flags |= DRM_MODE_FLAG_INTERLACE;
-+
-+      mode->base.type = DRM_MODE_OBJECT_MODE;
-+
-+      return 0;
-+}
-+
- static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
-                                  size_t len)
- {
-@@ -1063,30 +1115,40 @@ static int vc4_fkms_connector_get_modes(
-                                       to_vc4_fkms_connector(connector);
-       struct drm_encoder *encoder = fkms_connector->encoder;
-       struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
--      int ret = 0;
-+      struct drm_display_mode fw_mode;
-+      struct drm_display_mode *mode;
-       struct edid *edid;
-+      int num_modes;
--      edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
--                             fkms_connector);
-+      if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode)) {
-+              drm_mode_debug_printmodeline(&fw_mode);
-+              mode = drm_mode_duplicate(connector->dev,
-+                                        &fw_mode);
-+              drm_mode_probed_add(connector, mode);
-+              num_modes = 1;  /* 1 mode */
-+      } else {
-+              edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
-+                                     fkms_connector);
--      /* FIXME: Can we do CEC?
--       * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
--       * if (!edid)
--       *      return -ENODEV;
--       */
--
--      vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
--
--      if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
--              vc4_encoder->rgb_range_selectable =
--                      drm_rgb_quant_range_selectable(edid);
-+              /* FIXME: Can we do CEC?
-+               * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
-+               * if (!edid)
-+               *      return -ENODEV;
-+               */
-+
-+              vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
-+
-+              if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
-+                      vc4_encoder->rgb_range_selectable =
-+                              drm_rgb_quant_range_selectable(edid);
-+              }
-+
-+              drm_connector_update_edid_property(connector, edid);
-+              num_modes = drm_add_edid_modes(connector, edid);
-+              kfree(edid);
-       }
--      drm_connector_update_edid_property(connector, edid);
--      ret = drm_add_edid_modes(connector, edid);
--      kfree(edid);
--
--      return ret;
-+      return num_modes;
- }
- /* This is the DSI panel resolution. Use this as a default should the firmware
-@@ -1104,57 +1166,15 @@ static int vc4_fkms_lcd_connector_get_mo
- {
-       struct vc4_fkms_connector *fkms_connector =
-                                       to_vc4_fkms_connector(connector);
--      struct vc4_dev *vc4 = fkms_connector->vc4_dev;
-       struct drm_display_mode *mode;
--      struct mailbox_set_mode mb = {
--              .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
--                        sizeof(struct set_timings), 0},
--              .timings = { .display = fkms_connector->display_number },
--      };
-       struct drm_display_mode fw_mode;
--      int ret = 0;
--
--      ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
--      if (!ret) {
--              /* Equivalent to DRM_MODE macro. */
--              memset(&fw_mode, 0, sizeof(fw_mode));
--              strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
--              fw_mode.status = 0;
--              fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
--              fw_mode.clock = mb.timings.clock;
--              fw_mode.hdisplay = mb.timings.hdisplay;
--              fw_mode.hsync_start = mb.timings.hsync_start;
--              fw_mode.hsync_end = mb.timings.hsync_end;
--              fw_mode.htotal = mb.timings.htotal;
--              fw_mode.hskew = 0;
--              fw_mode.vdisplay = mb.timings.vdisplay;
--              fw_mode.vsync_start = mb.timings.vsync_start;
--              fw_mode.vsync_end = mb.timings.vsync_end;
--              fw_mode.vtotal = mb.timings.vtotal;
--              fw_mode.vscan = mb.timings.vscan;
--              if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
--                      fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
--              else
--                      fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
--              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
--                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
--              else
--                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
--              if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
--                      fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
--              else
--                      fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
--              if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
--                      fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
--
--              fw_mode.base.type = DRM_MODE_OBJECT_MODE;
-+      if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode) && fw_mode.clock)
-               mode = drm_mode_duplicate(connector->dev,
-                                         &fw_mode);
--      } else {
-+      else
-               mode = drm_mode_duplicate(connector->dev,
-                                         &lcd_mode);
--      }
-       if (!mode) {
-               DRM_ERROR("Failed to create a new display mode\n");
diff --git a/target/linux/brcm2708/patches-4.19/950-0619-overlays-audremap-Support-GPIOs-18-19.patch b/target/linux/brcm2708/patches-4.19/950-0619-overlays-audremap-Support-GPIOs-18-19.patch
new file mode 100644 (file)
index 0000000..667e104
--- /dev/null
@@ -0,0 +1,68 @@
+From f42cc245e1f3e586f1a26550e5760489b6c329ab Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 23 Jul 2019 12:55:07 +0100
+Subject: [PATCH] overlays: audremap: Support GPIOs 18 & 19
+
+PWM audio can also be used on GPIOs 18 and 19, so add the pins_18_19
+parameter to select that location. pins_12_13 explicitly chooses GPIOs
+12 and 13, although this is the default behaviour so is there only for
+completeness.
+
+See: https://github.com/raspberrypi/firmware/issues/1178
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README               |  4 +++-
+ arch/arm/boot/dts/overlays/audremap-overlay.dts | 16 ++++++++++++++++
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -475,12 +475,14 @@ Params: <None>
+ Name:   audremap
+-Info:   Switches PWM sound output to pins 12 (Right) & 13 (Left)
++Info:   Switches PWM sound output to GPIOs on the 40-pin header
+ Load:   dtoverlay=audremap,<param>=<val>
+ Params: swap_lr                 Reverse the channel allocation, which will also
+                                 swap the audio jack outputs (default off)
+         enable_jack             Don't switch off the audio jack output
+                                 (default off)
++        pins_12_13              Select GPIOs 12 & 13 (default)
++        pins_18_19              Select GPIOs 18 & 19
+ Name:   balena-fin
+--- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
+@@ -7,13 +7,29 @@
+         fragment@0 {
+                 target = <&audio_pins>;
+                 frag0: __overlay__ {
++                };
++        };
++
++      fragment@1 {
++                target = <&audio_pins>;
++                __overlay__ {
+                         brcm,pins = < 12 13 >;
+                         brcm,function = < 4 >; /* alt0 alt0 */
+                 };
+         };
++      fragment@2 {
++              target = <&audio_pins>;
++              __dormant__ {
++                        brcm,pins = < 18 19 >;
++                        brcm,function = < 2 >; /* alt5 alt5 */
++              };
++      };
++
+       __overrides__ {
+               swap_lr = <&frag0>, "swap_lr?";
+               enable_jack = <&frag0>, "enable_jack?";
++              pins_12_13 = <0>,"+1-2";
++              pins_18_19 = <0>,"-1+2";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0620-drm-connector-Fix-drm_mode_create_tv_properties-doc.patch b/target/linux/brcm2708/patches-4.19/950-0620-drm-connector-Fix-drm_mode_create_tv_properties-doc.patch
new file mode 100644 (file)
index 0000000..8cc04b7
--- /dev/null
@@ -0,0 +1,29 @@
+From ce5c3d732efb5e3da50119ed876f0d6661f08b84 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:35 +0100
+Subject: [PATCH] drm/connector: Fix drm_mode_create_tv_properties()
+ doc
+
+Commit eda6887f1961e0d2fb866b1a520b2de5b3828de5 upstream.
+
+The in the kernel-doc header did not match the function name.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-2-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/drm_connector.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -1110,7 +1110,7 @@ void drm_hdmi_avi_infoframe_content_type
+ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
+ /**
+- * drm_create_tv_properties - create TV specific connector properties
++ * drm_mode_create_tv_properties - create TV specific connector properties
+  * @dev: DRM device
+  * @num_modes: number of different TV formats (modes) supported
+  * @modes: array of pointers to strings containing name of each format
diff --git a/target/linux/brcm2708/patches-4.19/950-0620-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch b/target/linux/brcm2708/patches-4.19/950-0620-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch
deleted file mode 100644 (file)
index 9f5b9e1..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 2c0bfade955e4e660941db287020d06c9e22267f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 11 Jul 2019 15:12:05 +0100
-Subject: [PATCH] drm/vc4: Pass the drm vrefresh to the firmware on
- mode set
-
-More for completeness than need, but use drm_mode_vrefresh
-to compute the vrefresh value, and pass that down to the
-firmware on mode set.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -737,8 +737,8 @@ static void vc4_crtc_mode_set_nofb(struc
-                     mode->hdisplay, mode->hsync_start, mode->hsync_end,
-                     mode->htotal, mode->hskew, mode->vdisplay,
-                     mode->vsync_start, mode->vsync_end, mode->vtotal,
--                    mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
--                    mode->flags);
-+                    mode->vscan, drm_mode_vrefresh(mode),
-+                    mode->picture_aspect_ratio, mode->flags);
-       mb.timings.display = vc4_crtc->display_number;
-       mb.timings.video_id_code = frame.avi.video_code;
-@@ -754,7 +754,7 @@ static void vc4_crtc_mode_set_nofb(struc
-       mb.timings.vsync_end = mode->vsync_end;
-       mb.timings.vtotal = mode->vtotal;
-       mb.timings.vscan = mode->vscan;
--      mb.timings.vrefresh = 0;
-+      mb.timings.vrefresh = drm_mode_vrefresh(mode);
-       mb.timings.flags = 0;
-       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
-               mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
diff --git a/target/linux/brcm2708/patches-4.19/950-0621-drm-connector-Clarify-the-unit-of-TV-margins.patch b/target/linux/brcm2708/patches-4.19/950-0621-drm-connector-Clarify-the-unit-of-TV-margins.patch
new file mode 100644 (file)
index 0000000..85b56a3
--- /dev/null
@@ -0,0 +1,58 @@
+From 4589a8a086094061e7476d41578e31349accc190 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:36 +0100
+Subject: [PATCH] drm/connector: Clarify the unit of TV margins
+
+Commit 56406e15b5e83256151ef74eb1a219cbf13d91c8 upstream.
+
+All margins are expressed in pixels. Clarify that in the doc.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-3-boris.brezillon@bootlin.com
+---
+ include/drm/drm_connector.h   | 2 +-
+ include/drm/drm_mode_config.h | 8 ++++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -346,7 +346,7 @@ int drm_display_info_set_bus_formats(str
+ /**
+  * struct drm_tv_connector_state - TV connector related states
+  * @subconnector: selected subconnector
+- * @margins: margins
++ * @margins: margins (all margins are expressed in pixels)
+  * @margins.left: left margin
+  * @margins.right: right margin
+  * @margins.top: top margin
+--- a/include/drm/drm_mode_config.h
++++ b/include/drm/drm_mode_config.h
+@@ -668,22 +668,22 @@ struct drm_mode_config {
+       struct drm_property *tv_mode_property;
+       /**
+        * @tv_left_margin_property: Optional TV property to set the left
+-       * margin.
++       * margin (expressed in pixels).
+        */
+       struct drm_property *tv_left_margin_property;
+       /**
+        * @tv_right_margin_property: Optional TV property to set the right
+-       * margin.
++       * margin (expressed in pixels).
+        */
+       struct drm_property *tv_right_margin_property;
+       /**
+        * @tv_top_margin_property: Optional TV property to set the right
+-       * margin.
++       * margin (expressed in pixels).
+        */
+       struct drm_property *tv_top_margin_property;
+       /**
+        * @tv_bottom_margin_property: Optional TV property to set the right
+-       * margin.
++       * margin (expressed in pixels).
+        */
+       struct drm_property *tv_bottom_margin_property;
+       /**
diff --git a/target/linux/brcm2708/patches-4.19/950-0621-overlays-audremap-Support-GPIOs-18-19.patch b/target/linux/brcm2708/patches-4.19/950-0621-overlays-audremap-Support-GPIOs-18-19.patch
deleted file mode 100644 (file)
index 667e104..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-From f42cc245e1f3e586f1a26550e5760489b6c329ab Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 23 Jul 2019 12:55:07 +0100
-Subject: [PATCH] overlays: audremap: Support GPIOs 18 & 19
-
-PWM audio can also be used on GPIOs 18 and 19, so add the pins_18_19
-parameter to select that location. pins_12_13 explicitly chooses GPIOs
-12 and 13, although this is the default behaviour so is there only for
-completeness.
-
-See: https://github.com/raspberrypi/firmware/issues/1178
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README               |  4 +++-
- arch/arm/boot/dts/overlays/audremap-overlay.dts | 16 ++++++++++++++++
- 2 files changed, 19 insertions(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -475,12 +475,14 @@ Params: <None>
- Name:   audremap
--Info:   Switches PWM sound output to pins 12 (Right) & 13 (Left)
-+Info:   Switches PWM sound output to GPIOs on the 40-pin header
- Load:   dtoverlay=audremap,<param>=<val>
- Params: swap_lr                 Reverse the channel allocation, which will also
-                                 swap the audio jack outputs (default off)
-         enable_jack             Don't switch off the audio jack output
-                                 (default off)
-+        pins_12_13              Select GPIOs 12 & 13 (default)
-+        pins_18_19              Select GPIOs 18 & 19
- Name:   balena-fin
---- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
-@@ -7,13 +7,29 @@
-         fragment@0 {
-                 target = <&audio_pins>;
-                 frag0: __overlay__ {
-+                };
-+        };
-+
-+      fragment@1 {
-+                target = <&audio_pins>;
-+                __overlay__ {
-                         brcm,pins = < 12 13 >;
-                         brcm,function = < 4 >; /* alt0 alt0 */
-                 };
-         };
-+      fragment@2 {
-+              target = <&audio_pins>;
-+              __dormant__ {
-+                        brcm,pins = < 18 19 >;
-+                        brcm,function = < 2 >; /* alt5 alt5 */
-+              };
-+      };
-+
-       __overrides__ {
-               swap_lr = <&frag0>, "swap_lr?";
-               enable_jack = <&frag0>, "enable_jack?";
-+              pins_12_13 = <0>,"+1-2";
-+              pins_18_19 = <0>,"-1+2";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0622-drm-connector-Allow-creation-of-margin-props-alone.patch b/target/linux/brcm2708/patches-4.19/950-0622-drm-connector-Allow-creation-of-margin-props-alone.patch
new file mode 100644 (file)
index 0000000..1b242f4
--- /dev/null
@@ -0,0 +1,136 @@
+From 4f2277b18d6bbb6fac50b751c4e513619849b23c Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:37 +0100
+Subject: [PATCH] drm/connector: Allow creation of margin props alone
+
+Commit 6c4f52dca36f5e3e2354c30591d38e92f4657ed9 upstream.
+
+TV margins properties can only be added as part of the SDTV TV
+connector properties creation, but we might need those props for HDMI
+TVs too, so let's move the margins props creation in a separate
+function and expose it to drivers.
+
+We also add an helper to attach margins props to a connector.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-4-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/drm_connector.c | 83 ++++++++++++++++++++++++++-------
+ include/drm/drm_connector.h     |  2 +
+ 2 files changed, 67 insertions(+), 18 deletions(-)
+
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -1110,6 +1110,70 @@ void drm_hdmi_avi_infoframe_content_type
+ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
+ /**
++ * drm_mode_attach_tv_margin_properties - attach TV connector margin properties
++ * @connector: DRM connector
++ *
++ * Called by a driver when it needs to attach TV margin props to a connector.
++ * Typically used on SDTV and HDMI connectors.
++ */
++void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)
++{
++      struct drm_device *dev = connector->dev;
++
++      drm_object_attach_property(&connector->base,
++                                 dev->mode_config.tv_left_margin_property,
++                                 0);
++      drm_object_attach_property(&connector->base,
++                                 dev->mode_config.tv_right_margin_property,
++                                 0);
++      drm_object_attach_property(&connector->base,
++                                 dev->mode_config.tv_top_margin_property,
++                                 0);
++      drm_object_attach_property(&connector->base,
++                                 dev->mode_config.tv_bottom_margin_property,
++                                 0);
++}
++EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
++
++/**
++ * drm_mode_create_tv_margin_properties - create TV connector margin properties
++ * @dev: DRM device
++ *
++ * Called by a driver's HDMI connector initialization routine, this function
++ * creates the TV margin properties for a given device. No need to call this
++ * function for an SDTV connector, it's already called from
++ * drm_mode_create_tv_properties().
++ */
++int drm_mode_create_tv_margin_properties(struct drm_device *dev)
++{
++      if (dev->mode_config.tv_left_margin_property)
++              return 0;
++
++      dev->mode_config.tv_left_margin_property =
++              drm_property_create_range(dev, 0, "left margin", 0, 100);
++      if (!dev->mode_config.tv_left_margin_property)
++              return -ENOMEM;
++
++      dev->mode_config.tv_right_margin_property =
++              drm_property_create_range(dev, 0, "right margin", 0, 100);
++      if (!dev->mode_config.tv_right_margin_property)
++              return -ENOMEM;
++
++      dev->mode_config.tv_top_margin_property =
++              drm_property_create_range(dev, 0, "top margin", 0, 100);
++      if (!dev->mode_config.tv_top_margin_property)
++              return -ENOMEM;
++
++      dev->mode_config.tv_bottom_margin_property =
++              drm_property_create_range(dev, 0, "bottom margin", 0, 100);
++      if (!dev->mode_config.tv_bottom_margin_property)
++              return -ENOMEM;
++
++      return 0;
++}
++EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
++
++/**
+  * drm_mode_create_tv_properties - create TV specific connector properties
+  * @dev: DRM device
+  * @num_modes: number of different TV formats (modes) supported
+@@ -1155,24 +1219,7 @@ int drm_mode_create_tv_properties(struct
+       /*
+        * Other, TV specific properties: margins & TV modes.
+        */
+-      dev->mode_config.tv_left_margin_property =
+-              drm_property_create_range(dev, 0, "left margin", 0, 100);
+-      if (!dev->mode_config.tv_left_margin_property)
+-              goto nomem;
+-
+-      dev->mode_config.tv_right_margin_property =
+-              drm_property_create_range(dev, 0, "right margin", 0, 100);
+-      if (!dev->mode_config.tv_right_margin_property)
+-              goto nomem;
+-
+-      dev->mode_config.tv_top_margin_property =
+-              drm_property_create_range(dev, 0, "top margin", 0, 100);
+-      if (!dev->mode_config.tv_top_margin_property)
+-              goto nomem;
+-
+-      dev->mode_config.tv_bottom_margin_property =
+-              drm_property_create_range(dev, 0, "bottom margin", 0, 100);
+-      if (!dev->mode_config.tv_bottom_margin_property)
++      if (drm_mode_create_tv_margin_properties(dev))
+               goto nomem;
+       dev->mode_config.tv_mode_property =
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -1175,9 +1175,11 @@ const char *drm_get_tv_select_name(int v
+ const char *drm_get_content_protection_name(int val);
+ int drm_mode_create_dvi_i_properties(struct drm_device *dev);
++int drm_mode_create_tv_margin_properties(struct drm_device *dev);
+ int drm_mode_create_tv_properties(struct drm_device *dev,
+                                 unsigned int num_modes,
+                                 const char * const modes[]);
++void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
+ int drm_mode_create_scaling_mode_property(struct drm_device *dev);
+ int drm_connector_attach_content_type_property(struct drm_connector *dev);
+ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
diff --git a/target/linux/brcm2708/patches-4.19/950-0622-drm-connector-Fix-drm_mode_create_tv_properties-doc.patch b/target/linux/brcm2708/patches-4.19/950-0622-drm-connector-Fix-drm_mode_create_tv_properties-doc.patch
deleted file mode 100644 (file)
index 8cc04b7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From ce5c3d732efb5e3da50119ed876f0d6661f08b84 Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Thu, 6 Dec 2018 15:24:35 +0100
-Subject: [PATCH] drm/connector: Fix drm_mode_create_tv_properties()
- doc
-
-Commit eda6887f1961e0d2fb866b1a520b2de5b3828de5 upstream.
-
-The in the kernel-doc header did not match the function name.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-2-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/drm_connector.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/drm_connector.c
-+++ b/drivers/gpu/drm/drm_connector.c
-@@ -1110,7 +1110,7 @@ void drm_hdmi_avi_infoframe_content_type
- EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
- /**
-- * drm_create_tv_properties - create TV specific connector properties
-+ * drm_mode_create_tv_properties - create TV specific connector properties
-  * @dev: DRM device
-  * @num_modes: number of different TV formats (modes) supported
-  * @modes: array of pointers to strings containing name of each format
diff --git a/target/linux/brcm2708/patches-4.19/950-0623-drm-connector-Clarify-the-unit-of-TV-margins.patch b/target/linux/brcm2708/patches-4.19/950-0623-drm-connector-Clarify-the-unit-of-TV-margins.patch
deleted file mode 100644 (file)
index 85b56a3..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 4589a8a086094061e7476d41578e31349accc190 Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Thu, 6 Dec 2018 15:24:36 +0100
-Subject: [PATCH] drm/connector: Clarify the unit of TV margins
-
-Commit 56406e15b5e83256151ef74eb1a219cbf13d91c8 upstream.
-
-All margins are expressed in pixels. Clarify that in the doc.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-3-boris.brezillon@bootlin.com
----
- include/drm/drm_connector.h   | 2 +-
- include/drm/drm_mode_config.h | 8 ++++----
- 2 files changed, 5 insertions(+), 5 deletions(-)
-
---- a/include/drm/drm_connector.h
-+++ b/include/drm/drm_connector.h
-@@ -346,7 +346,7 @@ int drm_display_info_set_bus_formats(str
- /**
-  * struct drm_tv_connector_state - TV connector related states
-  * @subconnector: selected subconnector
-- * @margins: margins
-+ * @margins: margins (all margins are expressed in pixels)
-  * @margins.left: left margin
-  * @margins.right: right margin
-  * @margins.top: top margin
---- a/include/drm/drm_mode_config.h
-+++ b/include/drm/drm_mode_config.h
-@@ -668,22 +668,22 @@ struct drm_mode_config {
-       struct drm_property *tv_mode_property;
-       /**
-        * @tv_left_margin_property: Optional TV property to set the left
--       * margin.
-+       * margin (expressed in pixels).
-        */
-       struct drm_property *tv_left_margin_property;
-       /**
-        * @tv_right_margin_property: Optional TV property to set the right
--       * margin.
-+       * margin (expressed in pixels).
-        */
-       struct drm_property *tv_right_margin_property;
-       /**
-        * @tv_top_margin_property: Optional TV property to set the right
--       * margin.
-+       * margin (expressed in pixels).
-        */
-       struct drm_property *tv_top_margin_property;
-       /**
-        * @tv_bottom_margin_property: Optional TV property to set the right
--       * margin.
-+       * margin (expressed in pixels).
-        */
-       struct drm_property *tv_bottom_margin_property;
-       /**
diff --git a/target/linux/brcm2708/patches-4.19/950-0623-drm-vc4-Take-margin-setup-into-account-when-updating.patch b/target/linux/brcm2708/patches-4.19/950-0623-drm-vc4-Take-margin-setup-into-account-when-updating.patch
new file mode 100644 (file)
index 0000000..a50be7a
--- /dev/null
@@ -0,0 +1,185 @@
+From 0d592a7685e41d0bb1816a4fedb11d3570474417 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:38 +0100
+Subject: [PATCH] drm/vc4: Take margin setup into account when updating
+ planes
+
+Commit 666e73587f90f42d90385c1bea1009a650bf73f4 upstream.
+
+Applyin margins is just a matter of scaling all planes appropriately
+and adjusting the CRTC X/Y offset to account for the
+left/right/top/bottom borders.
+
+Create a vc4_plane_margins_adj() function doing that and call it from
+vc4_plane_setup_clipping_and_scaling() so that we are ready to attach
+margins properties to the HDMI connector.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-5-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c  | 43 +++++++++++++++++++++++++++
+ drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++
+ drivers/gpu/drm/vc4/vc4_plane.c | 51 +++++++++++++++++++++++++++++++++
+ 3 files changed, 97 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -48,6 +48,13 @@ struct vc4_crtc_state {
+       struct drm_mm_node mm;
+       bool feed_txp;
+       bool txp_armed;
++
++      struct {
++              unsigned int left;
++              unsigned int right;
++              unsigned int top;
++              unsigned int bottom;
++      } margins;
+ };
+ static inline struct vc4_crtc_state *
+@@ -623,6 +630,37 @@ static enum drm_mode_status vc4_crtc_mod
+       return MODE_OK;
+ }
++void vc4_crtc_get_margins(struct drm_crtc_state *state,
++                        unsigned int *left, unsigned int *right,
++                        unsigned int *top, unsigned int *bottom)
++{
++      struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
++      struct drm_connector_state *conn_state;
++      struct drm_connector *conn;
++      int i;
++
++      *left = vc4_state->margins.left;
++      *right = vc4_state->margins.right;
++      *top = vc4_state->margins.top;
++      *bottom = vc4_state->margins.bottom;
++
++      /* We have to interate over all new connector states because
++       * vc4_crtc_get_margins() might be called before
++       * vc4_crtc_atomic_check() which means margins info in vc4_crtc_state
++       * might be outdated.
++       */
++      for_each_new_connector_in_state(state->state, conn, conn_state, i) {
++              if (conn_state->crtc != state->crtc)
++                      continue;
++
++              *left = conn_state->tv.margins.left;
++              *right = conn_state->tv.margins.right;
++              *top = conn_state->tv.margins.top;
++              *bottom = conn_state->tv.margins.bottom;
++              break;
++      }
++}
++
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+                                struct drm_crtc_state *state)
+ {
+@@ -670,6 +708,10 @@ static int vc4_crtc_atomic_check(struct
+                       vc4_state->feed_txp = false;
+               }
++              vc4_state->margins.left = conn_state->tv.margins.left;
++              vc4_state->margins.right = conn_state->tv.margins.right;
++              vc4_state->margins.top = conn_state->tv.margins.top;
++              vc4_state->margins.bottom = conn_state->tv.margins.bottom;
+               break;
+       }
+@@ -971,6 +1013,7 @@ static struct drm_crtc_state *vc4_crtc_d
+       old_vc4_state = to_vc4_crtc_state(crtc->state);
+       vc4_state->feed_txp = old_vc4_state->feed_txp;
++      vc4_state->margins = old_vc4_state->margins;
+       __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
+       return &vc4_state->base;
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -705,6 +705,9 @@ bool vc4_crtc_get_scanoutpos(struct drm_
+                            const struct drm_display_mode *mode);
+ void vc4_crtc_handle_vblank(struct vc4_crtc *crtc);
+ void vc4_crtc_txp_armed(struct drm_crtc_state *state);
++void vc4_crtc_get_margins(struct drm_crtc_state *state,
++                        unsigned int *right, unsigned int *left,
++                        unsigned int *top, unsigned int *bottom);
+ /* vc4_debugfs.c */
+ int vc4_debugfs_init(struct drm_minor *minor);
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -258,6 +258,52 @@ static u32 vc4_get_scl_field(struct drm_
+       }
+ }
++static int vc4_plane_margins_adj(struct drm_plane_state *pstate)
++{
++      struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate);
++      unsigned int left, right, top, bottom, adjhdisplay, adjvdisplay;
++      struct drm_crtc_state *crtc_state;
++
++      crtc_state = drm_atomic_get_new_crtc_state(pstate->state,
++                                                 pstate->crtc);
++
++      vc4_crtc_get_margins(crtc_state, &left, &right, &top, &bottom);
++      if (!left && !right && !top && !bottom)
++              return 0;
++
++      if (left + right >= crtc_state->mode.hdisplay ||
++          top + bottom >= crtc_state->mode.vdisplay)
++              return -EINVAL;
++
++      adjhdisplay = crtc_state->mode.hdisplay - (left + right);
++      vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x *
++                                             adjhdisplay,
++                                             crtc_state->mode.hdisplay);
++      vc4_pstate->crtc_x += left;
++      if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left)
++              vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left;
++
++      adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
++      vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y *
++                                             adjvdisplay,
++                                             crtc_state->mode.vdisplay);
++      vc4_pstate->crtc_y += top;
++      if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top)
++              vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top;
++
++      vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w *
++                                             adjhdisplay,
++                                             crtc_state->mode.hdisplay);
++      vc4_pstate->crtc_h = DIV_ROUND_CLOSEST(vc4_pstate->crtc_h *
++                                             adjvdisplay,
++                                             crtc_state->mode.vdisplay);
++
++      if (!vc4_pstate->crtc_w || !vc4_pstate->crtc_h)
++              return -EINVAL;
++
++      return 0;
++}
++
+ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
+ {
+       struct drm_plane *plane = state->plane;
+@@ -269,6 +315,7 @@ static int vc4_plane_setup_clipping_and_
+       int num_planes = fb->format->num_planes;
+       u32 h_subsample = 1;
+       u32 v_subsample = 1;
++      int ret;
+       int i;
+       for (i = 0; i < num_planes; i++)
+@@ -292,6 +339,10 @@ static int vc4_plane_setup_clipping_and_
+       vc4_state->crtc_w = state->crtc_w;
+       vc4_state->crtc_h = state->crtc_h;
++      ret = vc4_plane_margins_adj(state);
++      if (ret)
++              return ret;
++
+       vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0],
+                                                      vc4_state->crtc_w);
+       vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0],
diff --git a/target/linux/brcm2708/patches-4.19/950-0624-drm-connector-Allow-creation-of-margin-props-alone.patch b/target/linux/brcm2708/patches-4.19/950-0624-drm-connector-Allow-creation-of-margin-props-alone.patch
deleted file mode 100644 (file)
index 1b242f4..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-From 4f2277b18d6bbb6fac50b751c4e513619849b23c Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Thu, 6 Dec 2018 15:24:37 +0100
-Subject: [PATCH] drm/connector: Allow creation of margin props alone
-
-Commit 6c4f52dca36f5e3e2354c30591d38e92f4657ed9 upstream.
-
-TV margins properties can only be added as part of the SDTV TV
-connector properties creation, but we might need those props for HDMI
-TVs too, so let's move the margins props creation in a separate
-function and expose it to drivers.
-
-We also add an helper to attach margins props to a connector.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-4-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/drm_connector.c | 83 ++++++++++++++++++++++++++-------
- include/drm/drm_connector.h     |  2 +
- 2 files changed, 67 insertions(+), 18 deletions(-)
-
---- a/drivers/gpu/drm/drm_connector.c
-+++ b/drivers/gpu/drm/drm_connector.c
-@@ -1110,6 +1110,70 @@ void drm_hdmi_avi_infoframe_content_type
- EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
- /**
-+ * drm_mode_attach_tv_margin_properties - attach TV connector margin properties
-+ * @connector: DRM connector
-+ *
-+ * Called by a driver when it needs to attach TV margin props to a connector.
-+ * Typically used on SDTV and HDMI connectors.
-+ */
-+void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)
-+{
-+      struct drm_device *dev = connector->dev;
-+
-+      drm_object_attach_property(&connector->base,
-+                                 dev->mode_config.tv_left_margin_property,
-+                                 0);
-+      drm_object_attach_property(&connector->base,
-+                                 dev->mode_config.tv_right_margin_property,
-+                                 0);
-+      drm_object_attach_property(&connector->base,
-+                                 dev->mode_config.tv_top_margin_property,
-+                                 0);
-+      drm_object_attach_property(&connector->base,
-+                                 dev->mode_config.tv_bottom_margin_property,
-+                                 0);
-+}
-+EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
-+
-+/**
-+ * drm_mode_create_tv_margin_properties - create TV connector margin properties
-+ * @dev: DRM device
-+ *
-+ * Called by a driver's HDMI connector initialization routine, this function
-+ * creates the TV margin properties for a given device. No need to call this
-+ * function for an SDTV connector, it's already called from
-+ * drm_mode_create_tv_properties().
-+ */
-+int drm_mode_create_tv_margin_properties(struct drm_device *dev)
-+{
-+      if (dev->mode_config.tv_left_margin_property)
-+              return 0;
-+
-+      dev->mode_config.tv_left_margin_property =
-+              drm_property_create_range(dev, 0, "left margin", 0, 100);
-+      if (!dev->mode_config.tv_left_margin_property)
-+              return -ENOMEM;
-+
-+      dev->mode_config.tv_right_margin_property =
-+              drm_property_create_range(dev, 0, "right margin", 0, 100);
-+      if (!dev->mode_config.tv_right_margin_property)
-+              return -ENOMEM;
-+
-+      dev->mode_config.tv_top_margin_property =
-+              drm_property_create_range(dev, 0, "top margin", 0, 100);
-+      if (!dev->mode_config.tv_top_margin_property)
-+              return -ENOMEM;
-+
-+      dev->mode_config.tv_bottom_margin_property =
-+              drm_property_create_range(dev, 0, "bottom margin", 0, 100);
-+      if (!dev->mode_config.tv_bottom_margin_property)
-+              return -ENOMEM;
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
-+
-+/**
-  * drm_mode_create_tv_properties - create TV specific connector properties
-  * @dev: DRM device
-  * @num_modes: number of different TV formats (modes) supported
-@@ -1155,24 +1219,7 @@ int drm_mode_create_tv_properties(struct
-       /*
-        * Other, TV specific properties: margins & TV modes.
-        */
--      dev->mode_config.tv_left_margin_property =
--              drm_property_create_range(dev, 0, "left margin", 0, 100);
--      if (!dev->mode_config.tv_left_margin_property)
--              goto nomem;
--
--      dev->mode_config.tv_right_margin_property =
--              drm_property_create_range(dev, 0, "right margin", 0, 100);
--      if (!dev->mode_config.tv_right_margin_property)
--              goto nomem;
--
--      dev->mode_config.tv_top_margin_property =
--              drm_property_create_range(dev, 0, "top margin", 0, 100);
--      if (!dev->mode_config.tv_top_margin_property)
--              goto nomem;
--
--      dev->mode_config.tv_bottom_margin_property =
--              drm_property_create_range(dev, 0, "bottom margin", 0, 100);
--      if (!dev->mode_config.tv_bottom_margin_property)
-+      if (drm_mode_create_tv_margin_properties(dev))
-               goto nomem;
-       dev->mode_config.tv_mode_property =
---- a/include/drm/drm_connector.h
-+++ b/include/drm/drm_connector.h
-@@ -1175,9 +1175,11 @@ const char *drm_get_tv_select_name(int v
- const char *drm_get_content_protection_name(int val);
- int drm_mode_create_dvi_i_properties(struct drm_device *dev);
-+int drm_mode_create_tv_margin_properties(struct drm_device *dev);
- int drm_mode_create_tv_properties(struct drm_device *dev,
-                                 unsigned int num_modes,
-                                 const char * const modes[]);
-+void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
- int drm_mode_create_scaling_mode_property(struct drm_device *dev);
- int drm_connector_attach_content_type_property(struct drm_connector *dev);
- int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
diff --git a/target/linux/brcm2708/patches-4.19/950-0624-drm-vc4-Attach-margin-props-to-the-HDMI-connector.patch b/target/linux/brcm2708/patches-4.19/950-0624-drm-vc4-Attach-margin-props-to-the-HDMI-connector.patch
new file mode 100644 (file)
index 0000000..906caba
--- /dev/null
@@ -0,0 +1,71 @@
+From efd1df5cd92e4436f863730f666117494613693b Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:39 +0100
+Subject: [PATCH] drm/vc4: Attach margin props to the HDMI connector
+
+Commit db999538fdb0679629d90652f8a1437df1e85a7d upstream.
+
+Now that the plane code takes the margins setup into account, we can
+safely attach margin props to the HDMI connector.
+
+We also take care of filling AVI infoframes correctly to expose the
+top/botton/left/right bar.
+
+Note that those margin props match pretty well the
+overscan_{left,right,top,bottom} properties defined in config.txt and
+parsed by the VC4 firmware.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-6-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -310,6 +310,7 @@ static struct drm_connector *vc4_hdmi_co
+ {
+       struct drm_connector *connector;
+       struct vc4_hdmi_connector *hdmi_connector;
++      int ret;
+       hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
+                                     GFP_KERNEL);
+@@ -323,6 +324,13 @@ static struct drm_connector *vc4_hdmi_co
+                          DRM_MODE_CONNECTOR_HDMIA);
+       drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
++      /* Create and attach TV margin props to this connector. */
++      ret = drm_mode_create_tv_margin_properties(dev);
++      if (ret)
++              return ERR_PTR(ret);
++
++      drm_connector_attach_tv_margin_properties(connector);
++
+       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+                            DRM_CONNECTOR_POLL_DISCONNECT);
+@@ -408,6 +416,9 @@ static void vc4_hdmi_write_infoframe(str
+ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
+ {
+       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
++      struct vc4_dev *vc4 = encoder->dev->dev_private;
++      struct vc4_hdmi *hdmi = vc4->hdmi;
++      struct drm_connector_state *cstate = hdmi->connector->state;
+       struct drm_crtc *crtc = encoder->crtc;
+       const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+       union hdmi_infoframe frame;
+@@ -426,6 +437,11 @@ static void vc4_hdmi_set_avi_infoframe(s
+                                          vc4_encoder->rgb_range_selectable,
+                                          false);
++      frame.avi.right_bar = cstate->tv.margins.right;
++      frame.avi.left_bar = cstate->tv.margins.left;
++      frame.avi.top_bar = cstate->tv.margins.top;
++      frame.avi.bottom_bar = cstate->tv.margins.bottom;
++
+       vc4_hdmi_write_infoframe(encoder, &frame);
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0625-drm-vc4-Add-support-for-margins-to-fkms.patch b/target/linux/brcm2708/patches-4.19/950-0625-drm-vc4-Add-support-for-margins-to-fkms.patch
new file mode 100644 (file)
index 0000000..12f1606
--- /dev/null
@@ -0,0 +1,328 @@
+From a4e8051901a5d858a69732a3f9734835afc00af5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 19 Jul 2019 15:35:13 +0100
+Subject: [PATCH] drm/vc4: Add support for margins to fkms
+
+Allows for overscan to be configured under FKMS.
+NB This is rescaling the planes, not reducing the size of the
+display mode.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 241 +++++++++++++++++++------
+ 1 file changed, 190 insertions(+), 51 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -256,6 +256,23 @@ static inline struct vc4_crtc *to_vc4_cr
+       return container_of(crtc, struct vc4_crtc, base);
+ }
++struct vc4_crtc_state {
++      struct drm_crtc_state base;
++
++      struct {
++              unsigned int left;
++              unsigned int right;
++              unsigned int top;
++              unsigned int bottom;
++      } margins;
++};
++
++static inline struct vc4_crtc_state *
++to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
++{
++      return (struct vc4_crtc_state *)crtc_state;
++}
++
+ struct vc4_fkms_encoder {
+       struct drm_encoder base;
+       bool hdmi_monitor;
+@@ -365,17 +382,127 @@ static int vc4_plane_set_blank(struct dr
+       return ret;
+ }
++static void vc4_fkms_crtc_get_margins(struct drm_crtc_state *state,
++                                    unsigned int *left, unsigned int *right,
++                                    unsigned int *top, unsigned int *bottom)
++{
++      struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
++      struct drm_connector_state *conn_state;
++      struct drm_connector *conn;
++      int i;
++
++      *left = vc4_state->margins.left;
++      *right = vc4_state->margins.right;
++      *top = vc4_state->margins.top;
++      *bottom = vc4_state->margins.bottom;
++
++      /* We have to interate over all new connector states because
++       * vc4_fkms_crtc_get_margins() might be called before
++       * vc4_fkms_crtc_atomic_check() which means margins info in
++       * vc4_crtc_state might be outdated.
++       */
++      for_each_new_connector_in_state(state->state, conn, conn_state, i) {
++              if (conn_state->crtc != state->crtc)
++                      continue;
++
++              *left = conn_state->tv.margins.left;
++              *right = conn_state->tv.margins.right;
++              *top = conn_state->tv.margins.top;
++              *bottom = conn_state->tv.margins.bottom;
++              break;
++      }
++}
++
++static int vc4_fkms_margins_adj(struct drm_plane_state *pstate,
++                              struct set_plane *plane)
++{
++      unsigned int left, right, top, bottom;
++      int adjhdisplay, adjvdisplay;
++      struct drm_crtc_state *crtc_state;
++
++      crtc_state = drm_atomic_get_new_crtc_state(pstate->state,
++                                                 pstate->crtc);
++
++      vc4_fkms_crtc_get_margins(crtc_state, &left, &right, &top, &bottom);
++
++      if (!left && !right && !top && !bottom)
++              return 0;
++
++      if (left + right >= crtc_state->mode.hdisplay ||
++          top + bottom >= crtc_state->mode.vdisplay)
++              return -EINVAL;
++
++      adjhdisplay = crtc_state->mode.hdisplay - (left + right);
++      plane->dst_x = DIV_ROUND_CLOSEST(plane->dst_x * adjhdisplay,
++                                       (int)crtc_state->mode.hdisplay);
++      plane->dst_x += left;
++      if (plane->dst_x > (int)(crtc_state->mode.hdisplay - left))
++              plane->dst_x = crtc_state->mode.hdisplay - left;
++
++      adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
++      plane->dst_y = DIV_ROUND_CLOSEST(plane->dst_y * adjvdisplay,
++                                       (int)crtc_state->mode.vdisplay);
++      plane->dst_y += top;
++      if (plane->dst_y > (int)(crtc_state->mode.vdisplay - top))
++              plane->dst_y = crtc_state->mode.vdisplay - top;
++
++      plane->dst_w = DIV_ROUND_CLOSEST(plane->dst_w * adjhdisplay,
++                                       crtc_state->mode.hdisplay);
++      plane->dst_h = DIV_ROUND_CLOSEST(plane->dst_h * adjvdisplay,
++                                       crtc_state->mode.vdisplay);
++
++      if (!plane->dst_w || !plane->dst_h)
++              return -EINVAL;
++
++      return 0;
++}
++
+ static void vc4_plane_atomic_update(struct drm_plane *plane,
+                                   struct drm_plane_state *old_state)
+ {
+       struct drm_plane_state *state = plane->state;
++
++      /*
++       * Do NOT set now, as we haven't checked if the crtc is active or not.
++       * Set from vc4_plane_set_blank instead.
++       *
++       * If the CRTC is on (or going to be on) and we're enabled,
++       * then unblank.  Otherwise, stay blank until CRTC enable.
++       */
++      if (state->crtc->state->active)
++              vc4_plane_set_blank(plane, false);
++}
++
++static void vc4_plane_atomic_disable(struct drm_plane *plane,
++                                   struct drm_plane_state *old_state)
++{
++      struct drm_plane_state *state = plane->state;
++      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
++
++      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
++                       plane->base.id, plane->name,
++                       state->crtc_w,
++                       state->crtc_h,
++                       vc4_plane->mb.plane.vc_image_type,
++                       state->crtc_x,
++                       state->crtc_y);
++      vc4_plane_set_blank(plane, true);
++}
++
++static bool plane_enabled(struct drm_plane_state *state)
++{
++      return state->fb && state->crtc;
++}
++
++static int vc4_plane_to_mb(struct drm_plane *plane,
++                         struct mailbox_set_plane *mb,
++                         struct drm_plane_state *state)
++{
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+       const struct drm_format_info *drm_fmt = fb->format;
+       const struct vc_image_format *vc_fmt =
+                                       vc4_get_vc_image_fmt(drm_fmt->format);
+-      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+-      struct mailbox_set_plane *mb = &vc4_plane->mb;
+       int num_planes = fb->format->num_planes;
+       struct drm_display_mode *mode = &state->crtc->mode;
+       unsigned int rotation = SUPPORTED_ROTATIONS;
+@@ -417,25 +544,7 @@ static void vc4_plane_atomic_update(stru
+               break;
+       }
+-      /* FIXME: If the dest rect goes off screen then clip the src rect so we
+-       * don't have off-screen pixels.
+-       */
+-      if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+-              /* There is no scaling on the cursor plane, therefore the calcs
+-               * to alter the source crop as the cursor goes off the screen
+-               * are simple.
+-               */
+-              if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
+-                      mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
+-                      mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
+-                                                                      << 16;
+-              }
+-              if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
+-                      mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
+-                      mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
+-                                                                      << 16;
+-              }
+-      }
++      vc4_fkms_margins_adj(state, &mb->plane);
+       if (num_planes > 1) {
+               /* Assume this must be YUV */
+@@ -525,38 +634,19 @@ static void vc4_plane_atomic_update(stru
+                        state->alpha,
+                        state->normalized_zpos);
+-      /*
+-       * Do NOT set now, as we haven't checked if the crtc is active or not.
+-       * Set from vc4_plane_set_blank instead.
+-       *
+-       * If the CRTC is on (or going to be on) and we're enabled,
+-       * then unblank.  Otherwise, stay blank until CRTC enable.
+-       */
+-      if (state->crtc->state->active)
+-              vc4_plane_set_blank(plane, false);
++      return 0;
+ }
+-static void vc4_plane_atomic_disable(struct drm_plane *plane,
+-                                   struct drm_plane_state *old_state)
++static int vc4_plane_atomic_check(struct drm_plane *plane,
++                                struct drm_plane_state *state)
+ {
+-      //struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+-      struct drm_plane_state *state = plane->state;
+       struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+-      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
+-                       plane->base.id, plane->name,
+-                       state->crtc_w,
+-                       state->crtc_h,
+-                       vc4_plane->mb.plane.vc_image_type,
+-                       state->crtc_x,
+-                       state->crtc_y);
+-      vc4_plane_set_blank(plane, true);
+-}
++      if (!plane_enabled(state))
++              return 0;
++
++      return vc4_plane_to_mb(plane, &vc4_plane->mb, state);
+-static int vc4_plane_atomic_check(struct drm_plane *plane,
+-                                struct drm_plane_state *state)
+-{
+-      return 0;
+ }
+ static void vc4_plane_destroy(struct drm_plane *plane)
+@@ -878,8 +968,23 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+                                struct drm_crtc_state *state)
+ {
+-      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
+-                    crtc->base.id);
++      struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
++      struct drm_connector *conn;
++      struct drm_connector_state *conn_state;
++      int i;
++
++      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n", crtc->base.id);
++
++      for_each_new_connector_in_state(state->state, conn, conn_state, i) {
++              if (conn_state->crtc != crtc)
++                      continue;
++
++              vc4_state->margins.left = conn_state->tv.margins.left;
++              vc4_state->margins.right = conn_state->tv.margins.right;
++              vc4_state->margins.top = conn_state->tv.margins.top;
++              vc4_state->margins.bottom = conn_state->tv.margins.bottom;
++              break;
++      }
+       return 0;
+ }
+@@ -980,6 +1085,33 @@ static int vc4_page_flip(struct drm_crtc
+       return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx);
+ }
++static struct drm_crtc_state *
++vc4_crtc_duplicate_state(struct drm_crtc *crtc)
++{
++      struct vc4_crtc_state *vc4_state, *old_vc4_state;
++
++      vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL);
++      if (!vc4_state)
++              return NULL;
++
++      old_vc4_state = to_vc4_crtc_state(crtc->state);
++      vc4_state->margins = old_vc4_state->margins;
++
++      __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
++      return &vc4_state->base;
++}
++
++static void
++vc4_crtc_reset(struct drm_crtc *crtc)
++{
++      if (crtc->state)
++              __drm_atomic_helper_crtc_destroy_state(crtc->state);
++
++      crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
++      if (crtc->state)
++              crtc->state->crtc = crtc;
++}
++
+ static int vc4_fkms_enable_vblank(struct drm_crtc *crtc)
+ {
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+@@ -1007,8 +1139,8 @@ static const struct drm_crtc_funcs vc4_c
+       .set_property = NULL,
+       .cursor_set = NULL, /* handled by drm_mode_cursor_universal */
+       .cursor_move = NULL, /* handled by drm_mode_cursor_universal */
+-      .reset = drm_atomic_helper_crtc_reset,
+-      .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
++      .reset = vc4_crtc_reset,
++      .atomic_duplicate_state = vc4_crtc_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank = vc4_fkms_enable_vblank,
+       .disable_vblank = vc4_fkms_disable_vblank,
+@@ -1267,6 +1399,13 @@ vc4_fkms_connector_init(struct drm_devic
+               connector->interlace_allowed = 0;
+       }
++      /* Create and attach TV margin props to this connector. */
++      ret = drm_mode_create_tv_margin_properties(dev);
++      if (ret)
++              return ERR_PTR(ret);
++
++      drm_connector_attach_tv_margin_properties(connector);
++
+       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+                            DRM_CONNECTOR_POLL_DISCONNECT);
diff --git a/target/linux/brcm2708/patches-4.19/950-0625-drm-vc4-Take-margin-setup-into-account-when-updating.patch b/target/linux/brcm2708/patches-4.19/950-0625-drm-vc4-Take-margin-setup-into-account-when-updating.patch
deleted file mode 100644 (file)
index a50be7a..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-From 0d592a7685e41d0bb1816a4fedb11d3570474417 Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Thu, 6 Dec 2018 15:24:38 +0100
-Subject: [PATCH] drm/vc4: Take margin setup into account when updating
- planes
-
-Commit 666e73587f90f42d90385c1bea1009a650bf73f4 upstream.
-
-Applyin margins is just a matter of scaling all planes appropriately
-and adjusting the CRTC X/Y offset to account for the
-left/right/top/bottom borders.
-
-Create a vc4_plane_margins_adj() function doing that and call it from
-vc4_plane_setup_clipping_and_scaling() so that we are ready to attach
-margins properties to the HDMI connector.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-5-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_crtc.c  | 43 +++++++++++++++++++++++++++
- drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++
- drivers/gpu/drm/vc4/vc4_plane.c | 51 +++++++++++++++++++++++++++++++++
- 3 files changed, 97 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_crtc.c
-+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
-@@ -48,6 +48,13 @@ struct vc4_crtc_state {
-       struct drm_mm_node mm;
-       bool feed_txp;
-       bool txp_armed;
-+
-+      struct {
-+              unsigned int left;
-+              unsigned int right;
-+              unsigned int top;
-+              unsigned int bottom;
-+      } margins;
- };
- static inline struct vc4_crtc_state *
-@@ -623,6 +630,37 @@ static enum drm_mode_status vc4_crtc_mod
-       return MODE_OK;
- }
-+void vc4_crtc_get_margins(struct drm_crtc_state *state,
-+                        unsigned int *left, unsigned int *right,
-+                        unsigned int *top, unsigned int *bottom)
-+{
-+      struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
-+      struct drm_connector_state *conn_state;
-+      struct drm_connector *conn;
-+      int i;
-+
-+      *left = vc4_state->margins.left;
-+      *right = vc4_state->margins.right;
-+      *top = vc4_state->margins.top;
-+      *bottom = vc4_state->margins.bottom;
-+
-+      /* We have to interate over all new connector states because
-+       * vc4_crtc_get_margins() might be called before
-+       * vc4_crtc_atomic_check() which means margins info in vc4_crtc_state
-+       * might be outdated.
-+       */
-+      for_each_new_connector_in_state(state->state, conn, conn_state, i) {
-+              if (conn_state->crtc != state->crtc)
-+                      continue;
-+
-+              *left = conn_state->tv.margins.left;
-+              *right = conn_state->tv.margins.right;
-+              *top = conn_state->tv.margins.top;
-+              *bottom = conn_state->tv.margins.bottom;
-+              break;
-+      }
-+}
-+
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
-                                struct drm_crtc_state *state)
- {
-@@ -670,6 +708,10 @@ static int vc4_crtc_atomic_check(struct
-                       vc4_state->feed_txp = false;
-               }
-+              vc4_state->margins.left = conn_state->tv.margins.left;
-+              vc4_state->margins.right = conn_state->tv.margins.right;
-+              vc4_state->margins.top = conn_state->tv.margins.top;
-+              vc4_state->margins.bottom = conn_state->tv.margins.bottom;
-               break;
-       }
-@@ -971,6 +1013,7 @@ static struct drm_crtc_state *vc4_crtc_d
-       old_vc4_state = to_vc4_crtc_state(crtc->state);
-       vc4_state->feed_txp = old_vc4_state->feed_txp;
-+      vc4_state->margins = old_vc4_state->margins;
-       __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
-       return &vc4_state->base;
---- a/drivers/gpu/drm/vc4/vc4_drv.h
-+++ b/drivers/gpu/drm/vc4/vc4_drv.h
-@@ -705,6 +705,9 @@ bool vc4_crtc_get_scanoutpos(struct drm_
-                            const struct drm_display_mode *mode);
- void vc4_crtc_handle_vblank(struct vc4_crtc *crtc);
- void vc4_crtc_txp_armed(struct drm_crtc_state *state);
-+void vc4_crtc_get_margins(struct drm_crtc_state *state,
-+                        unsigned int *right, unsigned int *left,
-+                        unsigned int *top, unsigned int *bottom);
- /* vc4_debugfs.c */
- int vc4_debugfs_init(struct drm_minor *minor);
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -258,6 +258,52 @@ static u32 vc4_get_scl_field(struct drm_
-       }
- }
-+static int vc4_plane_margins_adj(struct drm_plane_state *pstate)
-+{
-+      struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate);
-+      unsigned int left, right, top, bottom, adjhdisplay, adjvdisplay;
-+      struct drm_crtc_state *crtc_state;
-+
-+      crtc_state = drm_atomic_get_new_crtc_state(pstate->state,
-+                                                 pstate->crtc);
-+
-+      vc4_crtc_get_margins(crtc_state, &left, &right, &top, &bottom);
-+      if (!left && !right && !top && !bottom)
-+              return 0;
-+
-+      if (left + right >= crtc_state->mode.hdisplay ||
-+          top + bottom >= crtc_state->mode.vdisplay)
-+              return -EINVAL;
-+
-+      adjhdisplay = crtc_state->mode.hdisplay - (left + right);
-+      vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x *
-+                                             adjhdisplay,
-+                                             crtc_state->mode.hdisplay);
-+      vc4_pstate->crtc_x += left;
-+      if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left)
-+              vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left;
-+
-+      adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
-+      vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y *
-+                                             adjvdisplay,
-+                                             crtc_state->mode.vdisplay);
-+      vc4_pstate->crtc_y += top;
-+      if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top)
-+              vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top;
-+
-+      vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w *
-+                                             adjhdisplay,
-+                                             crtc_state->mode.hdisplay);
-+      vc4_pstate->crtc_h = DIV_ROUND_CLOSEST(vc4_pstate->crtc_h *
-+                                             adjvdisplay,
-+                                             crtc_state->mode.vdisplay);
-+
-+      if (!vc4_pstate->crtc_w || !vc4_pstate->crtc_h)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+
- static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
- {
-       struct drm_plane *plane = state->plane;
-@@ -269,6 +315,7 @@ static int vc4_plane_setup_clipping_and_
-       int num_planes = fb->format->num_planes;
-       u32 h_subsample = 1;
-       u32 v_subsample = 1;
-+      int ret;
-       int i;
-       for (i = 0; i < num_planes; i++)
-@@ -292,6 +339,10 @@ static int vc4_plane_setup_clipping_and_
-       vc4_state->crtc_w = state->crtc_w;
-       vc4_state->crtc_h = state->crtc_h;
-+      ret = vc4_plane_margins_adj(state);
-+      if (ret)
-+              return ret;
-+
-       vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0],
-                                                      vc4_state->crtc_w);
-       vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0],
diff --git a/target/linux/brcm2708/patches-4.19/950-0626-drm-vc4-Attach-margin-props-to-the-HDMI-connector.patch b/target/linux/brcm2708/patches-4.19/950-0626-drm-vc4-Attach-margin-props-to-the-HDMI-connector.patch
deleted file mode 100644 (file)
index 906caba..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-From efd1df5cd92e4436f863730f666117494613693b Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Thu, 6 Dec 2018 15:24:39 +0100
-Subject: [PATCH] drm/vc4: Attach margin props to the HDMI connector
-
-Commit db999538fdb0679629d90652f8a1437df1e85a7d upstream.
-
-Now that the plane code takes the margins setup into account, we can
-safely attach margin props to the HDMI connector.
-
-We also take care of filling AVI infoframes correctly to expose the
-top/botton/left/right bar.
-
-Note that those margin props match pretty well the
-overscan_{left,right,top,bottom} properties defined in config.txt and
-parsed by the VC4 firmware.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-6-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_hdmi.c | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_hdmi.c
-+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -310,6 +310,7 @@ static struct drm_connector *vc4_hdmi_co
- {
-       struct drm_connector *connector;
-       struct vc4_hdmi_connector *hdmi_connector;
-+      int ret;
-       hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
-                                     GFP_KERNEL);
-@@ -323,6 +324,13 @@ static struct drm_connector *vc4_hdmi_co
-                          DRM_MODE_CONNECTOR_HDMIA);
-       drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
-+      /* Create and attach TV margin props to this connector. */
-+      ret = drm_mode_create_tv_margin_properties(dev);
-+      if (ret)
-+              return ERR_PTR(ret);
-+
-+      drm_connector_attach_tv_margin_properties(connector);
-+
-       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
-                            DRM_CONNECTOR_POLL_DISCONNECT);
-@@ -408,6 +416,9 @@ static void vc4_hdmi_write_infoframe(str
- static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
- {
-       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-+      struct vc4_dev *vc4 = encoder->dev->dev_private;
-+      struct vc4_hdmi *hdmi = vc4->hdmi;
-+      struct drm_connector_state *cstate = hdmi->connector->state;
-       struct drm_crtc *crtc = encoder->crtc;
-       const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-       union hdmi_infoframe frame;
-@@ -426,6 +437,11 @@ static void vc4_hdmi_set_avi_infoframe(s
-                                          vc4_encoder->rgb_range_selectable,
-                                          false);
-+      frame.avi.right_bar = cstate->tv.margins.right;
-+      frame.avi.left_bar = cstate->tv.margins.left;
-+      frame.avi.top_bar = cstate->tv.margins.top;
-+      frame.avi.bottom_bar = cstate->tv.margins.bottom;
-+
-       vc4_hdmi_write_infoframe(encoder, &frame);
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0626-drm-vc4-Ensure-zpos-is-always-initialised.patch b/target/linux/brcm2708/patches-4.19/950-0626-drm-vc4-Ensure-zpos-is-always-initialised.patch
new file mode 100644 (file)
index 0000000..bd13a32
--- /dev/null
@@ -0,0 +1,26 @@
+From cf80e05ebb55c121c1567ac42b9e1a885fc346a3 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 19 Jul 2019 17:49:00 +0100
+Subject: [PATCH] drm/vc4: Ensure zpos is always initialised
+
+The compiler is warning that default_zpos can be used
+uninitialised as there is no default case to catch all plane
+types.
+No other plane types should ever be presented to vc4_fkms_plane_init,
+but add a default case regardless.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -773,6 +773,7 @@ static struct drm_plane *vc4_fkms_plane_
+        * other layers as requested by KMS.
+        */
+       switch (type) {
++      default:
+       case DRM_PLANE_TYPE_PRIMARY:
+               default_zpos = 0;
+               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0627-drm-vc4-Add-support-for-margins-to-fkms.patch b/target/linux/brcm2708/patches-4.19/950-0627-drm-vc4-Add-support-for-margins-to-fkms.patch
deleted file mode 100644 (file)
index 12f1606..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-From a4e8051901a5d858a69732a3f9734835afc00af5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 19 Jul 2019 15:35:13 +0100
-Subject: [PATCH] drm/vc4: Add support for margins to fkms
-
-Allows for overscan to be configured under FKMS.
-NB This is rescaling the planes, not reducing the size of the
-display mode.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 241 +++++++++++++++++++------
- 1 file changed, 190 insertions(+), 51 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -256,6 +256,23 @@ static inline struct vc4_crtc *to_vc4_cr
-       return container_of(crtc, struct vc4_crtc, base);
- }
-+struct vc4_crtc_state {
-+      struct drm_crtc_state base;
-+
-+      struct {
-+              unsigned int left;
-+              unsigned int right;
-+              unsigned int top;
-+              unsigned int bottom;
-+      } margins;
-+};
-+
-+static inline struct vc4_crtc_state *
-+to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
-+{
-+      return (struct vc4_crtc_state *)crtc_state;
-+}
-+
- struct vc4_fkms_encoder {
-       struct drm_encoder base;
-       bool hdmi_monitor;
-@@ -365,17 +382,127 @@ static int vc4_plane_set_blank(struct dr
-       return ret;
- }
-+static void vc4_fkms_crtc_get_margins(struct drm_crtc_state *state,
-+                                    unsigned int *left, unsigned int *right,
-+                                    unsigned int *top, unsigned int *bottom)
-+{
-+      struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
-+      struct drm_connector_state *conn_state;
-+      struct drm_connector *conn;
-+      int i;
-+
-+      *left = vc4_state->margins.left;
-+      *right = vc4_state->margins.right;
-+      *top = vc4_state->margins.top;
-+      *bottom = vc4_state->margins.bottom;
-+
-+      /* We have to interate over all new connector states because
-+       * vc4_fkms_crtc_get_margins() might be called before
-+       * vc4_fkms_crtc_atomic_check() which means margins info in
-+       * vc4_crtc_state might be outdated.
-+       */
-+      for_each_new_connector_in_state(state->state, conn, conn_state, i) {
-+              if (conn_state->crtc != state->crtc)
-+                      continue;
-+
-+              *left = conn_state->tv.margins.left;
-+              *right = conn_state->tv.margins.right;
-+              *top = conn_state->tv.margins.top;
-+              *bottom = conn_state->tv.margins.bottom;
-+              break;
-+      }
-+}
-+
-+static int vc4_fkms_margins_adj(struct drm_plane_state *pstate,
-+                              struct set_plane *plane)
-+{
-+      unsigned int left, right, top, bottom;
-+      int adjhdisplay, adjvdisplay;
-+      struct drm_crtc_state *crtc_state;
-+
-+      crtc_state = drm_atomic_get_new_crtc_state(pstate->state,
-+                                                 pstate->crtc);
-+
-+      vc4_fkms_crtc_get_margins(crtc_state, &left, &right, &top, &bottom);
-+
-+      if (!left && !right && !top && !bottom)
-+              return 0;
-+
-+      if (left + right >= crtc_state->mode.hdisplay ||
-+          top + bottom >= crtc_state->mode.vdisplay)
-+              return -EINVAL;
-+
-+      adjhdisplay = crtc_state->mode.hdisplay - (left + right);
-+      plane->dst_x = DIV_ROUND_CLOSEST(plane->dst_x * adjhdisplay,
-+                                       (int)crtc_state->mode.hdisplay);
-+      plane->dst_x += left;
-+      if (plane->dst_x > (int)(crtc_state->mode.hdisplay - left))
-+              plane->dst_x = crtc_state->mode.hdisplay - left;
-+
-+      adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
-+      plane->dst_y = DIV_ROUND_CLOSEST(plane->dst_y * adjvdisplay,
-+                                       (int)crtc_state->mode.vdisplay);
-+      plane->dst_y += top;
-+      if (plane->dst_y > (int)(crtc_state->mode.vdisplay - top))
-+              plane->dst_y = crtc_state->mode.vdisplay - top;
-+
-+      plane->dst_w = DIV_ROUND_CLOSEST(plane->dst_w * adjhdisplay,
-+                                       crtc_state->mode.hdisplay);
-+      plane->dst_h = DIV_ROUND_CLOSEST(plane->dst_h * adjvdisplay,
-+                                       crtc_state->mode.vdisplay);
-+
-+      if (!plane->dst_w || !plane->dst_h)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+
- static void vc4_plane_atomic_update(struct drm_plane *plane,
-                                   struct drm_plane_state *old_state)
- {
-       struct drm_plane_state *state = plane->state;
-+
-+      /*
-+       * Do NOT set now, as we haven't checked if the crtc is active or not.
-+       * Set from vc4_plane_set_blank instead.
-+       *
-+       * If the CRTC is on (or going to be on) and we're enabled,
-+       * then unblank.  Otherwise, stay blank until CRTC enable.
-+       */
-+      if (state->crtc->state->active)
-+              vc4_plane_set_blank(plane, false);
-+}
-+
-+static void vc4_plane_atomic_disable(struct drm_plane *plane,
-+                                   struct drm_plane_state *old_state)
-+{
-+      struct drm_plane_state *state = plane->state;
-+      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-+
-+      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
-+                       plane->base.id, plane->name,
-+                       state->crtc_w,
-+                       state->crtc_h,
-+                       vc4_plane->mb.plane.vc_image_type,
-+                       state->crtc_x,
-+                       state->crtc_y);
-+      vc4_plane_set_blank(plane, true);
-+}
-+
-+static bool plane_enabled(struct drm_plane_state *state)
-+{
-+      return state->fb && state->crtc;
-+}
-+
-+static int vc4_plane_to_mb(struct drm_plane *plane,
-+                         struct mailbox_set_plane *mb,
-+                         struct drm_plane_state *state)
-+{
-       struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
-       const struct drm_format_info *drm_fmt = fb->format;
-       const struct vc_image_format *vc_fmt =
-                                       vc4_get_vc_image_fmt(drm_fmt->format);
--      struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
--      struct mailbox_set_plane *mb = &vc4_plane->mb;
-       int num_planes = fb->format->num_planes;
-       struct drm_display_mode *mode = &state->crtc->mode;
-       unsigned int rotation = SUPPORTED_ROTATIONS;
-@@ -417,25 +544,7 @@ static void vc4_plane_atomic_update(stru
-               break;
-       }
--      /* FIXME: If the dest rect goes off screen then clip the src rect so we
--       * don't have off-screen pixels.
--       */
--      if (plane->type == DRM_PLANE_TYPE_CURSOR) {
--              /* There is no scaling on the cursor plane, therefore the calcs
--               * to alter the source crop as the cursor goes off the screen
--               * are simple.
--               */
--              if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
--                      mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
--                      mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
--                                                                      << 16;
--              }
--              if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
--                      mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
--                      mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
--                                                                      << 16;
--              }
--      }
-+      vc4_fkms_margins_adj(state, &mb->plane);
-       if (num_planes > 1) {
-               /* Assume this must be YUV */
-@@ -525,38 +634,19 @@ static void vc4_plane_atomic_update(stru
-                        state->alpha,
-                        state->normalized_zpos);
--      /*
--       * Do NOT set now, as we haven't checked if the crtc is active or not.
--       * Set from vc4_plane_set_blank instead.
--       *
--       * If the CRTC is on (or going to be on) and we're enabled,
--       * then unblank.  Otherwise, stay blank until CRTC enable.
--       */
--      if (state->crtc->state->active)
--              vc4_plane_set_blank(plane, false);
-+      return 0;
- }
--static void vc4_plane_atomic_disable(struct drm_plane *plane,
--                                   struct drm_plane_state *old_state)
-+static int vc4_plane_atomic_check(struct drm_plane *plane,
-+                                struct drm_plane_state *state)
- {
--      //struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
--      struct drm_plane_state *state = plane->state;
-       struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
--      DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
--                       plane->base.id, plane->name,
--                       state->crtc_w,
--                       state->crtc_h,
--                       vc4_plane->mb.plane.vc_image_type,
--                       state->crtc_x,
--                       state->crtc_y);
--      vc4_plane_set_blank(plane, true);
--}
-+      if (!plane_enabled(state))
-+              return 0;
-+
-+      return vc4_plane_to_mb(plane, &vc4_plane->mb, state);
--static int vc4_plane_atomic_check(struct drm_plane *plane,
--                                struct drm_plane_state *state)
--{
--      return 0;
- }
- static void vc4_plane_destroy(struct drm_plane *plane)
-@@ -878,8 +968,23 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
-                                struct drm_crtc_state *state)
- {
--      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
--                    crtc->base.id);
-+      struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
-+      struct drm_connector *conn;
-+      struct drm_connector_state *conn_state;
-+      int i;
-+
-+      DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n", crtc->base.id);
-+
-+      for_each_new_connector_in_state(state->state, conn, conn_state, i) {
-+              if (conn_state->crtc != crtc)
-+                      continue;
-+
-+              vc4_state->margins.left = conn_state->tv.margins.left;
-+              vc4_state->margins.right = conn_state->tv.margins.right;
-+              vc4_state->margins.top = conn_state->tv.margins.top;
-+              vc4_state->margins.bottom = conn_state->tv.margins.bottom;
-+              break;
-+      }
-       return 0;
- }
-@@ -980,6 +1085,33 @@ static int vc4_page_flip(struct drm_crtc
-       return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx);
- }
-+static struct drm_crtc_state *
-+vc4_crtc_duplicate_state(struct drm_crtc *crtc)
-+{
-+      struct vc4_crtc_state *vc4_state, *old_vc4_state;
-+
-+      vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL);
-+      if (!vc4_state)
-+              return NULL;
-+
-+      old_vc4_state = to_vc4_crtc_state(crtc->state);
-+      vc4_state->margins = old_vc4_state->margins;
-+
-+      __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
-+      return &vc4_state->base;
-+}
-+
-+static void
-+vc4_crtc_reset(struct drm_crtc *crtc)
-+{
-+      if (crtc->state)
-+              __drm_atomic_helper_crtc_destroy_state(crtc->state);
-+
-+      crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
-+      if (crtc->state)
-+              crtc->state->crtc = crtc;
-+}
-+
- static int vc4_fkms_enable_vblank(struct drm_crtc *crtc)
- {
-       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-@@ -1007,8 +1139,8 @@ static const struct drm_crtc_funcs vc4_c
-       .set_property = NULL,
-       .cursor_set = NULL, /* handled by drm_mode_cursor_universal */
-       .cursor_move = NULL, /* handled by drm_mode_cursor_universal */
--      .reset = drm_atomic_helper_crtc_reset,
--      .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
-+      .reset = vc4_crtc_reset,
-+      .atomic_duplicate_state = vc4_crtc_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
-       .enable_vblank = vc4_fkms_enable_vblank,
-       .disable_vblank = vc4_fkms_disable_vblank,
-@@ -1267,6 +1399,13 @@ vc4_fkms_connector_init(struct drm_devic
-               connector->interlace_allowed = 0;
-       }
-+      /* Create and attach TV margin props to this connector. */
-+      ret = drm_mode_create_tv_margin_properties(dev);
-+      if (ret)
-+              return ERR_PTR(ret);
-+
-+      drm_connector_attach_tv_margin_properties(connector);
-+
-       connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
-                            DRM_CONNECTOR_POLL_DISCONNECT);
diff --git a/target/linux/brcm2708/patches-4.19/950-0627-dts-bcm2838-add-missing-properties-for-pmu-and-gic-n.patch b/target/linux/brcm2708/patches-4.19/950-0627-dts-bcm2838-add-missing-properties-for-pmu-and-gic-n.patch
new file mode 100644 (file)
index 0000000..553c16c
--- /dev/null
@@ -0,0 +1,45 @@
+From a78d4d81c585a5de61e7fc7d574e6e3f769c18a6 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 24 Jul 2019 14:36:53 +0100
+Subject: [PATCH] dts: bcm2838: add missing properties for pmu and gic
+ nodes
+
+The GIC has a virtual interface maintenance interrupt and the PMU
+interrupts need affinity mappings as they are wired to generic SPIs.
+
+Also, delete incorrect PMU compatible string.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -35,6 +35,8 @@
+                               <0x40042000 0x2000>,
+                               <0x40044000 0x2000>,
+                               <0x40046000 0x2000>;
++                      interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) |
++                                               IRQ_TYPE_LEVEL_HIGH)>;
+               };
+               thermal: thermal@7d5d2200 {
+@@ -222,15 +224,12 @@
+       };
+       arm-pmu {
+-              /*
+-               * N.B. the A72 PMU support only exists in arch/arm64, hence
+-               * the fallback to the A53 version.
+-               */
+-              compatible = "arm,cortex-a72-pmu", "arm,cortex-a53-pmu";
++              compatible = "arm,cortex-a72-pmu";
+               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+                       <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+                       <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+                       <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
++              interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+       };
+       timer {
diff --git a/target/linux/brcm2708/patches-4.19/950-0628-adds-the-Hifiberry-DAC-ADC-PRO-version.patch b/target/linux/brcm2708/patches-4.19/950-0628-adds-the-Hifiberry-DAC-ADC-PRO-version.patch
new file mode 100644 (file)
index 0000000..427053d
--- /dev/null
@@ -0,0 +1,701 @@
+From bab5f8832c6b2859caea1cb5af1ffcb6276c2f74 Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joscha@schambacher.com>
+Date: Tue, 23 Jul 2019 16:57:35 +0200
+Subject: [PATCH] adds the Hifiberry DAC+ADC PRO version
+
+This adds the driver for the DAC+ADC PRO version of the Hifiberry soundcard with software controlled PCM1863 ADC
+Signed-off-by: Joerg Schambacher joerg@i2audio.com
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  21 +
+ .../hifiberry-dacplusadcpro-overlay.dts       |  64 +++
+ sound/soc/bcm/Kconfig                         |   8 +
+ sound/soc/bcm/Makefile                        |   2 +
+ sound/soc/bcm/hifiberry_dacplusadcpro.c       | 538 ++++++++++++++++++
+ 9 files changed, 637 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
+ create mode 100644 sound/soc/bcm/hifiberry_dacplusadcpro.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -53,6 +53,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       hifiberry-dac.dtbo \
+       hifiberry-dacplus.dtbo \
+       hifiberry-dacplusadc.dtbo \
++      hifiberry-dacplusadcpro.dtbo \
+       hifiberry-digi.dtbo \
+       hifiberry-digi-pro.dtbo \
+       hy28a.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -883,6 +883,27 @@ Params: 24db_digital_gain       Allow ga
+                                 master for bit clock and frame clock.
++Name:   hifiberry-dacplusadcpro
++Info:   Configures the HifiBerry DAC+ADC PRO audio card
++Load:   dtoverlay=hifiberry-dacplusadcpro,<param>=<val>
++Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
++                                Digital volume control. Enable with
++                                "dtoverlay=hifiberry-dacplusadcpro,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+ADC Pro into slave mode, using Pi as
++                                master for bit clock and frame clock.
++
++
+ Name:   hifiberry-digi
+ Info:   Configures the HifiBerry Digi and Digi+ audio card
+ Load:   dtoverlay=hifiberry-digi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
+@@ -0,0 +1,64 @@
++// Definitions for HiFiBerry DAC+ADC PRO
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2708";
++
++      fragment@0 {
++              target-path = "/clocks";
++              __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";
++
++                      hb_dac: pcm5122@4d {
++                              #sound-dai-cells = <0>;
++                              compatible = "ti,pcm5122";
++                              reg = <0x4d>;
++                              clocks = <&dacpro_osc>;
++                              status = "okay";
++                      };
++                      hb_adc: pcm186x@4a {
++                              #sound-dai-cells = <0>;
++                              compatible = "ti,pcm1863";
++                              reg = <0x4a>;
++                              clocks = <&dacpro_osc>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&sound>;
++              hifiberry_dacplusadcpro: __overlay__ {
++                      compatible = "hifiberry,hifiberry-dacplusadcpro";
++                      audio-codec = <&hb_dac &hb_adc>;
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++
++      __overrides__ {
++              24db_digital_gain =
++                      <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,24db_digital_gain?";
++              slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?";
++      };
++};
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -48,6 +48,14 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
+         help
+          Say Y or M if you want to add support for HifiBerry DAC+ADC.
++config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO
++        tristate "Support for HifiBerry DAC+ADC PRO"
++        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++        select SND_SOC_PCM512x_I2C
++      select SND_SOC_PCM186X_I2C
++        help
++         Say Y or M if you want to add support for HifiBerry DAC+ADC PRO.
++
+ config SND_BCM2708_SOC_HIFIBERRY_DIGI
+         tristate "Support for HifiBerry Digi"
+         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -14,6 +14,7 @@ snd-soc-googlevoicehat-codec-objs := goo
+ # BCM2708 Machine Support
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
++snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+@@ -38,6 +39,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
+ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD)  += snd-soc-googlevoicehat-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+--- /dev/null
++++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
+@@ -0,0 +1,538 @@
++/*
++ * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC PRO Version (SW control)
++ *
++ * Author:    Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
++ *            Copyright 2014-2015
++ *            based on code by Florian Meier <florian.meier@koalo.de>
++ *            ADC added by Joerg Schambacher <joerg@i2audio.com>
++ *            Copyright 2018-19
++ *
++ * 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/kernel.h>
++#include <linux/clk.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++#include <sound/tlv.h>
++
++#include "../codecs/pcm512x.h"
++#include "../codecs/pcm186x.h"
++
++#define HIFIBERRY_DACPRO_NOCLOCK 0
++#define HIFIBERRY_DACPRO_CLK44EN 1
++#define HIFIBERRY_DACPRO_CLK48EN 2
++
++struct pcm512x_priv {
++      struct regmap *regmap;
++      struct clk *sclk;
++};
++
++/* Clock rate of CLK44EN attached to GPIO6 pin */
++#define CLK_44EN_RATE 22579200UL
++/* Clock rate of CLK48EN attached to GPIO3 pin */
++#define CLK_48EN_RATE 24576000UL
++
++static bool slave;
++static bool snd_rpi_hifiberry_is_dacpro;
++static bool digital_gain_0db_limit = true;
++
++static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
++      0x00, 0x01, 0x02, 0x03, 0x10
++};
++
++static const char * const pcm186x_adcl_input_channel_sel_text[] = {
++      "No Select",
++      "VINL1[SE]",                                    /* Default for ADCL */
++      "VINL2[SE]",
++      "VINL2[SE] + VINL1[SE]",
++      "{VIN1P, VIN1M}[DIFF]"
++};
++
++static const char * const pcm186x_adcr_input_channel_sel_text[] = {
++      "No Select",
++      "VINR1[SE]",                                    /* Default for ADCR */
++      "VINR2[SE]",
++      "VINR2[SE] + VINR1[SE]",
++      "{VIN2P, VIN2M}[DIFF]"
++};
++
++static const struct soc_enum pcm186x_adc_input_channel_sel[] = {
++      SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_L, 0,
++                            PCM186X_ADC_INPUT_SEL_MASK,
++                            ARRAY_SIZE(pcm186x_adcl_input_channel_sel_text),
++                            pcm186x_adcl_input_channel_sel_text,
++                            pcm186x_adc_input_channel_sel_value),
++      SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_R, 0,
++                            PCM186X_ADC_INPUT_SEL_MASK,
++                            ARRAY_SIZE(pcm186x_adcr_input_channel_sel_text),
++                            pcm186x_adcr_input_channel_sel_text,
++                            pcm186x_adc_input_channel_sel_value),
++};
++
++static const unsigned int pcm186x_mic_bias_sel_value[] = {
++      0x00, 0x01, 0x11
++};
++
++static const char * const pcm186x_mic_bias_sel_text[] = {
++      "Mic Bias off",
++      "Mic Bias on",
++      "Mic Bias with Bypass Resistor"
++};
++
++static const struct soc_enum pcm186x_mic_bias_sel[] = {
++      SOC_VALUE_ENUM_SINGLE(PCM186X_MIC_BIAS_CTRL, 0,
++                            GENMASK(4, 0),
++                            ARRAY_SIZE(pcm186x_mic_bias_sel_text),
++                            pcm186x_mic_bias_sel_text,
++                            pcm186x_mic_bias_sel_value),
++};
++
++static const unsigned int pcm186x_gain_sel_value[] = {
++      0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
++      0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++      0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
++      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++      0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++      0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
++      0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
++      0x50
++};
++
++static const char * const pcm186x_gain_sel_text[] = {
++      "-12.0dB", "-11.5dB", "-11.0dB", "-10.5dB", "-10.0dB", "-9.5dB",
++      "-9.0dB", "-8.5dB", "-8.0dB", "-7.5dB", "-7.0dB", "-6.5dB",
++      "-6.0dB", "-5.5dB", "-5.0dB", "-4.5dB", "-4.0dB", "-3.5dB",
++      "-3.0dB", "-2.5dB", "-2.0dB", "-1.5dB", "-1.0dB", "-0.5dB",
++      "0.0dB", "0.5dB", "1.0dB", "1.5dB", "2.0dB", "2.5dB",
++      "3.0dB", "3.5dB", "4.0dB", "4.5dB", "5.0dB", "5.5dB",
++      "6.0dB", "6.5dB", "7.0dB", "7.5dB", "8.0dB", "8.5dB",
++      "9.0dB", "9.5dB", "10.0dB", "10.5dB", "11.0dB", "11.5dB",
++      "12.0dB", "12.5dB", "13.0dB", "13.5dB", "14.0dB", "14.5dB",
++      "15.0dB", "15.5dB", "16.0dB", "16.5dB", "17.0dB", "17.5dB",
++      "18.0dB", "18.5dB", "19.0dB", "19.5dB", "20.0dB", "20.5dB",
++      "21.0dB", "21.5dB", "22.0dB", "22.5dB", "23.0dB", "23.5dB",
++      "24.0dB", "24.5dB", "25.0dB", "25.5dB", "26.0dB", "26.5dB",
++      "27.0dB", "27.5dB", "28.0dB", "28.5dB", "29.0dB", "29.5dB",
++      "30.0dB", "30.5dB", "31.0dB", "31.5dB", "32.0dB", "32.5dB",
++      "33.0dB", "33.5dB", "34.0dB", "34.5dB", "35.0dB", "35.5dB",
++      "36.0dB", "36.5dB", "37.0dB", "37.5dB", "38.0dB", "38.5dB",
++      "39.0dB", "39.5dB", "40.0dB"};
++
++static const struct soc_enum pcm186x_gain_sel[] = {
++      SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_L, 0,
++                            0xff,
++                            ARRAY_SIZE(pcm186x_gain_sel_text),
++                            pcm186x_gain_sel_text,
++                            pcm186x_gain_sel_value),
++      SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_R, 0,
++                            0xff,
++                            ARRAY_SIZE(pcm186x_gain_sel_text),
++                            pcm186x_gain_sel_text,
++                            pcm186x_gain_sel_value),
++};
++
++static const struct snd_kcontrol_new pcm1863_snd_controls_card[] = {
++      SOC_ENUM("ADC Left Input", pcm186x_adc_input_channel_sel[0]),
++      SOC_ENUM("ADC Right Input", pcm186x_adc_input_channel_sel[1]),
++      SOC_ENUM("ADC Mic Bias", pcm186x_mic_bias_sel),
++      SOC_ENUM("PGA Gain Left", pcm186x_gain_sel[0]),
++      SOC_ENUM("PGA Gain Right", pcm186x_gain_sel[1]),
++};
++
++static int pcm1863_add_controls(struct snd_soc_component *component)
++{
++      snd_soc_add_component_controls(component,
++                      pcm1863_snd_controls_card,
++                      ARRAY_SIZE(pcm1863_snd_controls_card));
++      return 0;
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_select_clk(
++                                      struct snd_soc_component *component, int clk_id)
++{
++      switch (clk_id) {
++      case HIFIBERRY_DACPRO_NOCLOCK:
++              snd_soc_component_update_bits(component,
++                              PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
++              break;
++      case HIFIBERRY_DACPRO_CLK44EN:
++              snd_soc_component_update_bits(component,
++                              PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
++              break;
++      case HIFIBERRY_DACPRO_CLK48EN:
++              snd_soc_component_update_bits(component,
++                              PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
++              break;
++      }
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
++{
++      snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
++      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
++      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
++}
++
++static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk(struct snd_soc_component *component)
++{
++      unsigned int sck;
++
++      snd_soc_component_read(component, PCM512x_RATE_DET_4, &sck);
++      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;
++
++      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);
++
++      snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
++      isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++
++      snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
++      isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++
++      return (isClk44EN && isClk48En && !isNoClk);
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(int sample_rate)
++{
++      int type;
++
++      switch (sample_rate) {
++      case 11025:
++      case 22050:
++      case 44100:
++      case 88200:
++      case 176400:
++      case 352800:
++              type = HIFIBERRY_DACPRO_CLK44EN;
++              break;
++      default:
++              type = HIFIBERRY_DACPRO_CLK48EN;
++              break;
++      }
++      return type;
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_set_sclk(struct snd_soc_component *component,
++      int sample_rate)
++{
++      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++
++      if (!IS_ERR(pcm512x->sclk)) {
++              int ctype;
++
++              ctype = snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(sample_rate);
++              clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
++                      ? CLK_44EN_RATE : CLK_48EN_RATE);
++              snd_rpi_hifiberry_dacplusadcpro_select_clk(component, ctype);
++      }
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++      struct snd_soc_component *adc = rtd->codec_dais[1]->component;
++      struct snd_soc_dai_driver *adc_driver = rtd->codec_dais[1]->driver;
++      struct pcm512x_priv *priv;
++      int ret;
++
++      if (slave)
++              snd_rpi_hifiberry_is_dacpro = false;
++      else
++              snd_rpi_hifiberry_is_dacpro =
++                              snd_rpi_hifiberry_dacplusadcpro_is_pro_card(dac);
++
++      if (snd_rpi_hifiberry_is_dacpro) {
++              struct snd_soc_dai_link *dai = rtd->dai_link;
++
++              dai->name = "HiFiBerry DAC+ADC Pro";
++              dai->stream_name = "HiFiBerry DAC+ADC Pro HiFi";
++
++              // set DAC DAI configuration
++              ret = snd_soc_dai_set_fmt(rtd->codec_dais[0],
++                              SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++                      | SND_SOC_DAIFMT_CBM_CFM);
++              if (ret < 0)
++                      return ret;
++
++              // set ADC DAI configuration
++              ret = snd_soc_dai_set_fmt(rtd->codec_dais[1],
++                              SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++                      | SND_SOC_DAIFMT_CBS_CFS);
++              if (ret < 0)
++                      return ret;
++
++              // set CPU DAI configuration
++              ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
++                      SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
++              if (ret < 0)
++                      return ret;
++
++              snd_soc_component_update_bits(dac, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
++              snd_soc_component_update_bits(dac, PCM512x_MASTER_MODE, 0x03, 0x03);
++              snd_soc_component_update_bits(dac, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
++      } else {
++              priv = snd_soc_component_get_drvdata(dac);
++              priv->sclk = ERR_PTR(-ENOENT);
++      }
++
++      /* disable 24bit mode as long as I2S module does not have sign extension fixed */
++      adc_driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE;
++
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++      ret = pcm1863_add_controls(adc);
++      if (ret < 0)
++              dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
++              ret);
++
++      /* set GPIO2 to output, GPIO3 input */
++      snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
++      snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
++      snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
++
++      if (digital_gain_0db_limit) {
++              int ret;
++              struct snd_soc_card *card = rtd->card;
++
++              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);
++      }
++
++      return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
++      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *component = rtd->codec_dais[0]->component; /* only use DAC */
++      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++      struct snd_ratnum *rats_no_pll;
++      unsigned int num = 0, den = 0;
++      int err;
++
++      rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
++      if (!rats_no_pll)
++              return -ENOMEM;
++
++      rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
++      rats_no_pll->den_min = 1;
++      rats_no_pll->den_max = 128;
++      rats_no_pll->den_step = 1;
++
++      err = snd_interval_ratnum(hw_param_interval(params,
++              SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
++      if (err >= 0 && den) {
++              params->rate_num = num;
++              params->rate_den = den;
++      }
++
++      devm_kfree(rtd->dev, rats_no_pll);
++      return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_hw_params(
++      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++      int ret = 0;
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      int channels = params_channels(params);
++      int width = 32;
++      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++
++      if (snd_rpi_hifiberry_is_dacpro) {
++
++              width = snd_pcm_format_physical_width(params_format(params));
++
++              snd_rpi_hifiberry_dacplusadcpro_set_sclk(dac,
++                      params_rate(params));
++
++              ret = snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
++                      substream, params);
++              if (ret)
++                      return ret;
++      }
++
++      ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x03, 0x03,
++              channels, width);
++      if (ret)
++              return ret;
++      ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[0], 0x03, 0x03,
++              channels, width);
++      if (ret)
++              return ret;
++      ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[1], 0x03, 0x03,
++              channels, width);
++      return ret;
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_startup(
++      struct snd_pcm_substream *substream)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++      struct snd_soc_component *adc = rtd->codec_dais[1]->component;
++
++      /* switch on respective LED */
++      if (!substream->stream)
++              snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++      else
++              snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
++      return 0;
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_shutdown(
++      struct snd_pcm_substream *substream)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++      struct snd_soc_component *adc = rtd->codec_dais[1]->component;
++
++      /* switch off respective LED */
++      if (!substream->stream)
++              snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++      else
++              snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
++}
++
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_hifiberry_dacplusadcpro_ops = {
++      .hw_params = snd_rpi_hifiberry_dacplusadcpro_hw_params,
++      .startup = snd_rpi_hifiberry_dacplusadcpro_startup,
++      .shutdown = snd_rpi_hifiberry_dacplusadcpro_shutdown,
++};
++
++static struct snd_soc_dai_link_component snd_rpi_hifiberry_dacplusadcpro_codecs[] = {
++      {
++              .name           = "pcm512x.1-004d",
++              .dai_name       = "pcm512x-hifi",
++      },
++      {
++              .name           = "pcm186x.1-004a",
++              .dai_name       = "pcm1863-aif",
++      },
++};
++
++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadcpro_dai[] = {
++{
++      .name           = "HiFiBerry DAC+ADC PRO",
++      .stream_name    = "HiFiBerry DAC+ADC PRO HiFi",
++      .cpu_dai_name   = "bcm2708-i2s.0",
++      .platform_name  = "bcm2708-i2s.0",
++      .codecs         = snd_rpi_hifiberry_dacplusadcpro_codecs,
++      .num_codecs     = 2,
++      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++                              SND_SOC_DAIFMT_CBS_CFS,
++      .ops            = &snd_rpi_hifiberry_dacplusadcpro_ops,
++      .init           = snd_rpi_hifiberry_dacplusadcpro_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_hifiberry_dacplusadcpro = {
++      .name         = "snd_rpi_hifiberry_dacplusadcpro",
++      .driver_name  = "HifiberryDacpAdcPro",
++      .owner        = THIS_MODULE,
++      .dai_link     = snd_rpi_hifiberry_dacplusadcpro_dai,
++      .num_links    = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadcpro_dai),
++};
++
++static int snd_rpi_hifiberry_dacplusadcpro_probe(struct platform_device *pdev)
++{
++      int ret = 0, i = 0;
++      struct snd_soc_card *card = &snd_rpi_hifiberry_dacplusadcpro;
++
++      snd_rpi_hifiberry_dacplusadcpro.dev = &pdev->dev;
++      if (pdev->dev.of_node) {
++              struct device_node *i2s_node;
++              struct snd_soc_dai_link *dai;
++
++              dai = &snd_rpi_hifiberry_dacplusadcpro_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->cpu_dai_name = NULL;
++                              dai->cpu_of_node = i2s_node;
++                              dai->platform_name = NULL;
++                              dai->platform_of_node = i2s_node;
++                      }
++              }
++      }
++      digital_gain_0db_limit = !of_property_read_bool(
++              pdev->dev.of_node, "hifiberry-dacplusadcpro,24db_digital_gain");
++      slave = of_property_read_bool(pdev->dev.of_node,
++                                      "hifiberry-dacplusadcpro,slave");
++      ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplusadcpro);
++      if (ret && ret != -EPROBE_DEFER)
++              dev_err(&pdev->dev,
++                      "snd_soc_register_card() failed: %d\n", ret);
++
++      return ret;
++}
++
++static const struct of_device_id snd_rpi_hifiberry_dacplusadcpro_of_match[] = {
++      { .compatible = "hifiberry,hifiberry-dacplusadcpro", },
++      {},
++};
++
++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadcpro_of_match);
++
++static struct platform_driver snd_rpi_hifiberry_dacplusadcpro_driver = {
++      .driver = {
++              .name   = "snd-rpi-hifiberry-dacplusadcpro",
++              .owner  = THIS_MODULE,
++              .of_match_table = snd_rpi_hifiberry_dacplusadcpro_of_match,
++      },
++      .probe          = snd_rpi_hifiberry_dacplusadcpro_probe,
++};
++
++module_platform_driver(snd_rpi_hifiberry_dacplusadcpro_driver);
++
++MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
++MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0628-drm-vc4-Ensure-zpos-is-always-initialised.patch b/target/linux/brcm2708/patches-4.19/950-0628-drm-vc4-Ensure-zpos-is-always-initialised.patch
deleted file mode 100644 (file)
index bd13a32..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From cf80e05ebb55c121c1567ac42b9e1a885fc346a3 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 19 Jul 2019 17:49:00 +0100
-Subject: [PATCH] drm/vc4: Ensure zpos is always initialised
-
-The compiler is warning that default_zpos can be used
-uninitialised as there is no default case to catch all plane
-types.
-No other plane types should ever be presented to vc4_fkms_plane_init,
-but add a default case regardless.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -773,6 +773,7 @@ static struct drm_plane *vc4_fkms_plane_
-        * other layers as requested by KMS.
-        */
-       switch (type) {
-+      default:
-       case DRM_PLANE_TYPE_PRIMARY:
-               default_zpos = 0;
-               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0629-codecs-Correct-Katana-minimum-volume.patch b/target/linux/brcm2708/patches-4.19/950-0629-codecs-Correct-Katana-minimum-volume.patch
new file mode 100644 (file)
index 0000000..fca2810
--- /dev/null
@@ -0,0 +1,23 @@
+From 43866e3396623775215943f3062a98c642fcae95 Mon Sep 17 00:00:00 2001
+From: allo-com <jaikumar@cem-solutions.net>
+Date: Mon, 29 Jul 2019 15:06:57 +0530
+Subject: [PATCH] codecs: Correct Katana minimum volume
+
+Update Katana minimum volume to get the exact 0.5 dB value in each step.
+
+Signed-off-by: Sudeep Kumar <sudeepkumar@cem-solutions.net>
+---
+ sound/soc/bcm/allo-katana-codec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/bcm/allo-katana-codec.c
++++ b/sound/soc/bcm/allo-katana-codec.c
+@@ -126,7 +126,7 @@ static SOC_VALUE_ENUM_SINGLE_DECL(katana
+                                 katana_codec_deemphasis_texts,
+                                 katana_codec_deemphasis_values);
+-static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12700, 0);
++static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
+ static const struct snd_kcontrol_new katana_codec_controls[] = {
+       SOC_DOUBLE_R_TLV("Master Playback Volume", KATANA_CODEC_VOLUME_1,
diff --git a/target/linux/brcm2708/patches-4.19/950-0629-dts-bcm2838-add-missing-properties-for-pmu-and-gic-n.patch b/target/linux/brcm2708/patches-4.19/950-0629-dts-bcm2838-add-missing-properties-for-pmu-and-gic-n.patch
deleted file mode 100644 (file)
index 553c16c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From a78d4d81c585a5de61e7fc7d574e6e3f769c18a6 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Wed, 24 Jul 2019 14:36:53 +0100
-Subject: [PATCH] dts: bcm2838: add missing properties for pmu and gic
- nodes
-
-The GIC has a virtual interface maintenance interrupt and the PMU
-interrupts need affinity mappings as they are wired to generic SPIs.
-
-Also, delete incorrect PMU compatible string.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2838.dtsi | 9 ++++-----
- 1 file changed, 4 insertions(+), 5 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -35,6 +35,8 @@
-                               <0x40042000 0x2000>,
-                               <0x40044000 0x2000>,
-                               <0x40046000 0x2000>;
-+                      interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) |
-+                                               IRQ_TYPE_LEVEL_HIGH)>;
-               };
-               thermal: thermal@7d5d2200 {
-@@ -222,15 +224,12 @@
-       };
-       arm-pmu {
--              /*
--               * N.B. the A72 PMU support only exists in arch/arm64, hence
--               * the fallback to the A53 version.
--               */
--              compatible = "arm,cortex-a72-pmu", "arm,cortex-a53-pmu";
-+              compatible = "arm,cortex-a72-pmu";
-               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-+              interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
-       };
-       timer {
diff --git a/target/linux/brcm2708/patches-4.19/950-0630-adds-the-Hifiberry-DAC-ADC-PRO-version.patch b/target/linux/brcm2708/patches-4.19/950-0630-adds-the-Hifiberry-DAC-ADC-PRO-version.patch
deleted file mode 100644 (file)
index 427053d..0000000
+++ /dev/null
@@ -1,701 +0,0 @@
-From bab5f8832c6b2859caea1cb5af1ffcb6276c2f74 Mon Sep 17 00:00:00 2001
-From: Joerg Schambacher <joscha@schambacher.com>
-Date: Tue, 23 Jul 2019 16:57:35 +0200
-Subject: [PATCH] adds the Hifiberry DAC+ADC PRO version
-
-This adds the driver for the DAC+ADC PRO version of the Hifiberry soundcard with software controlled PCM1863 ADC
-Signed-off-by: Joerg Schambacher joerg@i2audio.com
----
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |  21 +
- .../hifiberry-dacplusadcpro-overlay.dts       |  64 +++
- sound/soc/bcm/Kconfig                         |   8 +
- sound/soc/bcm/Makefile                        |   2 +
- sound/soc/bcm/hifiberry_dacplusadcpro.c       | 538 ++++++++++++++++++
- 9 files changed, 637 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
- create mode 100644 sound/soc/bcm/hifiberry_dacplusadcpro.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -53,6 +53,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       hifiberry-dac.dtbo \
-       hifiberry-dacplus.dtbo \
-       hifiberry-dacplusadc.dtbo \
-+      hifiberry-dacplusadcpro.dtbo \
-       hifiberry-digi.dtbo \
-       hifiberry-digi-pro.dtbo \
-       hy28a.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -883,6 +883,27 @@ Params: 24db_digital_gain       Allow ga
-                                 master for bit clock and frame clock.
-+Name:   hifiberry-dacplusadcpro
-+Info:   Configures the HifiBerry DAC+ADC PRO audio card
-+Load:   dtoverlay=hifiberry-dacplusadcpro,<param>=<val>
-+Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
-+                                Digital volume control. Enable with
-+                                "dtoverlay=hifiberry-dacplusadcpro,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+ADC Pro into slave mode, using Pi as
-+                                master for bit clock and frame clock.
-+
-+
- Name:   hifiberry-digi
- Info:   Configures the HifiBerry Digi and Digi+ audio card
- Load:   dtoverlay=hifiberry-digi
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
-@@ -0,0 +1,64 @@
-+// Definitions for HiFiBerry DAC+ADC PRO
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2708";
-+
-+      fragment@0 {
-+              target-path = "/clocks";
-+              __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";
-+
-+                      hb_dac: pcm5122@4d {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "ti,pcm5122";
-+                              reg = <0x4d>;
-+                              clocks = <&dacpro_osc>;
-+                              status = "okay";
-+                      };
-+                      hb_adc: pcm186x@4a {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "ti,pcm1863";
-+                              reg = <0x4a>;
-+                              clocks = <&dacpro_osc>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&sound>;
-+              hifiberry_dacplusadcpro: __overlay__ {
-+                      compatible = "hifiberry,hifiberry-dacplusadcpro";
-+                      audio-codec = <&hb_dac &hb_adc>;
-+                      i2s-controller = <&i2s>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      __overrides__ {
-+              24db_digital_gain =
-+                      <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,24db_digital_gain?";
-+              slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?";
-+      };
-+};
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -48,6 +48,14 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
-         help
-          Say Y or M if you want to add support for HifiBerry DAC+ADC.
-+config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO
-+        tristate "Support for HifiBerry DAC+ADC PRO"
-+        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+        select SND_SOC_PCM512x_I2C
-+      select SND_SOC_PCM186X_I2C
-+        help
-+         Say Y or M if you want to add support for HifiBerry DAC+ADC PRO.
-+
- config SND_BCM2708_SOC_HIFIBERRY_DIGI
-         tristate "Support for HifiBerry Digi"
-         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -14,6 +14,7 @@ snd-soc-googlevoicehat-codec-objs := goo
- # BCM2708 Machine Support
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
- snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
-+snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
-@@ -38,6 +39,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
- obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD)  += snd-soc-googlevoicehat-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
-+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
---- /dev/null
-+++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
-@@ -0,0 +1,538 @@
-+/*
-+ * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC PRO Version (SW control)
-+ *
-+ * Author:    Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
-+ *            Copyright 2014-2015
-+ *            based on code by Florian Meier <florian.meier@koalo.de>
-+ *            ADC added by Joerg Schambacher <joerg@i2audio.com>
-+ *            Copyright 2018-19
-+ *
-+ * 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/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+#include <sound/tlv.h>
-+
-+#include "../codecs/pcm512x.h"
-+#include "../codecs/pcm186x.h"
-+
-+#define HIFIBERRY_DACPRO_NOCLOCK 0
-+#define HIFIBERRY_DACPRO_CLK44EN 1
-+#define HIFIBERRY_DACPRO_CLK48EN 2
-+
-+struct pcm512x_priv {
-+      struct regmap *regmap;
-+      struct clk *sclk;
-+};
-+
-+/* Clock rate of CLK44EN attached to GPIO6 pin */
-+#define CLK_44EN_RATE 22579200UL
-+/* Clock rate of CLK48EN attached to GPIO3 pin */
-+#define CLK_48EN_RATE 24576000UL
-+
-+static bool slave;
-+static bool snd_rpi_hifiberry_is_dacpro;
-+static bool digital_gain_0db_limit = true;
-+
-+static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
-+      0x00, 0x01, 0x02, 0x03, 0x10
-+};
-+
-+static const char * const pcm186x_adcl_input_channel_sel_text[] = {
-+      "No Select",
-+      "VINL1[SE]",                                    /* Default for ADCL */
-+      "VINL2[SE]",
-+      "VINL2[SE] + VINL1[SE]",
-+      "{VIN1P, VIN1M}[DIFF]"
-+};
-+
-+static const char * const pcm186x_adcr_input_channel_sel_text[] = {
-+      "No Select",
-+      "VINR1[SE]",                                    /* Default for ADCR */
-+      "VINR2[SE]",
-+      "VINR2[SE] + VINR1[SE]",
-+      "{VIN2P, VIN2M}[DIFF]"
-+};
-+
-+static const struct soc_enum pcm186x_adc_input_channel_sel[] = {
-+      SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_L, 0,
-+                            PCM186X_ADC_INPUT_SEL_MASK,
-+                            ARRAY_SIZE(pcm186x_adcl_input_channel_sel_text),
-+                            pcm186x_adcl_input_channel_sel_text,
-+                            pcm186x_adc_input_channel_sel_value),
-+      SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_R, 0,
-+                            PCM186X_ADC_INPUT_SEL_MASK,
-+                            ARRAY_SIZE(pcm186x_adcr_input_channel_sel_text),
-+                            pcm186x_adcr_input_channel_sel_text,
-+                            pcm186x_adc_input_channel_sel_value),
-+};
-+
-+static const unsigned int pcm186x_mic_bias_sel_value[] = {
-+      0x00, 0x01, 0x11
-+};
-+
-+static const char * const pcm186x_mic_bias_sel_text[] = {
-+      "Mic Bias off",
-+      "Mic Bias on",
-+      "Mic Bias with Bypass Resistor"
-+};
-+
-+static const struct soc_enum pcm186x_mic_bias_sel[] = {
-+      SOC_VALUE_ENUM_SINGLE(PCM186X_MIC_BIAS_CTRL, 0,
-+                            GENMASK(4, 0),
-+                            ARRAY_SIZE(pcm186x_mic_bias_sel_text),
-+                            pcm186x_mic_bias_sel_text,
-+                            pcm186x_mic_bias_sel_value),
-+};
-+
-+static const unsigned int pcm186x_gain_sel_value[] = {
-+      0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-+      0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-+      0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-+      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-+      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-+      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-+      0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-+      0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-+      0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
-+      0x50
-+};
-+
-+static const char * const pcm186x_gain_sel_text[] = {
-+      "-12.0dB", "-11.5dB", "-11.0dB", "-10.5dB", "-10.0dB", "-9.5dB",
-+      "-9.0dB", "-8.5dB", "-8.0dB", "-7.5dB", "-7.0dB", "-6.5dB",
-+      "-6.0dB", "-5.5dB", "-5.0dB", "-4.5dB", "-4.0dB", "-3.5dB",
-+      "-3.0dB", "-2.5dB", "-2.0dB", "-1.5dB", "-1.0dB", "-0.5dB",
-+      "0.0dB", "0.5dB", "1.0dB", "1.5dB", "2.0dB", "2.5dB",
-+      "3.0dB", "3.5dB", "4.0dB", "4.5dB", "5.0dB", "5.5dB",
-+      "6.0dB", "6.5dB", "7.0dB", "7.5dB", "8.0dB", "8.5dB",
-+      "9.0dB", "9.5dB", "10.0dB", "10.5dB", "11.0dB", "11.5dB",
-+      "12.0dB", "12.5dB", "13.0dB", "13.5dB", "14.0dB", "14.5dB",
-+      "15.0dB", "15.5dB", "16.0dB", "16.5dB", "17.0dB", "17.5dB",
-+      "18.0dB", "18.5dB", "19.0dB", "19.5dB", "20.0dB", "20.5dB",
-+      "21.0dB", "21.5dB", "22.0dB", "22.5dB", "23.0dB", "23.5dB",
-+      "24.0dB", "24.5dB", "25.0dB", "25.5dB", "26.0dB", "26.5dB",
-+      "27.0dB", "27.5dB", "28.0dB", "28.5dB", "29.0dB", "29.5dB",
-+      "30.0dB", "30.5dB", "31.0dB", "31.5dB", "32.0dB", "32.5dB",
-+      "33.0dB", "33.5dB", "34.0dB", "34.5dB", "35.0dB", "35.5dB",
-+      "36.0dB", "36.5dB", "37.0dB", "37.5dB", "38.0dB", "38.5dB",
-+      "39.0dB", "39.5dB", "40.0dB"};
-+
-+static const struct soc_enum pcm186x_gain_sel[] = {
-+      SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_L, 0,
-+                            0xff,
-+                            ARRAY_SIZE(pcm186x_gain_sel_text),
-+                            pcm186x_gain_sel_text,
-+                            pcm186x_gain_sel_value),
-+      SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_R, 0,
-+                            0xff,
-+                            ARRAY_SIZE(pcm186x_gain_sel_text),
-+                            pcm186x_gain_sel_text,
-+                            pcm186x_gain_sel_value),
-+};
-+
-+static const struct snd_kcontrol_new pcm1863_snd_controls_card[] = {
-+      SOC_ENUM("ADC Left Input", pcm186x_adc_input_channel_sel[0]),
-+      SOC_ENUM("ADC Right Input", pcm186x_adc_input_channel_sel[1]),
-+      SOC_ENUM("ADC Mic Bias", pcm186x_mic_bias_sel),
-+      SOC_ENUM("PGA Gain Left", pcm186x_gain_sel[0]),
-+      SOC_ENUM("PGA Gain Right", pcm186x_gain_sel[1]),
-+};
-+
-+static int pcm1863_add_controls(struct snd_soc_component *component)
-+{
-+      snd_soc_add_component_controls(component,
-+                      pcm1863_snd_controls_card,
-+                      ARRAY_SIZE(pcm1863_snd_controls_card));
-+      return 0;
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadcpro_select_clk(
-+                                      struct snd_soc_component *component, int clk_id)
-+{
-+      switch (clk_id) {
-+      case HIFIBERRY_DACPRO_NOCLOCK:
-+              snd_soc_component_update_bits(component,
-+                              PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
-+              break;
-+      case HIFIBERRY_DACPRO_CLK44EN:
-+              snd_soc_component_update_bits(component,
-+                              PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
-+              break;
-+      case HIFIBERRY_DACPRO_CLK48EN:
-+              snd_soc_component_update_bits(component,
-+                              PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
-+              break;
-+      }
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
-+{
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
-+      snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
-+}
-+
-+static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk(struct snd_soc_component *component)
-+{
-+      unsigned int sck;
-+
-+      snd_soc_component_read(component, PCM512x_RATE_DET_4, &sck);
-+      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;
-+
-+      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);
-+
-+      snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
-+      isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
-+
-+      snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
-+      isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
-+
-+      return (isClk44EN && isClk48En && !isNoClk);
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(int sample_rate)
-+{
-+      int type;
-+
-+      switch (sample_rate) {
-+      case 11025:
-+      case 22050:
-+      case 44100:
-+      case 88200:
-+      case 176400:
-+      case 352800:
-+              type = HIFIBERRY_DACPRO_CLK44EN;
-+              break;
-+      default:
-+              type = HIFIBERRY_DACPRO_CLK48EN;
-+              break;
-+      }
-+      return type;
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadcpro_set_sclk(struct snd_soc_component *component,
-+      int sample_rate)
-+{
-+      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+
-+      if (!IS_ERR(pcm512x->sclk)) {
-+              int ctype;
-+
-+              ctype = snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(sample_rate);
-+              clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
-+                      ? CLK_44EN_RATE : CLK_48EN_RATE);
-+              snd_rpi_hifiberry_dacplusadcpro_select_clk(component, ctype);
-+      }
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadcpro_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
-+      struct snd_soc_component *adc = rtd->codec_dais[1]->component;
-+      struct snd_soc_dai_driver *adc_driver = rtd->codec_dais[1]->driver;
-+      struct pcm512x_priv *priv;
-+      int ret;
-+
-+      if (slave)
-+              snd_rpi_hifiberry_is_dacpro = false;
-+      else
-+              snd_rpi_hifiberry_is_dacpro =
-+                              snd_rpi_hifiberry_dacplusadcpro_is_pro_card(dac);
-+
-+      if (snd_rpi_hifiberry_is_dacpro) {
-+              struct snd_soc_dai_link *dai = rtd->dai_link;
-+
-+              dai->name = "HiFiBerry DAC+ADC Pro";
-+              dai->stream_name = "HiFiBerry DAC+ADC Pro HiFi";
-+
-+              // set DAC DAI configuration
-+              ret = snd_soc_dai_set_fmt(rtd->codec_dais[0],
-+                              SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+                      | SND_SOC_DAIFMT_CBM_CFM);
-+              if (ret < 0)
-+                      return ret;
-+
-+              // set ADC DAI configuration
-+              ret = snd_soc_dai_set_fmt(rtd->codec_dais[1],
-+                              SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+                      | SND_SOC_DAIFMT_CBS_CFS);
-+              if (ret < 0)
-+                      return ret;
-+
-+              // set CPU DAI configuration
-+              ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
-+                      SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-+              if (ret < 0)
-+                      return ret;
-+
-+              snd_soc_component_update_bits(dac, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
-+              snd_soc_component_update_bits(dac, PCM512x_MASTER_MODE, 0x03, 0x03);
-+              snd_soc_component_update_bits(dac, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
-+      } else {
-+              priv = snd_soc_component_get_drvdata(dac);
-+              priv->sclk = ERR_PTR(-ENOENT);
-+      }
-+
-+      /* disable 24bit mode as long as I2S module does not have sign extension fixed */
-+      adc_driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE;
-+
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+
-+      ret = pcm1863_add_controls(adc);
-+      if (ret < 0)
-+              dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
-+              ret);
-+
-+      /* set GPIO2 to output, GPIO3 input */
-+      snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
-+      snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
-+      snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
-+
-+      if (digital_gain_0db_limit) {
-+              int ret;
-+              struct snd_soc_card *card = rtd->card;
-+
-+              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);
-+      }
-+
-+      return 0;
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
-+      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *component = rtd->codec_dais[0]->component; /* only use DAC */
-+      struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+      struct snd_ratnum *rats_no_pll;
-+      unsigned int num = 0, den = 0;
-+      int err;
-+
-+      rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
-+      if (!rats_no_pll)
-+              return -ENOMEM;
-+
-+      rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
-+      rats_no_pll->den_min = 1;
-+      rats_no_pll->den_max = 128;
-+      rats_no_pll->den_step = 1;
-+
-+      err = snd_interval_ratnum(hw_param_interval(params,
-+              SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
-+      if (err >= 0 && den) {
-+              params->rate_num = num;
-+              params->rate_den = den;
-+      }
-+
-+      devm_kfree(rtd->dev, rats_no_pll);
-+      return 0;
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadcpro_hw_params(
-+      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
-+{
-+      int ret = 0;
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      int channels = params_channels(params);
-+      int width = 32;
-+      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
-+
-+      if (snd_rpi_hifiberry_is_dacpro) {
-+
-+              width = snd_pcm_format_physical_width(params_format(params));
-+
-+              snd_rpi_hifiberry_dacplusadcpro_set_sclk(dac,
-+                      params_rate(params));
-+
-+              ret = snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
-+                      substream, params);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x03, 0x03,
-+              channels, width);
-+      if (ret)
-+              return ret;
-+      ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[0], 0x03, 0x03,
-+              channels, width);
-+      if (ret)
-+              return ret;
-+      ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[1], 0x03, 0x03,
-+              channels, width);
-+      return ret;
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadcpro_startup(
-+      struct snd_pcm_substream *substream)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
-+      struct snd_soc_component *adc = rtd->codec_dais[1]->component;
-+
-+      /* switch on respective LED */
-+      if (!substream->stream)
-+              snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+      else
-+              snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
-+      return 0;
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadcpro_shutdown(
-+      struct snd_pcm_substream *substream)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *dac = rtd->codec_dais[0]->component;
-+      struct snd_soc_component *adc = rtd->codec_dais[1]->component;
-+
-+      /* switch off respective LED */
-+      if (!substream->stream)
-+              snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
-+      else
-+              snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
-+}
-+
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_hifiberry_dacplusadcpro_ops = {
-+      .hw_params = snd_rpi_hifiberry_dacplusadcpro_hw_params,
-+      .startup = snd_rpi_hifiberry_dacplusadcpro_startup,
-+      .shutdown = snd_rpi_hifiberry_dacplusadcpro_shutdown,
-+};
-+
-+static struct snd_soc_dai_link_component snd_rpi_hifiberry_dacplusadcpro_codecs[] = {
-+      {
-+              .name           = "pcm512x.1-004d",
-+              .dai_name       = "pcm512x-hifi",
-+      },
-+      {
-+              .name           = "pcm186x.1-004a",
-+              .dai_name       = "pcm1863-aif",
-+      },
-+};
-+
-+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadcpro_dai[] = {
-+{
-+      .name           = "HiFiBerry DAC+ADC PRO",
-+      .stream_name    = "HiFiBerry DAC+ADC PRO HiFi",
-+      .cpu_dai_name   = "bcm2708-i2s.0",
-+      .platform_name  = "bcm2708-i2s.0",
-+      .codecs         = snd_rpi_hifiberry_dacplusadcpro_codecs,
-+      .num_codecs     = 2,
-+      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+                              SND_SOC_DAIFMT_CBS_CFS,
-+      .ops            = &snd_rpi_hifiberry_dacplusadcpro_ops,
-+      .init           = snd_rpi_hifiberry_dacplusadcpro_init,
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_hifiberry_dacplusadcpro = {
-+      .name         = "snd_rpi_hifiberry_dacplusadcpro",
-+      .driver_name  = "HifiberryDacpAdcPro",
-+      .owner        = THIS_MODULE,
-+      .dai_link     = snd_rpi_hifiberry_dacplusadcpro_dai,
-+      .num_links    = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadcpro_dai),
-+};
-+
-+static int snd_rpi_hifiberry_dacplusadcpro_probe(struct platform_device *pdev)
-+{
-+      int ret = 0, i = 0;
-+      struct snd_soc_card *card = &snd_rpi_hifiberry_dacplusadcpro;
-+
-+      snd_rpi_hifiberry_dacplusadcpro.dev = &pdev->dev;
-+      if (pdev->dev.of_node) {
-+              struct device_node *i2s_node;
-+              struct snd_soc_dai_link *dai;
-+
-+              dai = &snd_rpi_hifiberry_dacplusadcpro_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->cpu_dai_name = NULL;
-+                              dai->cpu_of_node = i2s_node;
-+                              dai->platform_name = NULL;
-+                              dai->platform_of_node = i2s_node;
-+                      }
-+              }
-+      }
-+      digital_gain_0db_limit = !of_property_read_bool(
-+              pdev->dev.of_node, "hifiberry-dacplusadcpro,24db_digital_gain");
-+      slave = of_property_read_bool(pdev->dev.of_node,
-+                                      "hifiberry-dacplusadcpro,slave");
-+      ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplusadcpro);
-+      if (ret && ret != -EPROBE_DEFER)
-+              dev_err(&pdev->dev,
-+                      "snd_soc_register_card() failed: %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static const struct of_device_id snd_rpi_hifiberry_dacplusadcpro_of_match[] = {
-+      { .compatible = "hifiberry,hifiberry-dacplusadcpro", },
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadcpro_of_match);
-+
-+static struct platform_driver snd_rpi_hifiberry_dacplusadcpro_driver = {
-+      .driver = {
-+              .name   = "snd-rpi-hifiberry-dacplusadcpro",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = snd_rpi_hifiberry_dacplusadcpro_of_match,
-+      },
-+      .probe          = snd_rpi_hifiberry_dacplusadcpro_probe,
-+};
-+
-+module_platform_driver(snd_rpi_hifiberry_dacplusadcpro_driver);
-+
-+MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
-+MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
-+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0630-drm-vc4-A-present-but-empty-dmas-disables-audio.patch b/target/linux/brcm2708/patches-4.19/950-0630-drm-vc4-A-present-but-empty-dmas-disables-audio.patch
new file mode 100644 (file)
index 0000000..2d38456
--- /dev/null
@@ -0,0 +1,33 @@
+From 8befbf55f2668a4dae739588ed3c0b0d06fccacd Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 31 Jul 2019 17:36:34 +0100
+Subject: [PATCH] drm/vc4: A present but empty dmas disables audio
+
+Overlays are unable to remove properties in the base DTB, but they
+can overwrite them. Allow a present but empty 'dmas' property
+to also disable the HDMI audio interface.
+
+See: https://github.com/raspberrypi/linux/issues/2489
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -1087,10 +1087,12 @@ static int vc4_hdmi_audio_init(struct vc
+       struct device *dev = &hdmi->pdev->dev;
+       const __be32 *addr;
+       int ret;
++      int len;
+-      if (!of_find_property(dev->of_node, "dmas", NULL)) {
++      if (!of_find_property(dev->of_node, "dmas", &len) ||
++          len == 0) {
+               dev_warn(dev,
+-                       "'dmas' DT property is missing, no HDMI audio\n");
++                       "'dmas' DT property is missing or empty, no HDMI audio\n");
+               return 0;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0631-codecs-Correct-Katana-minimum-volume.patch b/target/linux/brcm2708/patches-4.19/950-0631-codecs-Correct-Katana-minimum-volume.patch
deleted file mode 100644 (file)
index fca2810..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 43866e3396623775215943f3062a98c642fcae95 Mon Sep 17 00:00:00 2001
-From: allo-com <jaikumar@cem-solutions.net>
-Date: Mon, 29 Jul 2019 15:06:57 +0530
-Subject: [PATCH] codecs: Correct Katana minimum volume
-
-Update Katana minimum volume to get the exact 0.5 dB value in each step.
-
-Signed-off-by: Sudeep Kumar <sudeepkumar@cem-solutions.net>
----
- sound/soc/bcm/allo-katana-codec.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/sound/soc/bcm/allo-katana-codec.c
-+++ b/sound/soc/bcm/allo-katana-codec.c
-@@ -126,7 +126,7 @@ static SOC_VALUE_ENUM_SINGLE_DECL(katana
-                                 katana_codec_deemphasis_texts,
-                                 katana_codec_deemphasis_values);
--static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12700, 0);
-+static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
- static const struct snd_kcontrol_new katana_codec_controls[] = {
-       SOC_DOUBLE_R_TLV("Master Playback Volume", KATANA_CODEC_VOLUME_1,
diff --git a/target/linux/brcm2708/patches-4.19/950-0631-overlays-Add-audio-parameter-to-vc4-kms-v3d.patch b/target/linux/brcm2708/patches-4.19/950-0631-overlays-Add-audio-parameter-to-vc4-kms-v3d.patch
new file mode 100644 (file)
index 0000000..a70d50e
--- /dev/null
@@ -0,0 +1,49 @@
+From 418ca5973ad807f9d7f99e68af2bd21c7e8baa4d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 31 Jul 2019 17:39:37 +0100
+Subject: [PATCH] overlays: Add audio parameter to vc4-kms-v3d
+
+The audio parameter to the vc4-kms-v3d overlay allows audio support
+to be disabled (it defaults to on) by adding "audio=off" to the
+dtoverlay parameters.
+
+See: https://github.com/raspberrypi/linux/issues/2489
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README                  | 1 +
+ arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 8 ++++++++
+ 2 files changed, 9 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2480,6 +2480,7 @@ Params: cma-256                 CMA is 2
+         cma-128                 CMA is 128MB
+         cma-96                  CMA is 96MB
+         cma-64                  CMA is 64MB
++        audio                   Enable or disable audio over HDMI (default "on")
+ Name:   vga666
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
+@@ -134,11 +134,19 @@
+               };
+       };
++      fragment@17 {
++              target = <&hdmi>;
++              __dormant__  {
++                      dmas;
++              };
++      };
++
+       __overrides__ {
+               cma-256 = <0>,"+0-1-2-3-4";
+               cma-192 = <0>,"-0+1-2-3-4";
+               cma-128 = <0>,"-0-1+2-3-4";
+               cma-96  = <0>,"-0-1-2+3-4";
+               cma-64  = <0>,"-0-1-2-3+4";
++              audio   = <0>,"!17";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0632-drm-vc4-A-present-but-empty-dmas-disables-audio.patch b/target/linux/brcm2708/patches-4.19/950-0632-drm-vc4-A-present-but-empty-dmas-disables-audio.patch
deleted file mode 100644 (file)
index 2d38456..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 8befbf55f2668a4dae739588ed3c0b0d06fccacd Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 31 Jul 2019 17:36:34 +0100
-Subject: [PATCH] drm/vc4: A present but empty dmas disables audio
-
-Overlays are unable to remove properties in the base DTB, but they
-can overwrite them. Allow a present but empty 'dmas' property
-to also disable the HDMI audio interface.
-
-See: https://github.com/raspberrypi/linux/issues/2489
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_hdmi.c
-+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -1087,10 +1087,12 @@ static int vc4_hdmi_audio_init(struct vc
-       struct device *dev = &hdmi->pdev->dev;
-       const __be32 *addr;
-       int ret;
-+      int len;
--      if (!of_find_property(dev->of_node, "dmas", NULL)) {
-+      if (!of_find_property(dev->of_node, "dmas", &len) ||
-+          len == 0) {
-               dev_warn(dev,
--                       "'dmas' DT property is missing, no HDMI audio\n");
-+                       "'dmas' DT property is missing or empty, no HDMI audio\n");
-               return 0;
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0632-overlays-Update-the-upstream-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0632-overlays-Update-the-upstream-overlay.patch
new file mode 100644 (file)
index 0000000..6cec814
--- /dev/null
@@ -0,0 +1,28 @@
+From a14162d8da62fb570df916d7386febe51d6ed2bc Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 31 Jul 2019 17:41:47 +0100
+Subject: [PATCH] overlays: Update the upstream overlay
+
+The recent vc4-kms-v3d commit has changed the content of the
+upstream overlay (even though the extra fragment is disabled).
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/upstream-overlay.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -110,6 +110,12 @@
+               };
+       };
+       fragment@17 {
++              target = <&hdmi>;
++              __dormant__ {
++                      dmas;
++              };
++      };
++      fragment@18 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0633-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch b/target/linux/brcm2708/patches-4.19/950-0633-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch
new file mode 100644 (file)
index 0000000..2626658
--- /dev/null
@@ -0,0 +1,39 @@
+From c2957d7709a43c81e5345d537feaa6980ffcc1a4 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Mon, 29 Jul 2019 12:02:59 +0100
+Subject: [PATCH] Fixup FKMS interrupt handing for non-existent display
+
+If an errant interrupt flag was received from a non-existent display,
+a NULL pointer access was made. Protect against this by checking if a
+second display is present prior to checking the interrupt flags.
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1056,14 +1056,17 @@ static irqreturn_t vc4_crtc_irq_handler(
+                               vc4_crtc_handle_page_flip(crtc_list[0]);
+                       }
+-                      /* Check for the secondary display too */
+-                      chan = readl(crtc_list[0]->regs + SMIDSW1);
++                      if (crtc_list[1]) {
++                              /* Check for the secondary display too */
++                              chan = readl(crtc_list[0]->regs + SMIDSW1);
+-                      if (chan & 1) {
+-                              writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
+-                              if (crtc_list[1]->vblank_enabled)
+-                                      drm_crtc_handle_vblank(&crtc_list[1]->base);
+-                              vc4_crtc_handle_page_flip(crtc_list[1]);
++                              if (chan & 1) {
++                                      writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
++
++                                      if (crtc_list[1]->vblank_enabled)
++                                              drm_crtc_handle_vblank(&crtc_list[1]->base);
++                                      vc4_crtc_handle_page_flip(crtc_list[1]);
++                              }
+                       }
+               }
diff --git a/target/linux/brcm2708/patches-4.19/950-0633-overlays-Add-audio-parameter-to-vc4-kms-v3d.patch b/target/linux/brcm2708/patches-4.19/950-0633-overlays-Add-audio-parameter-to-vc4-kms-v3d.patch
deleted file mode 100644 (file)
index a70d50e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 418ca5973ad807f9d7f99e68af2bd21c7e8baa4d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 31 Jul 2019 17:39:37 +0100
-Subject: [PATCH] overlays: Add audio parameter to vc4-kms-v3d
-
-The audio parameter to the vc4-kms-v3d overlay allows audio support
-to be disabled (it defaults to on) by adding "audio=off" to the
-dtoverlay parameters.
-
-See: https://github.com/raspberrypi/linux/issues/2489
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README                  | 1 +
- arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 8 ++++++++
- 2 files changed, 9 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2480,6 +2480,7 @@ Params: cma-256                 CMA is 2
-         cma-128                 CMA is 128MB
-         cma-96                  CMA is 96MB
-         cma-64                  CMA is 64MB
-+        audio                   Enable or disable audio over HDMI (default "on")
- Name:   vga666
---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-@@ -134,11 +134,19 @@
-               };
-       };
-+      fragment@17 {
-+              target = <&hdmi>;
-+              __dormant__  {
-+                      dmas;
-+              };
-+      };
-+
-       __overrides__ {
-               cma-256 = <0>,"+0-1-2-3-4";
-               cma-192 = <0>,"-0+1-2-3-4";
-               cma-128 = <0>,"-0-1+2-3-4";
-               cma-96  = <0>,"-0-1-2+3-4";
-               cma-64  = <0>,"-0-1-2-3+4";
-+              audio   = <0>,"!17";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0634-drivers-char-Use-correct-name-for-the-Raspberry-Pi-v.patch b/target/linux/brcm2708/patches-4.19/950-0634-drivers-char-Use-correct-name-for-the-Raspberry-Pi-v.patch
new file mode 100644 (file)
index 0000000..92ecf12
--- /dev/null
@@ -0,0 +1,689 @@
+From 6c8c9ca56ce6039ade09d26c069132538e4de9f0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 28 Jul 2019 22:22:36 +0100
+Subject: [PATCH] drivers: char: Use correct name for the Raspberry Pi
+ video decoder
+
+Replace the old code name with a more appropriate name - RPiVid.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi                |  10 +-
+ drivers/char/broadcom/Kconfig                 |   8 +-
+ drivers/char/broadcom/Makefile                |   2 +-
+ .../broadcom/{argon-mem.c => rpivid-mem.c}    | 105 +++++++++---------
+ drivers/mfd/bcm2835-pm.c                      |  12 +-
+ drivers/soc/bcm/bcm2835-power.c               |   6 +-
+ include/linux/mfd/bcm2835-pm.h                |   2 +-
+ 8 files changed, 71 insertions(+), 76 deletions(-)
+ rename drivers/char/broadcom/{argon-mem.c => rpivid-mem.c} (69%)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -409,26 +409,26 @@
+               };
+               hevc-decoder@7eb00000 {
+-                      compatible = "raspberrypi,argon-hevc-decoder";
++                      compatible = "raspberrypi,rpivid-hevc-decoder";
+                       reg = <0x0 0x7eb00000 0x10000>;
+                       status = "okay";
+               };
+-              argon-local-intc@7eb10000 {
+-                      compatible = "raspberrypi,argon-local-intc";
++              rpivid-local-intc@7eb10000 {
++                      compatible = "raspberrypi,rpivid-local-intc";
+                       reg = <0x0 0x7eb10000 0x1000>;
+                       status = "okay";
+                       interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+               };
+               h264-decoder@7eb20000 {
+-                      compatible = "raspberrypi,argon-h264-decoder";
++                      compatible = "raspberrypi,rpivid-h264-decoder";
+                       reg = <0x0 0x7eb20000 0x10000>;
+                       status = "okay";
+               };
+               vp9-decoder@7eb30000 {
+-                      compatible = "raspberrypi,argon-vp9-decoder";
++                      compatible = "raspberrypi,rpivid-vp9-decoder";
+                       reg = <0x0 0x7eb30000 0x10000>;
+                       status = "okay";
+               };
+--- a/drivers/char/broadcom/Kconfig
++++ b/drivers/char/broadcom/Kconfig
+@@ -50,10 +50,10 @@ config BCM2835_SMI_DEV
+               Broadcom's Secondary Memory interface. The low-level functionality is provided
+               by the SMI driver itself.
+-config ARGON_MEM
+-      tristate "Character device driver for the Argon decoder hardware"
++config RPIVID_MEM
++      tristate "Character device driver for the Raspberry Pi RPIVid video decoder hardware"
+       default n
+       help
+               This driver provides a character device interface for memory-map operations
+-              so userspace tools can access the control and status registers of the Argon
+-              video decoder hardware.
++              so userspace tools can access the control and status registers of the
++              Raspberry Pi RPiVid video decoder hardware.
+--- a/drivers/char/broadcom/Makefile
++++ b/drivers/char/broadcom/Makefile
+@@ -4,4 +4,4 @@ obj-$(CONFIG_BCM_VC_SM)         += vc_sm
+ obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
+ obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o
+-obj-$(CONFIG_ARGON_MEM)               += argon-mem.o
++obj-$(CONFIG_RPIVID_MEM)      += rpivid-mem.o
+--- a/drivers/char/broadcom/argon-mem.c
++++ /dev/null
+@@ -1,277 +0,0 @@
+-/**
+- * argon-mem.c - character device access to the Argon decoder registers
+- *
+- * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
+- * register blocks such that ffmpeg plugins can access the hardware.
+- *
+- * Jonathan Bell <jonathan@raspberrypi.org>
+- * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- *    notice, this list of conditions, and the following disclaimer,
+- *    without modification.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- *    notice, this list of conditions and the following disclaimer in the
+- *    documentation and/or other materials provided with the distribution.
+- * 3. The names of the above-listed copyright holders may not be used
+- *    to endorse or promote products derived from this software without
+- *    specific prior written permission.
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") version 2, as published by the Free
+- * Software Foundation.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-#include <linux/platform_device.h>
+-#include <linux/mm.h>
+-#include <linux/slab.h>
+-#include <linux/cdev.h>
+-#include <linux/pagemap.h>
+-#include <linux/io.h>
+-
+-#define DRIVER_NAME "argon-mem"
+-#define DEVICE_MINOR 0
+-
+-struct argon_mem_priv {
+-      dev_t devid;
+-      struct class *class;
+-      struct cdev argon_mem_cdev;
+-      unsigned long regs_phys;
+-      unsigned long mem_window_len;
+-      struct device *dev;
+-      const char *name;
+-};
+-
+-static int argon_mem_open(struct inode *inode, struct file *file)
+-{
+-      int dev = iminor(inode);
+-      int ret = 0;
+-      struct argon_mem_priv *priv;
+-      if (dev != DEVICE_MINOR)
+-              ret = -ENXIO;
+-
+-      priv = container_of(inode->i_cdev, struct argon_mem_priv,
+-                              argon_mem_cdev);
+-      if (!priv)
+-              return -EINVAL;
+-      file->private_data = priv;
+-      return ret;
+-}
+-
+-static int argon_mem_release(struct inode *inode, struct file *file)
+-{
+-      int dev = iminor(inode);
+-      int ret = 0;
+-
+-      if (dev != DEVICE_MINOR)
+-              ret = -ENXIO;
+-
+-      return ret;
+-}
+-
+-static const struct vm_operations_struct argon_mem_vm_ops = {
+-#ifdef CONFIG_HAVE_IOREMAP_PROT
+-      .access = generic_access_phys
+-#endif
+-};
+-
+-static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
+-{
+-      struct argon_mem_priv *priv;
+-      unsigned long pages;
+-
+-      priv = file->private_data;
+-      pages = priv->regs_phys >> PAGE_SHIFT;
+-      /*
+-       * The address decode is far larger than the actual number of registers.
+-       * Just map the whole lot in.
+-       */
+-      vma->vm_page_prot = phys_mem_access_prot(file, pages,
+-                                               priv->mem_window_len,
+-                                               vma->vm_page_prot);
+-      vma->vm_ops = &argon_mem_vm_ops;
+-      if (remap_pfn_range(vma, vma->vm_start,
+-                      pages,
+-                      priv->mem_window_len,
+-                      vma->vm_page_prot)) {
+-              return -EAGAIN;
+-      }
+-      return 0;
+-}
+-
+-static const struct file_operations
+-argon_mem_fops = {
+-      .owner = THIS_MODULE,
+-      .open = argon_mem_open,
+-      .release = argon_mem_release,
+-      .mmap = argon_mem_mmap,
+-};
+-
+-static const struct of_device_id argon_mem_of_match[];
+-static int argon_mem_probe(struct platform_device *pdev)
+-{
+-      int err;
+-      void *ptr_err;
+-      const struct of_device_id *id;
+-      struct device *dev = &pdev->dev;
+-      struct device *argon_mem_dev;
+-      struct resource *ioresource;
+-      struct argon_mem_priv *priv;
+-
+-
+-      /* Allocate buffers and instance data */
+-
+-      priv = kzalloc(sizeof(struct argon_mem_priv), GFP_KERNEL);
+-
+-      if (!priv) {
+-              err = -ENOMEM;
+-              goto failed_inst_alloc;
+-      }
+-      platform_set_drvdata(pdev, priv);
+-
+-      priv->dev = dev;
+-      id = of_match_device(argon_mem_of_match, dev);
+-      if (!id)
+-              return -EINVAL;
+-      priv->name = id->data;
+-
+-      ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      if (ioresource) {
+-              priv->regs_phys = ioresource->start;
+-              priv->mem_window_len = ioresource->end - ioresource->start;
+-      } else {
+-              dev_err(priv->dev, "failed to get IO resource");
+-              err = -ENOENT;
+-              goto failed_get_resource;
+-      }
+-
+-      /* Create character device entries */
+-
+-      err = alloc_chrdev_region(&priv->devid,
+-                                DEVICE_MINOR, 1, priv->name);
+-      if (err != 0) {
+-              dev_err(priv->dev, "unable to allocate device number");
+-              goto failed_alloc_chrdev;
+-      }
+-      cdev_init(&priv->argon_mem_cdev, &argon_mem_fops);
+-      priv->argon_mem_cdev.owner = THIS_MODULE;
+-      err = cdev_add(&priv->argon_mem_cdev, priv->devid, 1);
+-      if (err != 0) {
+-              dev_err(priv->dev, "unable to register device");
+-              goto failed_cdev_add;
+-      }
+-
+-      /* Create sysfs entries */
+-
+-      priv->class = class_create(THIS_MODULE, priv->name);
+-      ptr_err = priv->class;
+-      if (IS_ERR(ptr_err))
+-              goto failed_class_create;
+-
+-      argon_mem_dev = device_create(priv->class, NULL,
+-                                      priv->devid, NULL,
+-                                      priv->name);
+-      ptr_err = argon_mem_dev;
+-      if (IS_ERR(ptr_err))
+-              goto failed_device_create;
+-
+-      dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
+-              priv->name, priv->regs_phys, priv->mem_window_len);
+-
+-      return 0;
+-
+-failed_device_create:
+-      class_destroy(priv->class);
+-failed_class_create:
+-      cdev_del(&priv->argon_mem_cdev);
+-      err = PTR_ERR(ptr_err);
+-failed_cdev_add:
+-      unregister_chrdev_region(priv->devid, 1);
+-failed_alloc_chrdev:
+-failed_get_resource:
+-      kfree(priv);
+-failed_inst_alloc:
+-      dev_err(priv->dev, "could not load argon_mem");
+-      return err;
+-}
+-
+-static int argon_mem_remove(struct platform_device *pdev)
+-{
+-      struct device *dev = &pdev->dev;
+-      struct argon_mem_priv *priv = platform_get_drvdata(pdev);
+-
+-      device_destroy(priv->class, priv->devid);
+-      class_destroy(priv->class);
+-      cdev_del(&priv->argon_mem_cdev);
+-      unregister_chrdev_region(priv->devid, 1);
+-      kfree(priv);
+-
+-      dev_info(dev, "%s driver removed - OK", priv->name);
+-      return 0;
+-}
+-
+-static const char argon_hevc_name[] = "argon-hevcmem";
+-static const char argon_h264_name[] = "argon-h264mem";
+-static const char argon_vp9_name[] = "argon-vp9mem";
+-static const char argon_intc_name[] = "argon-intcmem";
+-
+-static const struct of_device_id argon_mem_of_match[] = {
+-      {
+-              .compatible = "raspberrypi,argon-hevc-decoder",
+-              .data = &argon_hevc_name,
+-      },
+-      {
+-              .compatible = "raspberrypi,argon-h264-decoder",
+-              .data = &argon_h264_name,
+-      },
+-      {
+-              .compatible = "raspberrypi,argon-vp9-decoder",
+-              .data = &argon_vp9_name,
+-      },
+-      /* The "intc" is included as this block of hardware contains the
+-       * "frame done" status flags.
+-       */
+-      {
+-              .compatible = "raspberrypi,argon-local-intc",
+-              .data = &argon_intc_name,
+-      },
+-      { /* sentinel */ },
+-};
+-
+-MODULE_DEVICE_TABLE(of, argon_mem_of_match);
+-
+-static struct platform_driver argon_mem_driver = {
+-      .probe = argon_mem_probe,
+-      .remove = argon_mem_remove,
+-      .driver = {
+-                 .name = DRIVER_NAME,
+-                 .owner = THIS_MODULE,
+-                 .of_match_table = argon_mem_of_match,
+-                 },
+-};
+-
+-module_platform_driver(argon_mem_driver);
+-
+-MODULE_ALIAS("platform:argon-mem");
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("Driver for accessing Argon decoder registers from userspace");
+-MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
+--- /dev/null
++++ b/drivers/char/broadcom/rpivid-mem.c
+@@ -0,0 +1,272 @@
++/**
++ * rpivid-mem.c - character device access to the RPiVid decoder registers
++ *
++ * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
++ * register blocks such that ffmpeg plugins can access the hardware.
++ *
++ * Jonathan Bell <jonathan@raspberrypi.org>
++ * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions, and the following disclaimer,
++ *    without modification.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The names of the above-listed copyright holders may not be used
++ *    to endorse or promote products derived from this software without
++ *    specific prior written permission.
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") version 2, as published by the Free
++ * Software Foundation.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
++ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
++ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/cdev.h>
++#include <linux/pagemap.h>
++#include <linux/io.h>
++
++#define DRIVER_NAME "rpivid-mem"
++#define DEVICE_MINOR 0
++
++struct rpivid_mem_priv {
++      dev_t devid;
++      struct class *class;
++      struct cdev rpivid_mem_cdev;
++      unsigned long regs_phys;
++      unsigned long mem_window_len;
++      struct device *dev;
++      const char *name;
++};
++
++static int rpivid_mem_open(struct inode *inode, struct file *file)
++{
++      int dev = iminor(inode);
++      int ret = 0;
++      struct rpivid_mem_priv *priv;
++      if (dev != DEVICE_MINOR)
++              ret = -ENXIO;
++
++      priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
++                              rpivid_mem_cdev);
++      if (!priv)
++              return -EINVAL;
++      file->private_data = priv;
++      return ret;
++}
++
++static int rpivid_mem_release(struct inode *inode, struct file *file)
++{
++      int dev = iminor(inode);
++      int ret = 0;
++
++      if (dev != DEVICE_MINOR)
++              ret = -ENXIO;
++
++      return ret;
++}
++
++static const struct vm_operations_struct rpivid_mem_vm_ops = {
++#ifdef CONFIG_HAVE_IOREMAP_PROT
++      .access = generic_access_phys
++#endif
++};
++
++static int rpivid_mem_mmap(struct file *file, struct vm_area_struct *vma)
++{
++      struct rpivid_mem_priv *priv;
++      unsigned long pages;
++
++      priv = file->private_data;
++      pages = priv->regs_phys >> PAGE_SHIFT;
++      /*
++       * The address decode is far larger than the actual number of registers.
++       * Just map the whole lot in.
++       */
++      vma->vm_page_prot = phys_mem_access_prot(file, pages,
++                                               priv->mem_window_len,
++                                               vma->vm_page_prot);
++      vma->vm_ops = &rpivid_mem_vm_ops;
++      if (remap_pfn_range(vma, vma->vm_start,
++                      pages,
++                      priv->mem_window_len,
++                      vma->vm_page_prot)) {
++              return -EAGAIN;
++      }
++      return 0;
++}
++
++static const struct file_operations
++rpivid_mem_fops = {
++      .owner = THIS_MODULE,
++      .open = rpivid_mem_open,
++      .release = rpivid_mem_release,
++      .mmap = rpivid_mem_mmap,
++};
++
++static const struct of_device_id rpivid_mem_of_match[];
++static int rpivid_mem_probe(struct platform_device *pdev)
++{
++      int err;
++      void *ptr_err;
++      const struct of_device_id *id;
++      struct device *dev = &pdev->dev;
++      struct device *rpivid_mem_dev;
++      struct resource *ioresource;
++      struct rpivid_mem_priv *priv;
++
++
++      /* Allocate buffers and instance data */
++
++      priv = kzalloc(sizeof(struct rpivid_mem_priv), GFP_KERNEL);
++
++      if (!priv) {
++              err = -ENOMEM;
++              goto failed_inst_alloc;
++      }
++      platform_set_drvdata(pdev, priv);
++
++      priv->dev = dev;
++      id = of_match_device(rpivid_mem_of_match, dev);
++      if (!id)
++              return -EINVAL;
++      priv->name = id->data;
++
++      ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (ioresource) {
++              priv->regs_phys = ioresource->start;
++              priv->mem_window_len = ioresource->end - ioresource->start;
++      } else {
++              dev_err(priv->dev, "failed to get IO resource");
++              err = -ENOENT;
++              goto failed_get_resource;
++      }
++
++      /* Create character device entries */
++
++      err = alloc_chrdev_region(&priv->devid,
++                                DEVICE_MINOR, 1, priv->name);
++      if (err != 0) {
++              dev_err(priv->dev, "unable to allocate device number");
++              goto failed_alloc_chrdev;
++      }
++      cdev_init(&priv->rpivid_mem_cdev, &rpivid_mem_fops);
++      priv->rpivid_mem_cdev.owner = THIS_MODULE;
++      err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 1);
++      if (err != 0) {
++              dev_err(priv->dev, "unable to register device");
++              goto failed_cdev_add;
++      }
++
++      /* Create sysfs entries */
++
++      priv->class = class_create(THIS_MODULE, priv->name);
++      ptr_err = priv->class;
++      if (IS_ERR(ptr_err))
++              goto failed_class_create;
++
++      rpivid_mem_dev = device_create(priv->class, NULL,
++                                      priv->devid, NULL,
++                                      priv->name);
++      ptr_err = rpivid_mem_dev;
++      if (IS_ERR(ptr_err))
++              goto failed_device_create;
++
++      dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
++              priv->name, priv->regs_phys, priv->mem_window_len);
++
++      return 0;
++
++failed_device_create:
++      class_destroy(priv->class);
++failed_class_create:
++      cdev_del(&priv->rpivid_mem_cdev);
++      err = PTR_ERR(ptr_err);
++failed_cdev_add:
++      unregister_chrdev_region(priv->devid, 1);
++failed_alloc_chrdev:
++failed_get_resource:
++      kfree(priv);
++failed_inst_alloc:
++      dev_err(priv->dev, "could not load rpivid_mem");
++      return err;
++}
++
++static int rpivid_mem_remove(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct rpivid_mem_priv *priv = platform_get_drvdata(pdev);
++
++      device_destroy(priv->class, priv->devid);
++      class_destroy(priv->class);
++      cdev_del(&priv->rpivid_mem_cdev);
++      unregister_chrdev_region(priv->devid, 1);
++      kfree(priv);
++
++      dev_info(dev, "%s driver removed - OK", priv->name);
++      return 0;
++}
++
++static const struct of_device_id rpivid_mem_of_match[] = {
++      {
++              .compatible = "raspberrypi,rpivid-hevc-decoder",
++              .data = "rpivid-hevcmem",
++      },
++      {
++              .compatible = "raspberrypi,rpivid-h264-decoder",
++              .data = "rpivid-h264mem",
++      },
++      {
++              .compatible = "raspberrypi,rpivid-vp9-decoder",
++              .data = "rpivid-vp9mem",
++      },
++      /* The "intc" is included as this block of hardware contains the
++       * "frame done" status flags.
++       */
++      {
++              .compatible = "raspberrypi,rpivid-local-intc",
++              .data = "rpivid-intcmem",
++      },
++      { /* sentinel */ },
++};
++
++MODULE_DEVICE_TABLE(of, rpivid_mem_of_match);
++
++static struct platform_driver rpivid_mem_driver = {
++      .probe = rpivid_mem_probe,
++      .remove = rpivid_mem_remove,
++      .driver = {
++                 .name = DRIVER_NAME,
++                 .owner = THIS_MODULE,
++                 .of_match_table = rpivid_mem_of_match,
++                 },
++};
++
++module_platform_driver(rpivid_mem_driver);
++
++MODULE_ALIAS("platform:rpivid-mem");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Driver for accessing RPiVid decoder registers from userspace");
++MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
+--- a/drivers/mfd/bcm2835-pm.c
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -50,14 +50,14 @@ static int bcm2835_pm_probe(struct platf
+       if (ret)
+               return ret;
+-      /* Map the ARGON ASB regs if present. */
++      /* Map the RPiVid ASB regs if present. */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       if (res) {
+-              pm->arg_asb = devm_ioremap_resource(dev, res);
+-              if (IS_ERR(pm->arg_asb)) {
+-                      dev_err(dev, "Failed to map ARGON ASB: %ld\n",
+-                              PTR_ERR(pm->arg_asb));
+-                      return PTR_ERR(pm->arg_asb);
++              pm->rpivid_asb = devm_ioremap_resource(dev, res);
++              if (IS_ERR(pm->rpivid_asb)) {
++                      dev_err(dev, "Failed to map RPiVid ASB: %ld\n",
++                              PTR_ERR(pm->rpivid_asb));
++                      return PTR_ERR(pm->rpivid_asb);
+               }
+       }
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -637,15 +637,15 @@ static int bcm2835_power_probe(struct pl
+       power->base = pm->base;
+       power->asb = pm->asb;
+-      /* 2711 hack: the new ARGON ASB took over V3D, which is our
++      /* 2711 hack: the new RPiVid ASB took over V3D, which is our
+        * only consumer of this driver so far.  The old ASB seems to
+        * still be present with ISP and H264 bits but no V3D, but I
+        * don't know if that's real or not.  The V3D is in the same
+        * place in the new ASB as the old one, so just poke the new
+        * one for now.
+        */
+-      if (pm->arg_asb) {
+-              power->asb = pm->arg_asb;
++      if (pm->rpivid_asb) {
++              power->asb = pm->rpivid_asb;
+               power->is_2711 = true;
+       }
+--- a/include/linux/mfd/bcm2835-pm.h
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -9,7 +9,7 @@ struct bcm2835_pm {
+       struct device *dev;
+       void __iomem *base;
+       void __iomem *asb;
+-      void __iomem *arg_asb;
++      void __iomem *rpivid_asb;
+ };
+ #endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0634-overlays-Update-the-upstream-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0634-overlays-Update-the-upstream-overlay.patch
deleted file mode 100644 (file)
index 6cec814..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From a14162d8da62fb570df916d7386febe51d6ed2bc Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 31 Jul 2019 17:41:47 +0100
-Subject: [PATCH] overlays: Update the upstream overlay
-
-The recent vc4-kms-v3d commit has changed the content of the
-upstream overlay (even though the extra fragment is disabled).
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/upstream-overlay.dts | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -110,6 +110,12 @@
-               };
-       };
-       fragment@17 {
-+              target = <&hdmi>;
-+              __dormant__ {
-+                      dmas;
-+              };
-+      };
-+      fragment@18 {
-               target = <&usb>;
-               #address-cells = <1>;
-               #size-cells = <1>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0635-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch b/target/linux/brcm2708/patches-4.19/950-0635-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch
deleted file mode 100644 (file)
index 2626658..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From c2957d7709a43c81e5345d537feaa6980ffcc1a4 Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Mon, 29 Jul 2019 12:02:59 +0100
-Subject: [PATCH] Fixup FKMS interrupt handing for non-existent display
-
-If an errant interrupt flag was received from a non-existent display,
-a NULL pointer access was made. Protect against this by checking if a
-second display is present prior to checking the interrupt flags.
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 17 ++++++++++-------
- 1 file changed, 10 insertions(+), 7 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1056,14 +1056,17 @@ static irqreturn_t vc4_crtc_irq_handler(
-                               vc4_crtc_handle_page_flip(crtc_list[0]);
-                       }
--                      /* Check for the secondary display too */
--                      chan = readl(crtc_list[0]->regs + SMIDSW1);
-+                      if (crtc_list[1]) {
-+                              /* Check for the secondary display too */
-+                              chan = readl(crtc_list[0]->regs + SMIDSW1);
--                      if (chan & 1) {
--                              writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
--                              if (crtc_list[1]->vblank_enabled)
--                                      drm_crtc_handle_vblank(&crtc_list[1]->base);
--                              vc4_crtc_handle_page_flip(crtc_list[1]);
-+                              if (chan & 1) {
-+                                      writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
-+
-+                                      if (crtc_list[1]->vblank_enabled)
-+                                              drm_crtc_handle_vblank(&crtc_list[1]->base);
-+                                      vc4_crtc_handle_page_flip(crtc_list[1]);
-+                              }
-                       }
-               }
diff --git a/target/linux/brcm2708/patches-4.19/950-0635-driver-char-rpivid-also-support-legacy-name.patch b/target/linux/brcm2708/patches-4.19/950-0635-driver-char-rpivid-also-support-legacy-name.patch
new file mode 100644 (file)
index 0000000..34dd242
--- /dev/null
@@ -0,0 +1,71 @@
+From 80c20ff00542b050733780ae6088e50663ee8d78 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 29 Jul 2019 12:03:21 +0100
+Subject: [PATCH] driver: char: rpivid - also support legacy name
+
+Provide transitional support for the previous names of
+the character devices.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/char/broadcom/rpivid-mem.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+--- a/drivers/char/broadcom/rpivid-mem.c
++++ b/drivers/char/broadcom/rpivid-mem.c
+@@ -66,7 +66,7 @@ static int rpivid_mem_open(struct inode
+       int dev = iminor(inode);
+       int ret = 0;
+       struct rpivid_mem_priv *priv;
+-      if (dev != DEVICE_MINOR)
++      if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
+               ret = -ENXIO;
+       priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
+@@ -82,7 +82,7 @@ static int rpivid_mem_release(struct ino
+       int dev = iminor(inode);
+       int ret = 0;
+-      if (dev != DEVICE_MINOR)
++      if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
+               ret = -ENXIO;
+       return ret;
+@@ -167,14 +167,14 @@ static int rpivid_mem_probe(struct platf
+       /* Create character device entries */
+       err = alloc_chrdev_region(&priv->devid,
+-                                DEVICE_MINOR, 1, priv->name);
++                                DEVICE_MINOR, 2, priv->name);
+       if (err != 0) {
+               dev_err(priv->dev, "unable to allocate device number");
+               goto failed_alloc_chrdev;
+       }
+       cdev_init(&priv->rpivid_mem_cdev, &rpivid_mem_fops);
+       priv->rpivid_mem_cdev.owner = THIS_MODULE;
+-      err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 1);
++      err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 2);
+       if (err != 0) {
+               dev_err(priv->dev, "unable to register device");
+               goto failed_cdev_add;
+@@ -194,6 +194,20 @@ static int rpivid_mem_probe(struct platf
+       if (IS_ERR(ptr_err))
+               goto failed_device_create;
++      /* Legacy alias */
++      {
++              char *oldname = kstrdup(priv->name, GFP_KERNEL);
++
++              oldname[1] = 'a';
++              oldname[2] = 'r';
++              oldname[3] = 'g';
++              oldname[4] = 'o';
++              oldname[5] = 'n';
++              (void)device_create(priv->class, NULL, priv->devid + 1, NULL,
++                                     oldname + 1);
++              kfree(oldname);
++      }
++
+       dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
+               priv->name, priv->regs_phys, priv->mem_window_len);
diff --git a/target/linux/brcm2708/patches-4.19/950-0636-drivers-char-Use-correct-name-for-the-Raspberry-Pi-v.patch b/target/linux/brcm2708/patches-4.19/950-0636-drivers-char-Use-correct-name-for-the-Raspberry-Pi-v.patch
deleted file mode 100644 (file)
index 92ecf12..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-From 6c8c9ca56ce6039ade09d26c069132538e4de9f0 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Sun, 28 Jul 2019 22:22:36 +0100
-Subject: [PATCH] drivers: char: Use correct name for the Raspberry Pi
- video decoder
-
-Replace the old code name with a more appropriate name - RPiVid.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2838.dtsi                |  10 +-
- drivers/char/broadcom/Kconfig                 |   8 +-
- drivers/char/broadcom/Makefile                |   2 +-
- .../broadcom/{argon-mem.c => rpivid-mem.c}    | 105 +++++++++---------
- drivers/mfd/bcm2835-pm.c                      |  12 +-
- drivers/soc/bcm/bcm2835-power.c               |   6 +-
- include/linux/mfd/bcm2835-pm.h                |   2 +-
- 8 files changed, 71 insertions(+), 76 deletions(-)
- rename drivers/char/broadcom/{argon-mem.c => rpivid-mem.c} (69%)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -409,26 +409,26 @@
-               };
-               hevc-decoder@7eb00000 {
--                      compatible = "raspberrypi,argon-hevc-decoder";
-+                      compatible = "raspberrypi,rpivid-hevc-decoder";
-                       reg = <0x0 0x7eb00000 0x10000>;
-                       status = "okay";
-               };
--              argon-local-intc@7eb10000 {
--                      compatible = "raspberrypi,argon-local-intc";
-+              rpivid-local-intc@7eb10000 {
-+                      compatible = "raspberrypi,rpivid-local-intc";
-                       reg = <0x0 0x7eb10000 0x1000>;
-                       status = "okay";
-                       interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
-               };
-               h264-decoder@7eb20000 {
--                      compatible = "raspberrypi,argon-h264-decoder";
-+                      compatible = "raspberrypi,rpivid-h264-decoder";
-                       reg = <0x0 0x7eb20000 0x10000>;
-                       status = "okay";
-               };
-               vp9-decoder@7eb30000 {
--                      compatible = "raspberrypi,argon-vp9-decoder";
-+                      compatible = "raspberrypi,rpivid-vp9-decoder";
-                       reg = <0x0 0x7eb30000 0x10000>;
-                       status = "okay";
-               };
---- a/drivers/char/broadcom/Kconfig
-+++ b/drivers/char/broadcom/Kconfig
-@@ -50,10 +50,10 @@ config BCM2835_SMI_DEV
-               Broadcom's Secondary Memory interface. The low-level functionality is provided
-               by the SMI driver itself.
--config ARGON_MEM
--      tristate "Character device driver for the Argon decoder hardware"
-+config RPIVID_MEM
-+      tristate "Character device driver for the Raspberry Pi RPIVid video decoder hardware"
-       default n
-       help
-               This driver provides a character device interface for memory-map operations
--              so userspace tools can access the control and status registers of the Argon
--              video decoder hardware.
-+              so userspace tools can access the control and status registers of the
-+              Raspberry Pi RPiVid video decoder hardware.
---- a/drivers/char/broadcom/Makefile
-+++ b/drivers/char/broadcom/Makefile
-@@ -4,4 +4,4 @@ obj-$(CONFIG_BCM_VC_SM)         += vc_sm
- obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
- obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o
--obj-$(CONFIG_ARGON_MEM)               += argon-mem.o
-+obj-$(CONFIG_RPIVID_MEM)      += rpivid-mem.o
---- a/drivers/char/broadcom/argon-mem.c
-+++ /dev/null
-@@ -1,277 +0,0 @@
--/**
-- * argon-mem.c - character device access to the Argon decoder registers
-- *
-- * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
-- * register blocks such that ffmpeg plugins can access the hardware.
-- *
-- * Jonathan Bell <jonathan@raspberrypi.org>
-- * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
-- *
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met:
-- * 1. Redistributions of source code must retain the above copyright
-- *    notice, this list of conditions, and the following disclaimer,
-- *    without modification.
-- * 2. Redistributions in binary form must reproduce the above copyright
-- *    notice, this list of conditions and the following disclaimer in the
-- *    documentation and/or other materials provided with the distribution.
-- * 3. The names of the above-listed copyright holders may not be used
-- *    to endorse or promote products derived from this software without
-- *    specific prior written permission.
-- *
-- * ALTERNATIVELY, this software may be distributed under the terms of the
-- * GNU General Public License ("GPL") version 2, as published by the Free
-- * Software Foundation.
-- *
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- */
--
--#include <linux/kernel.h>
--#include <linux/module.h>
--#include <linux/of.h>
--#include <linux/of_device.h>
--#include <linux/platform_device.h>
--#include <linux/mm.h>
--#include <linux/slab.h>
--#include <linux/cdev.h>
--#include <linux/pagemap.h>
--#include <linux/io.h>
--
--#define DRIVER_NAME "argon-mem"
--#define DEVICE_MINOR 0
--
--struct argon_mem_priv {
--      dev_t devid;
--      struct class *class;
--      struct cdev argon_mem_cdev;
--      unsigned long regs_phys;
--      unsigned long mem_window_len;
--      struct device *dev;
--      const char *name;
--};
--
--static int argon_mem_open(struct inode *inode, struct file *file)
--{
--      int dev = iminor(inode);
--      int ret = 0;
--      struct argon_mem_priv *priv;
--      if (dev != DEVICE_MINOR)
--              ret = -ENXIO;
--
--      priv = container_of(inode->i_cdev, struct argon_mem_priv,
--                              argon_mem_cdev);
--      if (!priv)
--              return -EINVAL;
--      file->private_data = priv;
--      return ret;
--}
--
--static int argon_mem_release(struct inode *inode, struct file *file)
--{
--      int dev = iminor(inode);
--      int ret = 0;
--
--      if (dev != DEVICE_MINOR)
--              ret = -ENXIO;
--
--      return ret;
--}
--
--static const struct vm_operations_struct argon_mem_vm_ops = {
--#ifdef CONFIG_HAVE_IOREMAP_PROT
--      .access = generic_access_phys
--#endif
--};
--
--static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
--{
--      struct argon_mem_priv *priv;
--      unsigned long pages;
--
--      priv = file->private_data;
--      pages = priv->regs_phys >> PAGE_SHIFT;
--      /*
--       * The address decode is far larger than the actual number of registers.
--       * Just map the whole lot in.
--       */
--      vma->vm_page_prot = phys_mem_access_prot(file, pages,
--                                               priv->mem_window_len,
--                                               vma->vm_page_prot);
--      vma->vm_ops = &argon_mem_vm_ops;
--      if (remap_pfn_range(vma, vma->vm_start,
--                      pages,
--                      priv->mem_window_len,
--                      vma->vm_page_prot)) {
--              return -EAGAIN;
--      }
--      return 0;
--}
--
--static const struct file_operations
--argon_mem_fops = {
--      .owner = THIS_MODULE,
--      .open = argon_mem_open,
--      .release = argon_mem_release,
--      .mmap = argon_mem_mmap,
--};
--
--static const struct of_device_id argon_mem_of_match[];
--static int argon_mem_probe(struct platform_device *pdev)
--{
--      int err;
--      void *ptr_err;
--      const struct of_device_id *id;
--      struct device *dev = &pdev->dev;
--      struct device *argon_mem_dev;
--      struct resource *ioresource;
--      struct argon_mem_priv *priv;
--
--
--      /* Allocate buffers and instance data */
--
--      priv = kzalloc(sizeof(struct argon_mem_priv), GFP_KERNEL);
--
--      if (!priv) {
--              err = -ENOMEM;
--              goto failed_inst_alloc;
--      }
--      platform_set_drvdata(pdev, priv);
--
--      priv->dev = dev;
--      id = of_match_device(argon_mem_of_match, dev);
--      if (!id)
--              return -EINVAL;
--      priv->name = id->data;
--
--      ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--      if (ioresource) {
--              priv->regs_phys = ioresource->start;
--              priv->mem_window_len = ioresource->end - ioresource->start;
--      } else {
--              dev_err(priv->dev, "failed to get IO resource");
--              err = -ENOENT;
--              goto failed_get_resource;
--      }
--
--      /* Create character device entries */
--
--      err = alloc_chrdev_region(&priv->devid,
--                                DEVICE_MINOR, 1, priv->name);
--      if (err != 0) {
--              dev_err(priv->dev, "unable to allocate device number");
--              goto failed_alloc_chrdev;
--      }
--      cdev_init(&priv->argon_mem_cdev, &argon_mem_fops);
--      priv->argon_mem_cdev.owner = THIS_MODULE;
--      err = cdev_add(&priv->argon_mem_cdev, priv->devid, 1);
--      if (err != 0) {
--              dev_err(priv->dev, "unable to register device");
--              goto failed_cdev_add;
--      }
--
--      /* Create sysfs entries */
--
--      priv->class = class_create(THIS_MODULE, priv->name);
--      ptr_err = priv->class;
--      if (IS_ERR(ptr_err))
--              goto failed_class_create;
--
--      argon_mem_dev = device_create(priv->class, NULL,
--                                      priv->devid, NULL,
--                                      priv->name);
--      ptr_err = argon_mem_dev;
--      if (IS_ERR(ptr_err))
--              goto failed_device_create;
--
--      dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
--              priv->name, priv->regs_phys, priv->mem_window_len);
--
--      return 0;
--
--failed_device_create:
--      class_destroy(priv->class);
--failed_class_create:
--      cdev_del(&priv->argon_mem_cdev);
--      err = PTR_ERR(ptr_err);
--failed_cdev_add:
--      unregister_chrdev_region(priv->devid, 1);
--failed_alloc_chrdev:
--failed_get_resource:
--      kfree(priv);
--failed_inst_alloc:
--      dev_err(priv->dev, "could not load argon_mem");
--      return err;
--}
--
--static int argon_mem_remove(struct platform_device *pdev)
--{
--      struct device *dev = &pdev->dev;
--      struct argon_mem_priv *priv = platform_get_drvdata(pdev);
--
--      device_destroy(priv->class, priv->devid);
--      class_destroy(priv->class);
--      cdev_del(&priv->argon_mem_cdev);
--      unregister_chrdev_region(priv->devid, 1);
--      kfree(priv);
--
--      dev_info(dev, "%s driver removed - OK", priv->name);
--      return 0;
--}
--
--static const char argon_hevc_name[] = "argon-hevcmem";
--static const char argon_h264_name[] = "argon-h264mem";
--static const char argon_vp9_name[] = "argon-vp9mem";
--static const char argon_intc_name[] = "argon-intcmem";
--
--static const struct of_device_id argon_mem_of_match[] = {
--      {
--              .compatible = "raspberrypi,argon-hevc-decoder",
--              .data = &argon_hevc_name,
--      },
--      {
--              .compatible = "raspberrypi,argon-h264-decoder",
--              .data = &argon_h264_name,
--      },
--      {
--              .compatible = "raspberrypi,argon-vp9-decoder",
--              .data = &argon_vp9_name,
--      },
--      /* The "intc" is included as this block of hardware contains the
--       * "frame done" status flags.
--       */
--      {
--              .compatible = "raspberrypi,argon-local-intc",
--              .data = &argon_intc_name,
--      },
--      { /* sentinel */ },
--};
--
--MODULE_DEVICE_TABLE(of, argon_mem_of_match);
--
--static struct platform_driver argon_mem_driver = {
--      .probe = argon_mem_probe,
--      .remove = argon_mem_remove,
--      .driver = {
--                 .name = DRIVER_NAME,
--                 .owner = THIS_MODULE,
--                 .of_match_table = argon_mem_of_match,
--                 },
--};
--
--module_platform_driver(argon_mem_driver);
--
--MODULE_ALIAS("platform:argon-mem");
--MODULE_LICENSE("GPL");
--MODULE_DESCRIPTION("Driver for accessing Argon decoder registers from userspace");
--MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
---- /dev/null
-+++ b/drivers/char/broadcom/rpivid-mem.c
-@@ -0,0 +1,272 @@
-+/**
-+ * rpivid-mem.c - character device access to the RPiVid decoder registers
-+ *
-+ * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
-+ * register blocks such that ffmpeg plugins can access the hardware.
-+ *
-+ * Jonathan Bell <jonathan@raspberrypi.org>
-+ * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions, and the following disclaimer,
-+ *    without modification.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 3. The names of the above-listed copyright holders may not be used
-+ *    to endorse or promote products derived from this software without
-+ *    specific prior written permission.
-+ *
-+ * ALTERNATIVELY, this software may be distributed under the terms of the
-+ * GNU General Public License ("GPL") version 2, as published by the Free
-+ * Software Foundation.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/cdev.h>
-+#include <linux/pagemap.h>
-+#include <linux/io.h>
-+
-+#define DRIVER_NAME "rpivid-mem"
-+#define DEVICE_MINOR 0
-+
-+struct rpivid_mem_priv {
-+      dev_t devid;
-+      struct class *class;
-+      struct cdev rpivid_mem_cdev;
-+      unsigned long regs_phys;
-+      unsigned long mem_window_len;
-+      struct device *dev;
-+      const char *name;
-+};
-+
-+static int rpivid_mem_open(struct inode *inode, struct file *file)
-+{
-+      int dev = iminor(inode);
-+      int ret = 0;
-+      struct rpivid_mem_priv *priv;
-+      if (dev != DEVICE_MINOR)
-+              ret = -ENXIO;
-+
-+      priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
-+                              rpivid_mem_cdev);
-+      if (!priv)
-+              return -EINVAL;
-+      file->private_data = priv;
-+      return ret;
-+}
-+
-+static int rpivid_mem_release(struct inode *inode, struct file *file)
-+{
-+      int dev = iminor(inode);
-+      int ret = 0;
-+
-+      if (dev != DEVICE_MINOR)
-+              ret = -ENXIO;
-+
-+      return ret;
-+}
-+
-+static const struct vm_operations_struct rpivid_mem_vm_ops = {
-+#ifdef CONFIG_HAVE_IOREMAP_PROT
-+      .access = generic_access_phys
-+#endif
-+};
-+
-+static int rpivid_mem_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+      struct rpivid_mem_priv *priv;
-+      unsigned long pages;
-+
-+      priv = file->private_data;
-+      pages = priv->regs_phys >> PAGE_SHIFT;
-+      /*
-+       * The address decode is far larger than the actual number of registers.
-+       * Just map the whole lot in.
-+       */
-+      vma->vm_page_prot = phys_mem_access_prot(file, pages,
-+                                               priv->mem_window_len,
-+                                               vma->vm_page_prot);
-+      vma->vm_ops = &rpivid_mem_vm_ops;
-+      if (remap_pfn_range(vma, vma->vm_start,
-+                      pages,
-+                      priv->mem_window_len,
-+                      vma->vm_page_prot)) {
-+              return -EAGAIN;
-+      }
-+      return 0;
-+}
-+
-+static const struct file_operations
-+rpivid_mem_fops = {
-+      .owner = THIS_MODULE,
-+      .open = rpivid_mem_open,
-+      .release = rpivid_mem_release,
-+      .mmap = rpivid_mem_mmap,
-+};
-+
-+static const struct of_device_id rpivid_mem_of_match[];
-+static int rpivid_mem_probe(struct platform_device *pdev)
-+{
-+      int err;
-+      void *ptr_err;
-+      const struct of_device_id *id;
-+      struct device *dev = &pdev->dev;
-+      struct device *rpivid_mem_dev;
-+      struct resource *ioresource;
-+      struct rpivid_mem_priv *priv;
-+
-+
-+      /* Allocate buffers and instance data */
-+
-+      priv = kzalloc(sizeof(struct rpivid_mem_priv), GFP_KERNEL);
-+
-+      if (!priv) {
-+              err = -ENOMEM;
-+              goto failed_inst_alloc;
-+      }
-+      platform_set_drvdata(pdev, priv);
-+
-+      priv->dev = dev;
-+      id = of_match_device(rpivid_mem_of_match, dev);
-+      if (!id)
-+              return -EINVAL;
-+      priv->name = id->data;
-+
-+      ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (ioresource) {
-+              priv->regs_phys = ioresource->start;
-+              priv->mem_window_len = ioresource->end - ioresource->start;
-+      } else {
-+              dev_err(priv->dev, "failed to get IO resource");
-+              err = -ENOENT;
-+              goto failed_get_resource;
-+      }
-+
-+      /* Create character device entries */
-+
-+      err = alloc_chrdev_region(&priv->devid,
-+                                DEVICE_MINOR, 1, priv->name);
-+      if (err != 0) {
-+              dev_err(priv->dev, "unable to allocate device number");
-+              goto failed_alloc_chrdev;
-+      }
-+      cdev_init(&priv->rpivid_mem_cdev, &rpivid_mem_fops);
-+      priv->rpivid_mem_cdev.owner = THIS_MODULE;
-+      err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 1);
-+      if (err != 0) {
-+              dev_err(priv->dev, "unable to register device");
-+              goto failed_cdev_add;
-+      }
-+
-+      /* Create sysfs entries */
-+
-+      priv->class = class_create(THIS_MODULE, priv->name);
-+      ptr_err = priv->class;
-+      if (IS_ERR(ptr_err))
-+              goto failed_class_create;
-+
-+      rpivid_mem_dev = device_create(priv->class, NULL,
-+                                      priv->devid, NULL,
-+                                      priv->name);
-+      ptr_err = rpivid_mem_dev;
-+      if (IS_ERR(ptr_err))
-+              goto failed_device_create;
-+
-+      dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
-+              priv->name, priv->regs_phys, priv->mem_window_len);
-+
-+      return 0;
-+
-+failed_device_create:
-+      class_destroy(priv->class);
-+failed_class_create:
-+      cdev_del(&priv->rpivid_mem_cdev);
-+      err = PTR_ERR(ptr_err);
-+failed_cdev_add:
-+      unregister_chrdev_region(priv->devid, 1);
-+failed_alloc_chrdev:
-+failed_get_resource:
-+      kfree(priv);
-+failed_inst_alloc:
-+      dev_err(priv->dev, "could not load rpivid_mem");
-+      return err;
-+}
-+
-+static int rpivid_mem_remove(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct rpivid_mem_priv *priv = platform_get_drvdata(pdev);
-+
-+      device_destroy(priv->class, priv->devid);
-+      class_destroy(priv->class);
-+      cdev_del(&priv->rpivid_mem_cdev);
-+      unregister_chrdev_region(priv->devid, 1);
-+      kfree(priv);
-+
-+      dev_info(dev, "%s driver removed - OK", priv->name);
-+      return 0;
-+}
-+
-+static const struct of_device_id rpivid_mem_of_match[] = {
-+      {
-+              .compatible = "raspberrypi,rpivid-hevc-decoder",
-+              .data = "rpivid-hevcmem",
-+      },
-+      {
-+              .compatible = "raspberrypi,rpivid-h264-decoder",
-+              .data = "rpivid-h264mem",
-+      },
-+      {
-+              .compatible = "raspberrypi,rpivid-vp9-decoder",
-+              .data = "rpivid-vp9mem",
-+      },
-+      /* The "intc" is included as this block of hardware contains the
-+       * "frame done" status flags.
-+       */
-+      {
-+              .compatible = "raspberrypi,rpivid-local-intc",
-+              .data = "rpivid-intcmem",
-+      },
-+      { /* sentinel */ },
-+};
-+
-+MODULE_DEVICE_TABLE(of, rpivid_mem_of_match);
-+
-+static struct platform_driver rpivid_mem_driver = {
-+      .probe = rpivid_mem_probe,
-+      .remove = rpivid_mem_remove,
-+      .driver = {
-+                 .name = DRIVER_NAME,
-+                 .owner = THIS_MODULE,
-+                 .of_match_table = rpivid_mem_of_match,
-+                 },
-+};
-+
-+module_platform_driver(rpivid_mem_driver);
-+
-+MODULE_ALIAS("platform:rpivid-mem");
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Driver for accessing RPiVid decoder registers from userspace");
-+MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
---- a/drivers/mfd/bcm2835-pm.c
-+++ b/drivers/mfd/bcm2835-pm.c
-@@ -50,14 +50,14 @@ static int bcm2835_pm_probe(struct platf
-       if (ret)
-               return ret;
--      /* Map the ARGON ASB regs if present. */
-+      /* Map the RPiVid ASB regs if present. */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-       if (res) {
--              pm->arg_asb = devm_ioremap_resource(dev, res);
--              if (IS_ERR(pm->arg_asb)) {
--                      dev_err(dev, "Failed to map ARGON ASB: %ld\n",
--                              PTR_ERR(pm->arg_asb));
--                      return PTR_ERR(pm->arg_asb);
-+              pm->rpivid_asb = devm_ioremap_resource(dev, res);
-+              if (IS_ERR(pm->rpivid_asb)) {
-+                      dev_err(dev, "Failed to map RPiVid ASB: %ld\n",
-+                              PTR_ERR(pm->rpivid_asb));
-+                      return PTR_ERR(pm->rpivid_asb);
-               }
-       }
---- a/drivers/soc/bcm/bcm2835-power.c
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -637,15 +637,15 @@ static int bcm2835_power_probe(struct pl
-       power->base = pm->base;
-       power->asb = pm->asb;
--      /* 2711 hack: the new ARGON ASB took over V3D, which is our
-+      /* 2711 hack: the new RPiVid ASB took over V3D, which is our
-        * only consumer of this driver so far.  The old ASB seems to
-        * still be present with ISP and H264 bits but no V3D, but I
-        * don't know if that's real or not.  The V3D is in the same
-        * place in the new ASB as the old one, so just poke the new
-        * one for now.
-        */
--      if (pm->arg_asb) {
--              power->asb = pm->arg_asb;
-+      if (pm->rpivid_asb) {
-+              power->asb = pm->rpivid_asb;
-               power->is_2711 = true;
-       }
---- a/include/linux/mfd/bcm2835-pm.h
-+++ b/include/linux/mfd/bcm2835-pm.h
-@@ -9,7 +9,7 @@ struct bcm2835_pm {
-       struct device *dev;
-       void __iomem *base;
-       void __iomem *asb;
--      void __iomem *arg_asb;
-+      void __iomem *rpivid_asb;
- };
- #endif /* BCM2835_MFD_PM_H */
diff --git a/target/linux/brcm2708/patches-4.19/950-0636-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch b/target/linux/brcm2708/patches-4.19/950-0636-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch
new file mode 100644 (file)
index 0000000..c0a7af1
--- /dev/null
@@ -0,0 +1,63 @@
+From 16c1e20b50e121f836f434bb6c22c73e2f51d29f Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 1 Aug 2019 16:41:20 +0100
+Subject: [PATCH] hid: usb: Add device quirks for Freeway Airmouse T3
+ and MX3
+
+These wireless mouse/keyboard combo remote control devices specify
+multiple "wheel" events in their report descriptors. The wheel events
+are incorrectly defined and apparently map to accelerometer data, leading
+to spurious mouse scroll events being generated at an extreme rate when
+the device is moved.
+
+As a workaround, use HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE to mask
+feeding the extra wheel events to the input subsystem.
+
+See: https://github.com/raspberrypi/firmware/issues/1189
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/hid/hid-ids.h    | 6 ++++++
+ drivers/hid/hid-quirks.c | 2 ++
+ 2 files changed, 8 insertions(+)
+
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -222,6 +222,9 @@
+ #define USB_VENDOR_ID_BAANTO          0x2453
+ #define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100
++#define USB_VENDOR_ID_BEKEN           0x25a7
++#define USB_DEVICE_ID_AIRMOUSE_T3     0x2402
++
+ #define USB_VENDOR_ID_BELKIN          0x050d
+ #define USB_DEVICE_ID_FLIP_KVM                0x3201
+@@ -1196,6 +1199,9 @@
+ #define USB_VENDOR_ID_XAT     0x2505
+ #define USB_DEVICE_ID_XAT_CSR 0x0220
++#define USB_VENDOR_ID_XENTA                   0x1d57
++#define USB_DEVICE_ID_AIRMOUSE_MX3            0xad03
++
+ #define USB_VENDOR_ID_XIN_MO                  0x16c0
+ #define USB_DEVICE_ID_XIN_MO_DUAL_ARCADE      0x05e1
+ #define USB_DEVICE_ID_THT_2P_ARCADE           0x75e1
+--- a/drivers/hid/hid-quirks.c
++++ b/drivers/hid/hid-quirks.c
+@@ -43,6 +43,7 @@ static const struct hid_device_id hid_qu
+       { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET },
++      { HID_USB_DEVICE(USB_VENDOR_ID_BEKEN, USB_DEVICE_ID_AIRMOUSE_T3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL },
+@@ -175,6 +176,7 @@ static const struct hid_device_id hid_qu
+       { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
++      { HID_USB_DEVICE(USB_VENDOR_ID_XENTA, USB_DEVICE_ID_AIRMOUSE_MX3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT },
+       { 0 }
diff --git a/target/linux/brcm2708/patches-4.19/950-0637-driver-char-rpivid-also-support-legacy-name.patch b/target/linux/brcm2708/patches-4.19/950-0637-driver-char-rpivid-also-support-legacy-name.patch
deleted file mode 100644 (file)
index 34dd242..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-From 80c20ff00542b050733780ae6088e50663ee8d78 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 29 Jul 2019 12:03:21 +0100
-Subject: [PATCH] driver: char: rpivid - also support legacy name
-
-Provide transitional support for the previous names of
-the character devices.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/char/broadcom/rpivid-mem.c | 22 ++++++++++++++++++----
- 1 file changed, 18 insertions(+), 4 deletions(-)
-
---- a/drivers/char/broadcom/rpivid-mem.c
-+++ b/drivers/char/broadcom/rpivid-mem.c
-@@ -66,7 +66,7 @@ static int rpivid_mem_open(struct inode
-       int dev = iminor(inode);
-       int ret = 0;
-       struct rpivid_mem_priv *priv;
--      if (dev != DEVICE_MINOR)
-+      if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
-               ret = -ENXIO;
-       priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
-@@ -82,7 +82,7 @@ static int rpivid_mem_release(struct ino
-       int dev = iminor(inode);
-       int ret = 0;
--      if (dev != DEVICE_MINOR)
-+      if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
-               ret = -ENXIO;
-       return ret;
-@@ -167,14 +167,14 @@ static int rpivid_mem_probe(struct platf
-       /* Create character device entries */
-       err = alloc_chrdev_region(&priv->devid,
--                                DEVICE_MINOR, 1, priv->name);
-+                                DEVICE_MINOR, 2, priv->name);
-       if (err != 0) {
-               dev_err(priv->dev, "unable to allocate device number");
-               goto failed_alloc_chrdev;
-       }
-       cdev_init(&priv->rpivid_mem_cdev, &rpivid_mem_fops);
-       priv->rpivid_mem_cdev.owner = THIS_MODULE;
--      err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 1);
-+      err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 2);
-       if (err != 0) {
-               dev_err(priv->dev, "unable to register device");
-               goto failed_cdev_add;
-@@ -194,6 +194,20 @@ static int rpivid_mem_probe(struct platf
-       if (IS_ERR(ptr_err))
-               goto failed_device_create;
-+      /* Legacy alias */
-+      {
-+              char *oldname = kstrdup(priv->name, GFP_KERNEL);
-+
-+              oldname[1] = 'a';
-+              oldname[2] = 'r';
-+              oldname[3] = 'g';
-+              oldname[4] = 'o';
-+              oldname[5] = 'n';
-+              (void)device_create(priv->class, NULL, priv->devid + 1, NULL,
-+                                     oldname + 1);
-+              kfree(oldname);
-+      }
-+
-       dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
-               priv->name, priv->regs_phys, priv->mem_window_len);
diff --git a/target/linux/brcm2708/patches-4.19/950-0637-drm-vc4-Add-Broadcast-RGB-connector-property.patch b/target/linux/brcm2708/patches-4.19/950-0637-drm-vc4-Add-Broadcast-RGB-connector-property.patch
new file mode 100644 (file)
index 0000000..26da5d9
--- /dev/null
@@ -0,0 +1,302 @@
+From b96e24487cc48a2cb593f27c24074087a21de848 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 14 Jun 2019 10:12:07 +0100
+Subject: [PATCH] drm/vc4: Add "Broadcast RGB" connector property
+
+Some HDMI monitors do not abide by the full or limited
+(16-235) range RGB flags in the AVI infoframe. This can
+result in images looking washed out (if given limited and
+interpreting as full), or detail disappearing at the extremes
+(given full and interpreting as limited).
+
+Copy the Intel i915 driver's approach of adding an override
+property ("Broadcast RGB") to force one mode or the other.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 190 +++++++++++++++++++++++--
+ 1 file changed, 177 insertions(+), 13 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -285,6 +285,13 @@ to_vc4_fkms_encoder(struct drm_encoder *
+       return container_of(encoder, struct vc4_fkms_encoder, base);
+ }
++/* "Broadcast RGB" property.
++ * Allows overriding of HDMI full or limited range RGB
++ */
++#define VC4_BROADCAST_RGB_AUTO 0
++#define VC4_BROADCAST_RGB_FULL 1
++#define VC4_BROADCAST_RGB_LIMITED 2
++
+ /* VC4 FKMS connector KMS struct */
+ struct vc4_fkms_connector {
+       struct drm_connector base;
+@@ -297,6 +304,8 @@ struct vc4_fkms_connector {
+       struct vc4_dev *vc4_dev;
+       u32 display_number;
+       u32 display_type;
++
++      struct drm_property *broadcast_rgb_property;
+ };
+ static inline struct vc4_fkms_connector *
+@@ -305,6 +314,16 @@ to_vc4_fkms_connector(struct drm_connect
+       return container_of(connector, struct vc4_fkms_connector, base);
+ }
++/* VC4 FKMS connector state */
++struct vc4_fkms_connector_state {
++      struct drm_connector_state base;
++
++      int broadcast_rgb;
++};
++
++#define to_vc4_fkms_connector_state(x) \
++                      container_of(x, struct vc4_fkms_connector_state, base)
++
+ static u32 vc4_get_display_type(u32 display_number)
+ {
+       const u32 display_types[] = {
+@@ -832,8 +851,6 @@ static void vc4_crtc_mode_set_nofb(struc
+                     mode->picture_aspect_ratio, mode->flags);
+       mb.timings.display = vc4_crtc->display_number;
+-      mb.timings.video_id_code = frame.avi.video_code;
+-
+       mb.timings.clock = mode->clock;
+       mb.timings.hdisplay = mode->hdisplay;
+       mb.timings.hsync_start = mode->hsync_start;
+@@ -871,11 +888,30 @@ static void vc4_crtc_mode_set_nofb(struc
+               break;
+       }
+-      if (!vc4_encoder->hdmi_monitor)
++      if (!vc4_encoder->hdmi_monitor) {
+               mb.timings.flags |= TIMINGS_FLAGS_DVI;
+-      else if (drm_default_rgb_quant_range(mode) ==
++              mb.timings.video_id_code = frame.avi.video_code;
++      } else {
++              struct vc4_fkms_connector_state *conn_state =
++                      to_vc4_fkms_connector_state(vc4_crtc->connector->state);
++
++              /* Do not provide a VIC as the HDMI spec requires that we do not
++               * signal the opposite of the defined range in the AVI
++               * infoframe.
++               */
++              mb.timings.video_id_code = 0;
++
++              if (conn_state->broadcast_rgb == VC4_BROADCAST_RGB_AUTO) {
++                      /* See CEA-861-E - 5.1 Default Encoding Parameters */
++                      if (drm_default_rgb_quant_range(mode) ==
+                                       HDMI_QUANTIZATION_RANGE_LIMITED)
+-              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++                              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++              } else {
++                      if (conn_state->broadcast_rgb ==
++                                              VC4_BROADCAST_RGB_LIMITED)
++                              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++              }
++      }
+       /*
+       FIXME: To implement
+@@ -1340,13 +1376,95 @@ static void vc4_fkms_connector_destroy(s
+       drm_connector_cleanup(connector);
+ }
++/**
++ * vc4_connector_duplicate_state - duplicate connector state
++ * @connector: digital connector
++ *
++ * Allocates and returns a copy of the connector state (both common and
++ * digital connector specific) for the specified connector.
++ *
++ * Returns: The newly allocated connector state, or NULL on failure.
++ */
++struct drm_connector_state *
++vc4_connector_duplicate_state(struct drm_connector *connector)
++{
++      struct vc4_fkms_connector_state *state;
++
++      state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);
++      if (!state)
++              return NULL;
++
++      __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
++      return &state->base;
++}
++
++/**
++ * vc4_connector_atomic_get_property - hook for connector->atomic_get_property.
++ * @connector: Connector to get the property for.
++ * @state: Connector state to retrieve the property from.
++ * @property: Property to retrieve.
++ * @val: Return value for the property.
++ *
++ * Returns the atomic property value for a digital connector.
++ */
++int vc4_connector_atomic_get_property(struct drm_connector *connector,
++                                    const struct drm_connector_state *state,
++                                    struct drm_property *property,
++                                    uint64_t *val)
++{
++      struct vc4_fkms_connector *fkms_connector =
++                                      to_vc4_fkms_connector(connector);
++      struct vc4_fkms_connector_state *vc4_conn_state =
++                                      to_vc4_fkms_connector_state(state);
++
++      if (property == fkms_connector->broadcast_rgb_property) {
++              *val = vc4_conn_state->broadcast_rgb;
++      } else {
++              DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
++                               property->base.id, property->name);
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++/**
++ * vc4_connector_atomic_set_property - hook for connector->atomic_set_property.
++ * @connector: Connector to set the property for.
++ * @state: Connector state to set the property on.
++ * @property: Property to set.
++ * @val: New value for the property.
++ *
++ * Sets the atomic property value for a digital connector.
++ */
++int vc4_connector_atomic_set_property(struct drm_connector *connector,
++                                    struct drm_connector_state *state,
++                                    struct drm_property *property,
++                                    uint64_t val)
++{
++      struct vc4_fkms_connector *fkms_connector =
++                                      to_vc4_fkms_connector(connector);
++      struct vc4_fkms_connector_state *vc4_conn_state =
++                                      to_vc4_fkms_connector_state(state);
++
++      if (property == fkms_connector->broadcast_rgb_property) {
++              vc4_conn_state->broadcast_rgb = val;
++              return 0;
++      }
++
++      DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
++                       property->base.id, property->name);
++      return -EINVAL;
++}
++
+ static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
+       .detect = vc4_fkms_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = vc4_fkms_connector_destroy,
+-      .reset = drm_atomic_helper_connector_reset,
+-      .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
++      .atomic_duplicate_state = vc4_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
++      .atomic_get_property = vc4_connector_atomic_get_property,
++      .atomic_set_property = vc4_connector_atomic_set_property,
+ };
+ static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = {
+@@ -1359,12 +1477,40 @@ static const struct drm_connector_helper
+       .best_encoder = vc4_fkms_connector_best_encoder,
+ };
++static const struct drm_prop_enum_list broadcast_rgb_names[] = {
++      { VC4_BROADCAST_RGB_AUTO, "Automatic" },
++      { VC4_BROADCAST_RGB_FULL, "Full" },
++      { VC4_BROADCAST_RGB_LIMITED, "Limited 16:235" },
++};
++
++static void
++vc4_attach_broadcast_rgb_property(struct vc4_fkms_connector *fkms_connector)
++{
++      struct drm_device *dev = fkms_connector->base.dev;
++      struct drm_property *prop;
++
++      prop = fkms_connector->broadcast_rgb_property;
++      if (!prop) {
++              prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
++                                              "Broadcast RGB",
++                                              broadcast_rgb_names,
++                                              ARRAY_SIZE(broadcast_rgb_names));
++              if (!prop)
++                      return;
++
++              fkms_connector->broadcast_rgb_property = prop;
++      }
++
++      drm_object_attach_property(&fkms_connector->base.base, prop, 0);
++}
++
+ static struct drm_connector *
+ vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
+                       u32 display_num)
+ {
+       struct drm_connector *connector = NULL;
+       struct vc4_fkms_connector *fkms_connector;
++      struct vc4_fkms_connector_state *conn_state = NULL;
+       struct vc4_dev *vc4_dev = to_vc4_dev(dev);
+       int ret = 0;
+@@ -1373,9 +1519,18 @@ vc4_fkms_connector_init(struct drm_devic
+       fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
+                                     GFP_KERNEL);
+       if (!fkms_connector) {
+-              ret = -ENOMEM;
+-              goto fail;
++              return ERR_PTR(-ENOMEM);
++      }
++
++      /*
++       * Allocate enough memory to hold vc4_fkms_connector_state,
++       */
++      conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
++      if (!conn_state) {
++              kfree(fkms_connector);
++              return ERR_PTR(-ENOMEM);
+       }
++
+       connector = &fkms_connector->base;
+       fkms_connector->encoder = encoder;
+@@ -1383,6 +1538,9 @@ vc4_fkms_connector_init(struct drm_devic
+       fkms_connector->display_type = vc4_get_display_type(display_num);
+       fkms_connector->vc4_dev = vc4_dev;
++      __drm_atomic_helper_connector_reset(connector,
++                                          &conn_state->base);
++
+       if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
+               drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+                                  DRM_MODE_CONNECTOR_DSI);
+@@ -1403,10 +1561,14 @@ vc4_fkms_connector_init(struct drm_devic
+               connector->interlace_allowed = 0;
+       }
+-      /* Create and attach TV margin props to this connector. */
+-      ret = drm_mode_create_tv_margin_properties(dev);
+-      if (ret)
+-              return ERR_PTR(ret);
++      /* Create and attach TV margin props to this connector.
++       * Already done for SDTV outputs.
++       */
++      if (fkms_connector->display_type != DRM_MODE_ENCODER_TVDAC) {
++              ret = drm_mode_create_tv_margin_properties(dev);
++              if (ret)
++                      goto fail;
++      }
+       drm_connector_attach_tv_margin_properties(connector);
+@@ -1415,6 +1577,8 @@ vc4_fkms_connector_init(struct drm_devic
+       connector->doublescan_allowed = 0;
++      vc4_attach_broadcast_rgb_property(fkms_connector);
++
+       drm_connector_attach_encoder(connector, encoder);
+       return connector;
diff --git a/target/linux/brcm2708/patches-4.19/950-0638-drm-connector-Add-documentation-for-drm_cmdline_mode.patch b/target/linux/brcm2708/patches-4.19/950-0638-drm-connector-Add-documentation-for-drm_cmdline_mode.patch
new file mode 100644 (file)
index 0000000..16b84bc
--- /dev/null
@@ -0,0 +1,125 @@
+From 7c0f4f4d81958f63abf696e71b342e8b75a6e530 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:48 +0200
+Subject: [PATCH] drm/connector: Add documentation for drm_cmdline_mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 772cd52c5574b04b00a97d638b2cfe94c0c1a9b6 upstream.
+
+The struct drm_cmdline_mode holds the result of the command line parsers.
+However, it wasn't documented so far, so let's do that.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/963c893c16c6a25fc469b53c726f493d99bdc578.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ include/drm/drm_connector.h | 86 ++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 84 insertions(+), 2 deletions(-)
+
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -755,18 +755,100 @@ struct drm_connector_funcs {
+                                  const struct drm_connector_state *state);
+ };
+-/* mode specified on the command line */
++/**
++ * struct drm_cmdline_mode - DRM Mode passed through the kernel command-line
++ *
++ * Each connector can have an initial mode with additional options
++ * passed through the kernel command line. This structure allows to
++ * express those parameters and will be filled by the command-line
++ * parser.
++ */
+ struct drm_cmdline_mode {
++      /**
++       * @specified:
++       *
++       * Has a mode been read from the command-line?
++       */
+       bool specified;
++
++      /**
++       * @refresh_specified:
++       *
++       * Did the mode have a preferred refresh rate?
++       */
+       bool refresh_specified;
++
++      /**
++       * @bpp_specified:
++       *
++       * Did the mode have a preferred BPP?
++       */
+       bool bpp_specified;
+-      int xres, yres;
++
++      /**
++       * @xres:
++       *
++       * Active resolution on the X axis, in pixels.
++       */
++      int xres;
++
++      /**
++       * @yres:
++       *
++       * Active resolution on the Y axis, in pixels.
++       */
++      int yres;
++
++      /**
++       * @bpp:
++       *
++       * Bits per pixels for the mode.
++       */
+       int bpp;
++
++      /**
++       * @refresh:
++       *
++       * Refresh rate, in Hertz.
++       */
+       int refresh;
++
++      /**
++       * @rb:
++       *
++       * Do we need to use reduced blanking?
++       */
+       bool rb;
++
++      /**
++       * @interlace:
++       *
++       * The mode is interlaced.
++       */
+       bool interlace;
++
++      /**
++       * @cvt:
++       *
++       * The timings will be calculated using the VESA Coordinated
++       * Video Timings instead of looking up the mode from a table.
++       */
+       bool cvt;
++
++      /**
++       * @margins:
++       *
++       * Add margins to the mode calculation (1.8% of xres rounded
++       * down to 8 pixels and 1.8% of yres).
++       */
+       bool margins;
++
++      /**
++       * @force:
++       *
++       * Ignore the hotplug state of the connector, and force its
++       * state to one of the DRM_FORCE_* values.
++       */
+       enum drm_connector_force force;
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0638-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch b/target/linux/brcm2708/patches-4.19/950-0638-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch
deleted file mode 100644 (file)
index c0a7af1..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From 16c1e20b50e121f836f434bb6c22c73e2f51d29f Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Thu, 1 Aug 2019 16:41:20 +0100
-Subject: [PATCH] hid: usb: Add device quirks for Freeway Airmouse T3
- and MX3
-
-These wireless mouse/keyboard combo remote control devices specify
-multiple "wheel" events in their report descriptors. The wheel events
-are incorrectly defined and apparently map to accelerometer data, leading
-to spurious mouse scroll events being generated at an extreme rate when
-the device is moved.
-
-As a workaround, use HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE to mask
-feeding the extra wheel events to the input subsystem.
-
-See: https://github.com/raspberrypi/firmware/issues/1189
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/hid/hid-ids.h    | 6 ++++++
- drivers/hid/hid-quirks.c | 2 ++
- 2 files changed, 8 insertions(+)
-
---- a/drivers/hid/hid-ids.h
-+++ b/drivers/hid/hid-ids.h
-@@ -222,6 +222,9 @@
- #define USB_VENDOR_ID_BAANTO          0x2453
- #define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100
-+#define USB_VENDOR_ID_BEKEN           0x25a7
-+#define USB_DEVICE_ID_AIRMOUSE_T3     0x2402
-+
- #define USB_VENDOR_ID_BELKIN          0x050d
- #define USB_DEVICE_ID_FLIP_KVM                0x3201
-@@ -1196,6 +1199,9 @@
- #define USB_VENDOR_ID_XAT     0x2505
- #define USB_DEVICE_ID_XAT_CSR 0x0220
-+#define USB_VENDOR_ID_XENTA                   0x1d57
-+#define USB_DEVICE_ID_AIRMOUSE_MX3            0xad03
-+
- #define USB_VENDOR_ID_XIN_MO                  0x16c0
- #define USB_DEVICE_ID_XIN_MO_DUAL_ARCADE      0x05e1
- #define USB_DEVICE_ID_THT_2P_ARCADE           0x75e1
---- a/drivers/hid/hid-quirks.c
-+++ b/drivers/hid/hid-quirks.c
-@@ -43,6 +43,7 @@ static const struct hid_device_id hid_qu
-       { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET },
-+      { HID_USB_DEVICE(USB_VENDOR_ID_BEKEN, USB_DEVICE_ID_AIRMOUSE_T3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL },
-@@ -175,6 +176,7 @@ static const struct hid_device_id hid_qu
-       { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-+      { HID_USB_DEVICE(USB_VENDOR_ID_XENTA, USB_DEVICE_ID_AIRMOUSE_MX3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-       { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT },
-       { 0 }
diff --git a/target/linux/brcm2708/patches-4.19/950-0639-drm-modes-Rewrite-the-command-line-parser.patch b/target/linux/brcm2708/patches-4.19/950-0639-drm-modes-Rewrite-the-command-line-parser.patch
new file mode 100644 (file)
index 0000000..24c25d6
--- /dev/null
@@ -0,0 +1,392 @@
+From 3508a8548f13be68b6d098ad99a7bc1fc1810f76 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:49 +0200
+Subject: [PATCH] drm/modes: Rewrite the command line parser
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit e08ab74bd4c7a5fe311bc05f32dbb4f1e7fa3428 upstream.
+
+Rewrite the command line parser in order to get away from the state machine
+parsing the video mode lines.
+
+Hopefully, this will allow to extend it more easily to support named modes
+and / or properties set directly on the command line.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/e32cd4009153b184103554009135c7bf7c9975d7.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/drm_modes.c | 325 +++++++++++++++++++++++-------------
+ 1 file changed, 210 insertions(+), 115 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -30,6 +30,7 @@
+  * authorization from the copyright holder(s) and author(s).
+  */
++#include <linux/ctype.h>
+ #include <linux/list.h>
+ #include <linux/list_sort.h>
+ #include <linux/export.h>
+@@ -1414,6 +1415,151 @@ void drm_connector_list_update(struct dr
+ }
+ EXPORT_SYMBOL(drm_connector_list_update);
++static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
++                                    struct drm_cmdline_mode *mode)
++{
++      unsigned int bpp;
++
++      if (str[0] != '-')
++              return -EINVAL;
++
++      str++;
++      bpp = simple_strtol(str, end_ptr, 10);
++      if (*end_ptr == str)
++              return -EINVAL;
++
++      mode->bpp = bpp;
++      mode->bpp_specified = true;
++
++      return 0;
++}
++
++static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
++                                        struct drm_cmdline_mode *mode)
++{
++      unsigned int refresh;
++
++      if (str[0] != '@')
++              return -EINVAL;
++
++      str++;
++      refresh = simple_strtol(str, end_ptr, 10);
++      if (*end_ptr == str)
++              return -EINVAL;
++
++      mode->refresh = refresh;
++      mode->refresh_specified = true;
++
++      return 0;
++}
++
++static int drm_mode_parse_cmdline_extra(const char *str, int length,
++                                      struct drm_connector *connector,
++                                      struct drm_cmdline_mode *mode)
++{
++      int i;
++
++      for (i = 0; i < length; i++) {
++              switch (str[i]) {
++              case 'i':
++                      mode->interlace = true;
++                      break;
++              case 'm':
++                      mode->margins = true;
++                      break;
++              case 'D':
++                      if (mode->force != DRM_FORCE_UNSPECIFIED)
++                              return -EINVAL;
++
++                      if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
++                          (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
++                              mode->force = DRM_FORCE_ON;
++                      else
++                              mode->force = DRM_FORCE_ON_DIGITAL;
++                      break;
++              case 'd':
++                      if (mode->force != DRM_FORCE_UNSPECIFIED)
++                              return -EINVAL;
++
++                      mode->force = DRM_FORCE_OFF;
++                      break;
++              case 'e':
++                      if (mode->force != DRM_FORCE_UNSPECIFIED)
++                              return -EINVAL;
++
++                      mode->force = DRM_FORCE_ON;
++                      break;
++              default:
++                      return -EINVAL;
++              }
++      }
++
++      return 0;
++}
++
++static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
++                                         bool extras,
++                                         struct drm_connector *connector,
++                                         struct drm_cmdline_mode *mode)
++{
++      const char *str_start = str;
++      bool rb = false, cvt = false;
++      int xres = 0, yres = 0;
++      int remaining, i;
++      char *end_ptr;
++
++      xres = simple_strtol(str, &end_ptr, 10);
++      if (end_ptr == str)
++              return -EINVAL;
++
++      if (end_ptr[0] != 'x')
++              return -EINVAL;
++      end_ptr++;
++
++      str = end_ptr;
++      yres = simple_strtol(str, &end_ptr, 10);
++      if (end_ptr == str)
++              return -EINVAL;
++
++      remaining = length - (end_ptr - str_start);
++      if (remaining < 0)
++              return -EINVAL;
++
++      for (i = 0; i < remaining; i++) {
++              switch (end_ptr[i]) {
++              case 'M':
++                      cvt = true;
++                      break;
++              case 'R':
++                      rb = true;
++                      break;
++              default:
++                      /*
++                       * Try to pass that to our extras parsing
++                       * function to handle the case where the
++                       * extras are directly after the resolution
++                       */
++                      if (extras) {
++                              int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
++                                                                     1,
++                                                                     connector,
++                                                                     mode);
++                              if (ret)
++                                      return ret;
++                      } else {
++                              return -EINVAL;
++                      }
++              }
++      }
++
++      mode->xres = xres;
++      mode->yres = yres;
++      mode->cvt = cvt;
++      mode->rb = rb;
++
++      return 0;
++}
++
+ /**
+  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
+  * @mode_option: optional per connector mode option
+@@ -1440,13 +1586,12 @@ bool drm_mode_parse_command_line_for_con
+                                              struct drm_cmdline_mode *mode)
+ {
+       const char *name;
+-      unsigned int namelen;
+-      bool res_specified = false, bpp_specified = false, refresh_specified = false;
+-      unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
+-      bool yres_specified = false, cvt = false, rb = false;
+-      bool interlace = false, margins = false, was_digit = false;
+-      int i;
+-      enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
++      bool parse_extras = false;
++      unsigned int bpp_off = 0, refresh_off = 0;
++      unsigned int mode_end = 0;
++      char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
++      char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
++      int ret;
+ #ifdef CONFIG_FB
+       if (!mode_option)
+@@ -1459,127 +1604,77 @@ bool drm_mode_parse_command_line_for_con
+       }
+       name = mode_option;
+-      namelen = strlen(name);
+-      for (i = namelen-1; i >= 0; i--) {
+-              switch (name[i]) {
+-              case '@':
+-                      if (!refresh_specified && !bpp_specified &&
+-                          !yres_specified && !cvt && !rb && was_digit) {
+-                              refresh = simple_strtol(&name[i+1], NULL, 10);
+-                              refresh_specified = true;
+-                              was_digit = false;
+-                      } else
+-                              goto done;
+-                      break;
+-              case '-':
+-                      if (!bpp_specified && !yres_specified && !cvt &&
+-                          !rb && was_digit) {
+-                              bpp = simple_strtol(&name[i+1], NULL, 10);
+-                              bpp_specified = true;
+-                              was_digit = false;
+-                      } else
+-                              goto done;
+-                      break;
+-              case 'x':
+-                      if (!yres_specified && was_digit) {
+-                              yres = simple_strtol(&name[i+1], NULL, 10);
+-                              yres_specified = true;
+-                              was_digit = false;
+-                      } else
+-                              goto done;
+-                      break;
+-              case '0' ... '9':
+-                      was_digit = true;
+-                      break;
+-              case 'M':
+-                      if (yres_specified || cvt || was_digit)
+-                              goto done;
+-                      cvt = true;
+-                      break;
+-              case 'R':
+-                      if (yres_specified || cvt || rb || was_digit)
+-                              goto done;
+-                      rb = true;
+-                      break;
+-              case 'm':
+-                      if (cvt || yres_specified || was_digit)
+-                              goto done;
+-                      margins = true;
+-                      break;
+-              case 'i':
+-                      if (cvt || yres_specified || was_digit)
+-                              goto done;
+-                      interlace = true;
+-                      break;
+-              case 'e':
+-                      if (yres_specified || bpp_specified || refresh_specified ||
+-                          was_digit || (force != DRM_FORCE_UNSPECIFIED))
+-                              goto done;
+-                      force = DRM_FORCE_ON;
+-                      break;
+-              case 'D':
+-                      if (yres_specified || bpp_specified || refresh_specified ||
+-                          was_digit || (force != DRM_FORCE_UNSPECIFIED))
+-                              goto done;
++      if (!isdigit(name[0]))
++              return false;
+-                      if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
+-                          (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
+-                              force = DRM_FORCE_ON;
+-                      else
+-                              force = DRM_FORCE_ON_DIGITAL;
+-                      break;
+-              case 'd':
+-                      if (yres_specified || bpp_specified || refresh_specified ||
+-                          was_digit || (force != DRM_FORCE_UNSPECIFIED))
+-                              goto done;
++      /* Try to locate the bpp and refresh specifiers, if any */
++      bpp_ptr = strchr(name, '-');
++      if (bpp_ptr) {
++              bpp_off = bpp_ptr - name;
++              mode->bpp_specified = true;
++      }
+-                      force = DRM_FORCE_OFF;
+-                      break;
+-              default:
+-                      goto done;
+-              }
++      refresh_ptr = strchr(name, '@');
++      if (refresh_ptr) {
++              refresh_off = refresh_ptr - name;
++              mode->refresh_specified = true;
+       }
+-      if (i < 0 && yres_specified) {
+-              char *ch;
+-              xres = simple_strtol(name, &ch, 10);
+-              if ((ch != NULL) && (*ch == 'x'))
+-                      res_specified = true;
+-              else
+-                      i = ch - name;
+-      } else if (!yres_specified && was_digit) {
+-              /* catch mode that begins with digits but has no 'x' */
+-              i = 0;
+-      }
+-done:
+-      if (i >= 0) {
+-              pr_warn("[drm] parse error at position %i in video mode '%s'\n",
+-                      i, name);
+-              mode->specified = false;
+-              return false;
++      /* Locate the end of the name / resolution, and parse it */
++      if (bpp_ptr && refresh_ptr) {
++              mode_end = min(bpp_off, refresh_off);
++      } else if (bpp_ptr) {
++              mode_end = bpp_off;
++      } else if (refresh_ptr) {
++              mode_end = refresh_off;
++      } else {
++              mode_end = strlen(name);
++              parse_extras = true;
+       }
+-      if (res_specified) {
+-              mode->specified = true;
+-              mode->xres = xres;
+-              mode->yres = yres;
++      ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
++                                            parse_extras,
++                                            connector,
++                                            mode);
++      if (ret)
++              return false;
++      mode->specified = true;
++
++      if (bpp_ptr) {
++              ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
++              if (ret)
++                      return false;
+       }
+-      if (refresh_specified) {
+-              mode->refresh_specified = true;
+-              mode->refresh = refresh;
++      if (refresh_ptr) {
++              ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
++                                                   &refresh_end_ptr, mode);
++              if (ret)
++                      return false;
+       }
+-      if (bpp_specified) {
+-              mode->bpp_specified = true;
+-              mode->bpp = bpp;
++      /*
++       * Locate the end of the bpp / refresh, and parse the extras
++       * if relevant
++       */
++      if (bpp_ptr && refresh_ptr)
++              extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
++      else if (bpp_ptr)
++              extra_ptr = bpp_end_ptr;
++      else if (refresh_ptr)
++              extra_ptr = refresh_end_ptr;
++
++      if (extra_ptr) {
++              int remaining = strlen(name) - (extra_ptr - name);
++
++              /*
++               * We still have characters to process, while
++               * we shouldn't have any
++               */
++              if (remaining > 0)
++                      return false;
+       }
+-      mode->rb = rb;
+-      mode->cvt = cvt;
+-      mode->interlace = interlace;
+-      mode->margins = margins;
+-      mode->force = force;
+       return true;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0639-drm-vc4-Add-Broadcast-RGB-connector-property.patch b/target/linux/brcm2708/patches-4.19/950-0639-drm-vc4-Add-Broadcast-RGB-connector-property.patch
deleted file mode 100644 (file)
index 26da5d9..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-From b96e24487cc48a2cb593f27c24074087a21de848 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 14 Jun 2019 10:12:07 +0100
-Subject: [PATCH] drm/vc4: Add "Broadcast RGB" connector property
-
-Some HDMI monitors do not abide by the full or limited
-(16-235) range RGB flags in the AVI infoframe. This can
-result in images looking washed out (if given limited and
-interpreting as full), or detail disappearing at the extremes
-(given full and interpreting as limited).
-
-Copy the Intel i915 driver's approach of adding an override
-property ("Broadcast RGB") to force one mode or the other.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 190 +++++++++++++++++++++++--
- 1 file changed, 177 insertions(+), 13 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -285,6 +285,13 @@ to_vc4_fkms_encoder(struct drm_encoder *
-       return container_of(encoder, struct vc4_fkms_encoder, base);
- }
-+/* "Broadcast RGB" property.
-+ * Allows overriding of HDMI full or limited range RGB
-+ */
-+#define VC4_BROADCAST_RGB_AUTO 0
-+#define VC4_BROADCAST_RGB_FULL 1
-+#define VC4_BROADCAST_RGB_LIMITED 2
-+
- /* VC4 FKMS connector KMS struct */
- struct vc4_fkms_connector {
-       struct drm_connector base;
-@@ -297,6 +304,8 @@ struct vc4_fkms_connector {
-       struct vc4_dev *vc4_dev;
-       u32 display_number;
-       u32 display_type;
-+
-+      struct drm_property *broadcast_rgb_property;
- };
- static inline struct vc4_fkms_connector *
-@@ -305,6 +314,16 @@ to_vc4_fkms_connector(struct drm_connect
-       return container_of(connector, struct vc4_fkms_connector, base);
- }
-+/* VC4 FKMS connector state */
-+struct vc4_fkms_connector_state {
-+      struct drm_connector_state base;
-+
-+      int broadcast_rgb;
-+};
-+
-+#define to_vc4_fkms_connector_state(x) \
-+                      container_of(x, struct vc4_fkms_connector_state, base)
-+
- static u32 vc4_get_display_type(u32 display_number)
- {
-       const u32 display_types[] = {
-@@ -832,8 +851,6 @@ static void vc4_crtc_mode_set_nofb(struc
-                     mode->picture_aspect_ratio, mode->flags);
-       mb.timings.display = vc4_crtc->display_number;
--      mb.timings.video_id_code = frame.avi.video_code;
--
-       mb.timings.clock = mode->clock;
-       mb.timings.hdisplay = mode->hdisplay;
-       mb.timings.hsync_start = mode->hsync_start;
-@@ -871,11 +888,30 @@ static void vc4_crtc_mode_set_nofb(struc
-               break;
-       }
--      if (!vc4_encoder->hdmi_monitor)
-+      if (!vc4_encoder->hdmi_monitor) {
-               mb.timings.flags |= TIMINGS_FLAGS_DVI;
--      else if (drm_default_rgb_quant_range(mode) ==
-+              mb.timings.video_id_code = frame.avi.video_code;
-+      } else {
-+              struct vc4_fkms_connector_state *conn_state =
-+                      to_vc4_fkms_connector_state(vc4_crtc->connector->state);
-+
-+              /* Do not provide a VIC as the HDMI spec requires that we do not
-+               * signal the opposite of the defined range in the AVI
-+               * infoframe.
-+               */
-+              mb.timings.video_id_code = 0;
-+
-+              if (conn_state->broadcast_rgb == VC4_BROADCAST_RGB_AUTO) {
-+                      /* See CEA-861-E - 5.1 Default Encoding Parameters */
-+                      if (drm_default_rgb_quant_range(mode) ==
-                                       HDMI_QUANTIZATION_RANGE_LIMITED)
--              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
-+                              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
-+              } else {
-+                      if (conn_state->broadcast_rgb ==
-+                                              VC4_BROADCAST_RGB_LIMITED)
-+                              mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
-+              }
-+      }
-       /*
-       FIXME: To implement
-@@ -1340,13 +1376,95 @@ static void vc4_fkms_connector_destroy(s
-       drm_connector_cleanup(connector);
- }
-+/**
-+ * vc4_connector_duplicate_state - duplicate connector state
-+ * @connector: digital connector
-+ *
-+ * Allocates and returns a copy of the connector state (both common and
-+ * digital connector specific) for the specified connector.
-+ *
-+ * Returns: The newly allocated connector state, or NULL on failure.
-+ */
-+struct drm_connector_state *
-+vc4_connector_duplicate_state(struct drm_connector *connector)
-+{
-+      struct vc4_fkms_connector_state *state;
-+
-+      state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);
-+      if (!state)
-+              return NULL;
-+
-+      __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
-+      return &state->base;
-+}
-+
-+/**
-+ * vc4_connector_atomic_get_property - hook for connector->atomic_get_property.
-+ * @connector: Connector to get the property for.
-+ * @state: Connector state to retrieve the property from.
-+ * @property: Property to retrieve.
-+ * @val: Return value for the property.
-+ *
-+ * Returns the atomic property value for a digital connector.
-+ */
-+int vc4_connector_atomic_get_property(struct drm_connector *connector,
-+                                    const struct drm_connector_state *state,
-+                                    struct drm_property *property,
-+                                    uint64_t *val)
-+{
-+      struct vc4_fkms_connector *fkms_connector =
-+                                      to_vc4_fkms_connector(connector);
-+      struct vc4_fkms_connector_state *vc4_conn_state =
-+                                      to_vc4_fkms_connector_state(state);
-+
-+      if (property == fkms_connector->broadcast_rgb_property) {
-+              *val = vc4_conn_state->broadcast_rgb;
-+      } else {
-+              DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
-+                               property->base.id, property->name);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * vc4_connector_atomic_set_property - hook for connector->atomic_set_property.
-+ * @connector: Connector to set the property for.
-+ * @state: Connector state to set the property on.
-+ * @property: Property to set.
-+ * @val: New value for the property.
-+ *
-+ * Sets the atomic property value for a digital connector.
-+ */
-+int vc4_connector_atomic_set_property(struct drm_connector *connector,
-+                                    struct drm_connector_state *state,
-+                                    struct drm_property *property,
-+                                    uint64_t val)
-+{
-+      struct vc4_fkms_connector *fkms_connector =
-+                                      to_vc4_fkms_connector(connector);
-+      struct vc4_fkms_connector_state *vc4_conn_state =
-+                                      to_vc4_fkms_connector_state(state);
-+
-+      if (property == fkms_connector->broadcast_rgb_property) {
-+              vc4_conn_state->broadcast_rgb = val;
-+              return 0;
-+      }
-+
-+      DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
-+                       property->base.id, property->name);
-+      return -EINVAL;
-+}
-+
- static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
-       .detect = vc4_fkms_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = vc4_fkms_connector_destroy,
--      .reset = drm_atomic_helper_connector_reset,
--      .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-+      .atomic_duplicate_state = vc4_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-+      .atomic_get_property = vc4_connector_atomic_get_property,
-+      .atomic_set_property = vc4_connector_atomic_set_property,
- };
- static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = {
-@@ -1359,12 +1477,40 @@ static const struct drm_connector_helper
-       .best_encoder = vc4_fkms_connector_best_encoder,
- };
-+static const struct drm_prop_enum_list broadcast_rgb_names[] = {
-+      { VC4_BROADCAST_RGB_AUTO, "Automatic" },
-+      { VC4_BROADCAST_RGB_FULL, "Full" },
-+      { VC4_BROADCAST_RGB_LIMITED, "Limited 16:235" },
-+};
-+
-+static void
-+vc4_attach_broadcast_rgb_property(struct vc4_fkms_connector *fkms_connector)
-+{
-+      struct drm_device *dev = fkms_connector->base.dev;
-+      struct drm_property *prop;
-+
-+      prop = fkms_connector->broadcast_rgb_property;
-+      if (!prop) {
-+              prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
-+                                              "Broadcast RGB",
-+                                              broadcast_rgb_names,
-+                                              ARRAY_SIZE(broadcast_rgb_names));
-+              if (!prop)
-+                      return;
-+
-+              fkms_connector->broadcast_rgb_property = prop;
-+      }
-+
-+      drm_object_attach_property(&fkms_connector->base.base, prop, 0);
-+}
-+
- static struct drm_connector *
- vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
-                       u32 display_num)
- {
-       struct drm_connector *connector = NULL;
-       struct vc4_fkms_connector *fkms_connector;
-+      struct vc4_fkms_connector_state *conn_state = NULL;
-       struct vc4_dev *vc4_dev = to_vc4_dev(dev);
-       int ret = 0;
-@@ -1373,9 +1519,18 @@ vc4_fkms_connector_init(struct drm_devic
-       fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
-                                     GFP_KERNEL);
-       if (!fkms_connector) {
--              ret = -ENOMEM;
--              goto fail;
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      /*
-+       * Allocate enough memory to hold vc4_fkms_connector_state,
-+       */
-+      conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
-+      if (!conn_state) {
-+              kfree(fkms_connector);
-+              return ERR_PTR(-ENOMEM);
-       }
-+
-       connector = &fkms_connector->base;
-       fkms_connector->encoder = encoder;
-@@ -1383,6 +1538,9 @@ vc4_fkms_connector_init(struct drm_devic
-       fkms_connector->display_type = vc4_get_display_type(display_num);
-       fkms_connector->vc4_dev = vc4_dev;
-+      __drm_atomic_helper_connector_reset(connector,
-+                                          &conn_state->base);
-+
-       if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
-               drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-                                  DRM_MODE_CONNECTOR_DSI);
-@@ -1403,10 +1561,14 @@ vc4_fkms_connector_init(struct drm_devic
-               connector->interlace_allowed = 0;
-       }
--      /* Create and attach TV margin props to this connector. */
--      ret = drm_mode_create_tv_margin_properties(dev);
--      if (ret)
--              return ERR_PTR(ret);
-+      /* Create and attach TV margin props to this connector.
-+       * Already done for SDTV outputs.
-+       */
-+      if (fkms_connector->display_type != DRM_MODE_ENCODER_TVDAC) {
-+              ret = drm_mode_create_tv_margin_properties(dev);
-+              if (ret)
-+                      goto fail;
-+      }
-       drm_connector_attach_tv_margin_properties(connector);
-@@ -1415,6 +1577,8 @@ vc4_fkms_connector_init(struct drm_devic
-       connector->doublescan_allowed = 0;
-+      vc4_attach_broadcast_rgb_property(fkms_connector);
-+
-       drm_connector_attach_encoder(connector, encoder);
-       return connector;
diff --git a/target/linux/brcm2708/patches-4.19/950-0640-drm-connector-Add-documentation-for-drm_cmdline_mode.patch b/target/linux/brcm2708/patches-4.19/950-0640-drm-connector-Add-documentation-for-drm_cmdline_mode.patch
deleted file mode 100644 (file)
index 16b84bc..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-From 7c0f4f4d81958f63abf696e71b342e8b75a6e530 Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:48 +0200
-Subject: [PATCH] drm/connector: Add documentation for drm_cmdline_mode
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 772cd52c5574b04b00a97d638b2cfe94c0c1a9b6 upstream.
-
-The struct drm_cmdline_mode holds the result of the command line parsers.
-However, it wasn't documented so far, so let's do that.
-
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/963c893c16c6a25fc469b53c726f493d99bdc578.1560783090.git-series.maxime.ripard@bootlin.com
----
- include/drm/drm_connector.h | 86 ++++++++++++++++++++++++++++++++++++-
- 1 file changed, 84 insertions(+), 2 deletions(-)
-
---- a/include/drm/drm_connector.h
-+++ b/include/drm/drm_connector.h
-@@ -755,18 +755,100 @@ struct drm_connector_funcs {
-                                  const struct drm_connector_state *state);
- };
--/* mode specified on the command line */
-+/**
-+ * struct drm_cmdline_mode - DRM Mode passed through the kernel command-line
-+ *
-+ * Each connector can have an initial mode with additional options
-+ * passed through the kernel command line. This structure allows to
-+ * express those parameters and will be filled by the command-line
-+ * parser.
-+ */
- struct drm_cmdline_mode {
-+      /**
-+       * @specified:
-+       *
-+       * Has a mode been read from the command-line?
-+       */
-       bool specified;
-+
-+      /**
-+       * @refresh_specified:
-+       *
-+       * Did the mode have a preferred refresh rate?
-+       */
-       bool refresh_specified;
-+
-+      /**
-+       * @bpp_specified:
-+       *
-+       * Did the mode have a preferred BPP?
-+       */
-       bool bpp_specified;
--      int xres, yres;
-+
-+      /**
-+       * @xres:
-+       *
-+       * Active resolution on the X axis, in pixels.
-+       */
-+      int xres;
-+
-+      /**
-+       * @yres:
-+       *
-+       * Active resolution on the Y axis, in pixels.
-+       */
-+      int yres;
-+
-+      /**
-+       * @bpp:
-+       *
-+       * Bits per pixels for the mode.
-+       */
-       int bpp;
-+
-+      /**
-+       * @refresh:
-+       *
-+       * Refresh rate, in Hertz.
-+       */
-       int refresh;
-+
-+      /**
-+       * @rb:
-+       *
-+       * Do we need to use reduced blanking?
-+       */
-       bool rb;
-+
-+      /**
-+       * @interlace:
-+       *
-+       * The mode is interlaced.
-+       */
-       bool interlace;
-+
-+      /**
-+       * @cvt:
-+       *
-+       * The timings will be calculated using the VESA Coordinated
-+       * Video Timings instead of looking up the mode from a table.
-+       */
-       bool cvt;
-+
-+      /**
-+       * @margins:
-+       *
-+       * Add margins to the mode calculation (1.8% of xres rounded
-+       * down to 8 pixels and 1.8% of yres).
-+       */
-       bool margins;
-+
-+      /**
-+       * @force:
-+       *
-+       * Ignore the hotplug state of the connector, and force its
-+       * state to one of the DRM_FORCE_* values.
-+       */
-       enum drm_connector_force force;
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0640-drm-modes-Support-modes-names-on-the-command-line.patch b/target/linux/brcm2708/patches-4.19/950-0640-drm-modes-Support-modes-names-on-the-command-line.patch
new file mode 100644 (file)
index 0000000..1cacab2
--- /dev/null
@@ -0,0 +1,174 @@
+From 2cea4924c69b6be5cfe8d976810ccf76a3991230 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:50 +0200
+Subject: [PATCH] drm/modes: Support modes names on the command line
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 3aeeb13d899627fe2b86bdbdcd0927cf7192234f upstream.
+Minor conflict resolution as upstream has moved functions
+from drm_fb_helper.c to a new drm_client_modeset.c
+
+The drm subsystem also uses the video= kernel parameter, and in the
+documentation refers to the fbdev documentation for that parameter.
+
+However, that documentation also says that instead of giving the mode using
+its resolution we can also give a name. However, DRM doesn't handle that
+case at the moment. Even though in most case it shouldn't make any
+difference, it might be useful for analog modes, where different standards
+might have the same resolution, but still have a few different parameters
+that are not encoded in the modes (NTSC vs NTSC-J vs PAL-M for example).
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/18443e0c3bdbbd16cea4ec63bc7f2079b820b43b.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/drm_connector.c |  3 +-
+ drivers/gpu/drm/drm_fb_helper.c |  4 +++
+ drivers/gpu/drm/drm_modes.c     | 62 ++++++++++++++++++++++++---------
+ include/drm/drm_connector.h     |  7 ++++
+ 4 files changed, 59 insertions(+), 17 deletions(-)
+
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -135,8 +135,9 @@ static void drm_connector_get_cmdline_mo
+               connector->force = mode->force;
+       }
+-      DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
++      DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
+                     connector->name,
++                    mode->name ? mode->name : "",
+                     mode->xres, mode->yres,
+                     mode->refresh_specified ? mode->refresh : 60,
+                     mode->rb ? " reduced blanking" : "",
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -2104,6 +2104,10 @@ struct drm_display_mode *drm_pick_cmdlin
+       prefer_non_interlace = !cmdline_mode->interlace;
+ again:
+       list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
++              /* Check (optional) mode name first */
++              if (!strcmp(mode->name, cmdline_mode->name))
++                      return mode;
++
+               /* check width/height */
+               if (mode->hdisplay != cmdline_mode->xres ||
+                   mode->vdisplay != cmdline_mode->yres)
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1586,7 +1586,7 @@ bool drm_mode_parse_command_line_for_con
+                                              struct drm_cmdline_mode *mode)
+ {
+       const char *name;
+-      bool parse_extras = false;
++      bool named_mode = false, parse_extras = false;
+       unsigned int bpp_off = 0, refresh_off = 0;
+       unsigned int mode_end = 0;
+       char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
+@@ -1605,8 +1605,22 @@ bool drm_mode_parse_command_line_for_con
+       name = mode_option;
+-      if (!isdigit(name[0]))
+-              return false;
++      /*
++       * This is a bit convoluted. To differentiate between the
++       * named modes and poorly formatted resolutions, we need a
++       * bunch of things:
++       *   - We need to make sure that the first character (which
++       *     would be our resolution in X) is a digit.
++       *   - However, if the X resolution is missing, then we end up
++       *     with something like x<yres>, with our first character
++       *     being an alpha-numerical character, which would be
++       *     considered a named mode.
++       *
++       * If this isn't enough, we should add more heuristics here,
++       * and matching unit-tests.
++       */
++      if (!isdigit(name[0]) && name[0] != 'x')
++              named_mode = true;
+       /* Try to locate the bpp and refresh specifiers, if any */
+       bpp_ptr = strchr(name, '-');
+@@ -1617,6 +1631,9 @@ bool drm_mode_parse_command_line_for_con
+       refresh_ptr = strchr(name, '@');
+       if (refresh_ptr) {
++              if (named_mode)
++                      return false;
++
+               refresh_off = refresh_ptr - name;
+               mode->refresh_specified = true;
+       }
+@@ -1633,12 +1650,16 @@ bool drm_mode_parse_command_line_for_con
+               parse_extras = true;
+       }
+-      ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
+-                                            parse_extras,
+-                                            connector,
+-                                            mode);
+-      if (ret)
+-              return false;
++      if (named_mode) {
++              strncpy(mode->name, name, mode_end);
++      } else {
++              ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
++                                                    parse_extras,
++                                                    connector,
++                                                    mode);
++              if (ret)
++                      return false;
++      }
+       mode->specified = true;
+       if (bpp_ptr) {
+@@ -1666,14 +1687,23 @@ bool drm_mode_parse_command_line_for_con
+               extra_ptr = refresh_end_ptr;
+       if (extra_ptr) {
+-              int remaining = strlen(name) - (extra_ptr - name);
++              if (!named_mode) {
++                      int len = strlen(name) - (extra_ptr - name);
+-              /*
+-               * We still have characters to process, while
+-               * we shouldn't have any
+-               */
+-              if (remaining > 0)
+-                      return false;
++                      ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
++                                                         connector, mode);
++                      if (ret)
++                              return false;
++              } else {
++                      int remaining = strlen(name) - (extra_ptr - name);
++
++                      /*
++                       * We still have characters to process, while
++                       * we shouldn't have any
++                       */
++                      if (remaining > 0)
++                              return false;
++              }
+       }
+       return true;
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -765,6 +765,13 @@ struct drm_connector_funcs {
+  */
+ struct drm_cmdline_mode {
+       /**
++       * @name:
++       *
++       * Name of the mode.
++       */
++      char name[DRM_DISPLAY_MODE_LEN];
++
++      /**
+        * @specified:
+        *
+        * Has a mode been read from the command-line?
diff --git a/target/linux/brcm2708/patches-4.19/950-0641-drm-modes-Allow-to-specify-rotation-and-reflection-o.patch b/target/linux/brcm2708/patches-4.19/950-0641-drm-modes-Allow-to-specify-rotation-and-reflection-o.patch
new file mode 100644 (file)
index 0000000..0b2a185
--- /dev/null
@@ -0,0 +1,277 @@
+From 5a8ccd79b6bad32e52620a94199bf1af2e19708e Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:51 +0200
+Subject: [PATCH] drm/modes: Allow to specify rotation and reflection
+ on the commandline
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 1bf4e09227c345e246062285eba4b8fe660e512e upstream.
+Minor conflict resolution as upstream has moved functions
+from drm_fb_helper.c to a new drm_client_modeset.c
+
+Rotations and reflections setup are needed in some scenarios to initialise
+properly the initial framebuffer. Some drivers already had a bunch of
+quirks to deal with this, such as either a private kernel command line
+parameter (omapdss) or on the device tree (various panels).
+
+In order to accomodate this, let's create a video mode parameter to deal
+with the rotation and reflexion.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/777da16e42db757c1f5b414b5ca34507097fed5c.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ Documentation/fb/modedb.txt     |  12 ++++
+ drivers/gpu/drm/drm_fb_helper.c |  30 +++++++++
+ drivers/gpu/drm/drm_modes.c     | 114 ++++++++++++++++++++++++++------
+ include/drm/drm_connector.h     |  10 +++
+ 4 files changed, 146 insertions(+), 20 deletions(-)
+
+--- a/Documentation/fb/modedb.txt
++++ b/Documentation/fb/modedb.txt
+@@ -51,6 +51,18 @@ To force the VGA output to be enabled an
+ Specifying the option multiple times for different ports is possible, e.g.:
+     video=LVDS-1:d video=HDMI-1:D
++Options can also be passed after the mode, using commas as separator.
++
++       Sample usage: 720x480,rotate=180 - 720x480 mode, rotated by 180 degrees
++
++Valid options are:
++
++  - reflect_x (boolean): Perform an axial symmetry on the X axis
++  - reflect_y (boolean): Perform an axial symmetry on the Y axis
++  - rotate (integer): Rotate the initial framebuffer by x
++    degrees. Valid values are 0, 90, 180 and 270.
++
++
+ ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
+ What is the VESA(TM) Coordinated Video Timings (CVT)?
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -2469,6 +2469,7 @@ static void drm_setup_crtc_rotation(stru
+                                   struct drm_connector *connector)
+ {
+       struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
++      struct drm_cmdline_mode *cmdline;
+       uint64_t valid_mask = 0;
+       int i, rotation;
+@@ -2488,6 +2489,35 @@ static void drm_setup_crtc_rotation(stru
+               rotation = DRM_MODE_ROTATE_0;
+       }
++      /**
++       * The panel already defined the default rotation
++       * through its orientation. Whatever has been provided
++       * on the command line needs to be added to that.
++       *
++       * Unfortunately, the rotations are at different bit
++       * indices, so the math to add them up are not as
++       * trivial as they could.
++       *
++       * Reflections on the other hand are pretty trivial to deal with, a
++       * simple XOR between the two handle the addition nicely.
++       */
++      cmdline = &connector->cmdline_mode;
++      if (cmdline->specified) {
++              unsigned int cmdline_rest, panel_rest;
++              unsigned int cmdline_rot, panel_rot;
++              unsigned int sum_rot, sum_rest;
++
++              panel_rot = ilog2(rotation & DRM_MODE_ROTATE_MASK);
++              cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
++              sum_rot = (panel_rot + cmdline_rot) % 4;
++
++              panel_rest = rotation & ~DRM_MODE_ROTATE_MASK;
++              cmdline_rest = cmdline->rotation_reflection & ~DRM_MODE_ROTATE_MASK;
++              sum_rest = panel_rest ^ cmdline_rest;
++
++              rotation = (1 << sum_rot) | sum_rest;
++      }
++
+       /*
+        * TODO: support 90 / 270 degree hardware rotation,
+        * depending on the hardware this may require the framebuffer
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1560,6 +1560,71 @@ static int drm_mode_parse_cmdline_res_mo
+       return 0;
+ }
++static int drm_mode_parse_cmdline_options(char *str, size_t len,
++                                        struct drm_connector *connector,
++                                        struct drm_cmdline_mode *mode)
++{
++      unsigned int rotation = 0;
++      char *sep = str;
++
++      while ((sep = strchr(sep, ','))) {
++              char *delim, *option;
++
++              option = sep + 1;
++              delim = strchr(option, '=');
++              if (!delim) {
++                      delim = strchr(option, ',');
++
++                      if (!delim)
++                              delim = str + len;
++              }
++
++              if (!strncmp(option, "rotate", delim - option)) {
++                      const char *value = delim + 1;
++                      unsigned int deg;
++
++                      deg = simple_strtol(value, &sep, 10);
++
++                      /* Make sure we have parsed something */
++                      if (sep == value)
++                              return -EINVAL;
++
++                      switch (deg) {
++                      case 0:
++                              rotation |= DRM_MODE_ROTATE_0;
++                              break;
++
++                      case 90:
++                              rotation |= DRM_MODE_ROTATE_90;
++                              break;
++
++                      case 180:
++                              rotation |= DRM_MODE_ROTATE_180;
++                              break;
++
++                      case 270:
++                              rotation |= DRM_MODE_ROTATE_270;
++                              break;
++
++                      default:
++                              return -EINVAL;
++                      }
++              } else if (!strncmp(option, "reflect_x", delim - option)) {
++                      rotation |= DRM_MODE_REFLECT_X;
++                      sep = delim;
++              } else if (!strncmp(option, "reflect_y", delim - option)) {
++                      rotation |= DRM_MODE_REFLECT_Y;
++                      sep = delim;
++              } else {
++                      return -EINVAL;
++              }
++      }
++
++      mode->rotation_reflection = rotation;
++
++      return 0;
++}
++
+ /**
+  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
+  * @mode_option: optional per connector mode option
+@@ -1575,6 +1640,10 @@ static int drm_mode_parse_cmdline_res_mo
+  *
+  *    <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
+  *
++ * Additionals options can be provided following the mode, using a comma to
++ * separate each option. Valid options can be found in
++ * Documentation/fb/modedb.txt.
++ *
+  * The intermediate drm_cmdline_mode structure is required to store additional
+  * options from the command line modline like the force-enable/disable flag.
+  *
+@@ -1587,9 +1656,10 @@ bool drm_mode_parse_command_line_for_con
+ {
+       const char *name;
+       bool named_mode = false, parse_extras = false;
+-      unsigned int bpp_off = 0, refresh_off = 0;
++      unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
+       unsigned int mode_end = 0;
+       char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
++      char *options_ptr = NULL;
+       char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
+       int ret;
+@@ -1638,13 +1708,18 @@ bool drm_mode_parse_command_line_for_con
+               mode->refresh_specified = true;
+       }
++      /* Locate the start of named options */
++      options_ptr = strchr(name, ',');
++      if (options_ptr)
++              options_off = options_ptr - name;
++
+       /* Locate the end of the name / resolution, and parse it */
+-      if (bpp_ptr && refresh_ptr) {
+-              mode_end = min(bpp_off, refresh_off);
+-      } else if (bpp_ptr) {
++      if (bpp_ptr) {
+               mode_end = bpp_off;
+       } else if (refresh_ptr) {
+               mode_end = refresh_off;
++      } else if (options_ptr) {
++              mode_end = options_off;
+       } else {
+               mode_end = strlen(name);
+               parse_extras = true;
+@@ -1686,24 +1761,23 @@ bool drm_mode_parse_command_line_for_con
+       else if (refresh_ptr)
+               extra_ptr = refresh_end_ptr;
+-      if (extra_ptr) {
+-              if (!named_mode) {
+-                      int len = strlen(name) - (extra_ptr - name);
+-
+-                      ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
+-                                                         connector, mode);
+-                      if (ret)
+-                              return false;
+-              } else {
+-                      int remaining = strlen(name) - (extra_ptr - name);
++      if (extra_ptr &&
++          extra_ptr != options_ptr) {
++              int len = strlen(name) - (extra_ptr - name);
+-                      /*
+-                       * We still have characters to process, while
+-                       * we shouldn't have any
+-                       */
+-                      if (remaining > 0)
+-                              return false;
+-              }
++              ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
++                                                 connector, mode);
++              if (ret)
++                      return false;
++      }
++
++      if (options_ptr) {
++              int len = strlen(name) - (options_ptr - name);
++
++              ret = drm_mode_parse_cmdline_options(options_ptr, len,
++                                                   connector, mode);
++              if (ret)
++                      return false;
+       }
+       return true;
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -857,6 +857,16 @@ struct drm_cmdline_mode {
+        * state to one of the DRM_FORCE_* values.
+        */
+       enum drm_connector_force force;
++
++      /**
++       * @rotation_reflection:
++       *
++       * Initial rotation and reflection of the mode setup from the
++       * command line. See DRM_MODE_ROTATE_* and
++       * DRM_MODE_REFLECT_*. The only rotations supported are
++       * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
++       */
++      unsigned int rotation_reflection;
+ };
+ /**
diff --git a/target/linux/brcm2708/patches-4.19/950-0641-drm-modes-Rewrite-the-command-line-parser.patch b/target/linux/brcm2708/patches-4.19/950-0641-drm-modes-Rewrite-the-command-line-parser.patch
deleted file mode 100644 (file)
index 24c25d6..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-From 3508a8548f13be68b6d098ad99a7bc1fc1810f76 Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:49 +0200
-Subject: [PATCH] drm/modes: Rewrite the command line parser
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit e08ab74bd4c7a5fe311bc05f32dbb4f1e7fa3428 upstream.
-
-Rewrite the command line parser in order to get away from the state machine
-parsing the video mode lines.
-
-Hopefully, this will allow to extend it more easily to support named modes
-and / or properties set directly on the command line.
-
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/e32cd4009153b184103554009135c7bf7c9975d7.1560783090.git-series.maxime.ripard@bootlin.com
----
- drivers/gpu/drm/drm_modes.c | 325 +++++++++++++++++++++++-------------
- 1 file changed, 210 insertions(+), 115 deletions(-)
-
---- a/drivers/gpu/drm/drm_modes.c
-+++ b/drivers/gpu/drm/drm_modes.c
-@@ -30,6 +30,7 @@
-  * authorization from the copyright holder(s) and author(s).
-  */
-+#include <linux/ctype.h>
- #include <linux/list.h>
- #include <linux/list_sort.h>
- #include <linux/export.h>
-@@ -1414,6 +1415,151 @@ void drm_connector_list_update(struct dr
- }
- EXPORT_SYMBOL(drm_connector_list_update);
-+static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
-+                                    struct drm_cmdline_mode *mode)
-+{
-+      unsigned int bpp;
-+
-+      if (str[0] != '-')
-+              return -EINVAL;
-+
-+      str++;
-+      bpp = simple_strtol(str, end_ptr, 10);
-+      if (*end_ptr == str)
-+              return -EINVAL;
-+
-+      mode->bpp = bpp;
-+      mode->bpp_specified = true;
-+
-+      return 0;
-+}
-+
-+static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
-+                                        struct drm_cmdline_mode *mode)
-+{
-+      unsigned int refresh;
-+
-+      if (str[0] != '@')
-+              return -EINVAL;
-+
-+      str++;
-+      refresh = simple_strtol(str, end_ptr, 10);
-+      if (*end_ptr == str)
-+              return -EINVAL;
-+
-+      mode->refresh = refresh;
-+      mode->refresh_specified = true;
-+
-+      return 0;
-+}
-+
-+static int drm_mode_parse_cmdline_extra(const char *str, int length,
-+                                      struct drm_connector *connector,
-+                                      struct drm_cmdline_mode *mode)
-+{
-+      int i;
-+
-+      for (i = 0; i < length; i++) {
-+              switch (str[i]) {
-+              case 'i':
-+                      mode->interlace = true;
-+                      break;
-+              case 'm':
-+                      mode->margins = true;
-+                      break;
-+              case 'D':
-+                      if (mode->force != DRM_FORCE_UNSPECIFIED)
-+                              return -EINVAL;
-+
-+                      if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
-+                          (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
-+                              mode->force = DRM_FORCE_ON;
-+                      else
-+                              mode->force = DRM_FORCE_ON_DIGITAL;
-+                      break;
-+              case 'd':
-+                      if (mode->force != DRM_FORCE_UNSPECIFIED)
-+                              return -EINVAL;
-+
-+                      mode->force = DRM_FORCE_OFF;
-+                      break;
-+              case 'e':
-+                      if (mode->force != DRM_FORCE_UNSPECIFIED)
-+                              return -EINVAL;
-+
-+                      mode->force = DRM_FORCE_ON;
-+                      break;
-+              default:
-+                      return -EINVAL;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
-+                                         bool extras,
-+                                         struct drm_connector *connector,
-+                                         struct drm_cmdline_mode *mode)
-+{
-+      const char *str_start = str;
-+      bool rb = false, cvt = false;
-+      int xres = 0, yres = 0;
-+      int remaining, i;
-+      char *end_ptr;
-+
-+      xres = simple_strtol(str, &end_ptr, 10);
-+      if (end_ptr == str)
-+              return -EINVAL;
-+
-+      if (end_ptr[0] != 'x')
-+              return -EINVAL;
-+      end_ptr++;
-+
-+      str = end_ptr;
-+      yres = simple_strtol(str, &end_ptr, 10);
-+      if (end_ptr == str)
-+              return -EINVAL;
-+
-+      remaining = length - (end_ptr - str_start);
-+      if (remaining < 0)
-+              return -EINVAL;
-+
-+      for (i = 0; i < remaining; i++) {
-+              switch (end_ptr[i]) {
-+              case 'M':
-+                      cvt = true;
-+                      break;
-+              case 'R':
-+                      rb = true;
-+                      break;
-+              default:
-+                      /*
-+                       * Try to pass that to our extras parsing
-+                       * function to handle the case where the
-+                       * extras are directly after the resolution
-+                       */
-+                      if (extras) {
-+                              int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
-+                                                                     1,
-+                                                                     connector,
-+                                                                     mode);
-+                              if (ret)
-+                                      return ret;
-+                      } else {
-+                              return -EINVAL;
-+                      }
-+              }
-+      }
-+
-+      mode->xres = xres;
-+      mode->yres = yres;
-+      mode->cvt = cvt;
-+      mode->rb = rb;
-+
-+      return 0;
-+}
-+
- /**
-  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
-  * @mode_option: optional per connector mode option
-@@ -1440,13 +1586,12 @@ bool drm_mode_parse_command_line_for_con
-                                              struct drm_cmdline_mode *mode)
- {
-       const char *name;
--      unsigned int namelen;
--      bool res_specified = false, bpp_specified = false, refresh_specified = false;
--      unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
--      bool yres_specified = false, cvt = false, rb = false;
--      bool interlace = false, margins = false, was_digit = false;
--      int i;
--      enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
-+      bool parse_extras = false;
-+      unsigned int bpp_off = 0, refresh_off = 0;
-+      unsigned int mode_end = 0;
-+      char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
-+      char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
-+      int ret;
- #ifdef CONFIG_FB
-       if (!mode_option)
-@@ -1459,127 +1604,77 @@ bool drm_mode_parse_command_line_for_con
-       }
-       name = mode_option;
--      namelen = strlen(name);
--      for (i = namelen-1; i >= 0; i--) {
--              switch (name[i]) {
--              case '@':
--                      if (!refresh_specified && !bpp_specified &&
--                          !yres_specified && !cvt && !rb && was_digit) {
--                              refresh = simple_strtol(&name[i+1], NULL, 10);
--                              refresh_specified = true;
--                              was_digit = false;
--                      } else
--                              goto done;
--                      break;
--              case '-':
--                      if (!bpp_specified && !yres_specified && !cvt &&
--                          !rb && was_digit) {
--                              bpp = simple_strtol(&name[i+1], NULL, 10);
--                              bpp_specified = true;
--                              was_digit = false;
--                      } else
--                              goto done;
--                      break;
--              case 'x':
--                      if (!yres_specified && was_digit) {
--                              yres = simple_strtol(&name[i+1], NULL, 10);
--                              yres_specified = true;
--                              was_digit = false;
--                      } else
--                              goto done;
--                      break;
--              case '0' ... '9':
--                      was_digit = true;
--                      break;
--              case 'M':
--                      if (yres_specified || cvt || was_digit)
--                              goto done;
--                      cvt = true;
--                      break;
--              case 'R':
--                      if (yres_specified || cvt || rb || was_digit)
--                              goto done;
--                      rb = true;
--                      break;
--              case 'm':
--                      if (cvt || yres_specified || was_digit)
--                              goto done;
--                      margins = true;
--                      break;
--              case 'i':
--                      if (cvt || yres_specified || was_digit)
--                              goto done;
--                      interlace = true;
--                      break;
--              case 'e':
--                      if (yres_specified || bpp_specified || refresh_specified ||
--                          was_digit || (force != DRM_FORCE_UNSPECIFIED))
--                              goto done;
--                      force = DRM_FORCE_ON;
--                      break;
--              case 'D':
--                      if (yres_specified || bpp_specified || refresh_specified ||
--                          was_digit || (force != DRM_FORCE_UNSPECIFIED))
--                              goto done;
-+      if (!isdigit(name[0]))
-+              return false;
--                      if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
--                          (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
--                              force = DRM_FORCE_ON;
--                      else
--                              force = DRM_FORCE_ON_DIGITAL;
--                      break;
--              case 'd':
--                      if (yres_specified || bpp_specified || refresh_specified ||
--                          was_digit || (force != DRM_FORCE_UNSPECIFIED))
--                              goto done;
-+      /* Try to locate the bpp and refresh specifiers, if any */
-+      bpp_ptr = strchr(name, '-');
-+      if (bpp_ptr) {
-+              bpp_off = bpp_ptr - name;
-+              mode->bpp_specified = true;
-+      }
--                      force = DRM_FORCE_OFF;
--                      break;
--              default:
--                      goto done;
--              }
-+      refresh_ptr = strchr(name, '@');
-+      if (refresh_ptr) {
-+              refresh_off = refresh_ptr - name;
-+              mode->refresh_specified = true;
-       }
--      if (i < 0 && yres_specified) {
--              char *ch;
--              xres = simple_strtol(name, &ch, 10);
--              if ((ch != NULL) && (*ch == 'x'))
--                      res_specified = true;
--              else
--                      i = ch - name;
--      } else if (!yres_specified && was_digit) {
--              /* catch mode that begins with digits but has no 'x' */
--              i = 0;
--      }
--done:
--      if (i >= 0) {
--              pr_warn("[drm] parse error at position %i in video mode '%s'\n",
--                      i, name);
--              mode->specified = false;
--              return false;
-+      /* Locate the end of the name / resolution, and parse it */
-+      if (bpp_ptr && refresh_ptr) {
-+              mode_end = min(bpp_off, refresh_off);
-+      } else if (bpp_ptr) {
-+              mode_end = bpp_off;
-+      } else if (refresh_ptr) {
-+              mode_end = refresh_off;
-+      } else {
-+              mode_end = strlen(name);
-+              parse_extras = true;
-       }
--      if (res_specified) {
--              mode->specified = true;
--              mode->xres = xres;
--              mode->yres = yres;
-+      ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
-+                                            parse_extras,
-+                                            connector,
-+                                            mode);
-+      if (ret)
-+              return false;
-+      mode->specified = true;
-+
-+      if (bpp_ptr) {
-+              ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
-+              if (ret)
-+                      return false;
-       }
--      if (refresh_specified) {
--              mode->refresh_specified = true;
--              mode->refresh = refresh;
-+      if (refresh_ptr) {
-+              ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
-+                                                   &refresh_end_ptr, mode);
-+              if (ret)
-+                      return false;
-       }
--      if (bpp_specified) {
--              mode->bpp_specified = true;
--              mode->bpp = bpp;
-+      /*
-+       * Locate the end of the bpp / refresh, and parse the extras
-+       * if relevant
-+       */
-+      if (bpp_ptr && refresh_ptr)
-+              extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
-+      else if (bpp_ptr)
-+              extra_ptr = bpp_end_ptr;
-+      else if (refresh_ptr)
-+              extra_ptr = refresh_end_ptr;
-+
-+      if (extra_ptr) {
-+              int remaining = strlen(name) - (extra_ptr - name);
-+
-+              /*
-+               * We still have characters to process, while
-+               * we shouldn't have any
-+               */
-+              if (remaining > 0)
-+                      return false;
-       }
--      mode->rb = rb;
--      mode->cvt = cvt;
--      mode->interlace = interlace;
--      mode->margins = margins;
--      mode->force = force;
-       return true;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0642-drm-connector-Introduce-a-TV-margins-structure.patch b/target/linux/brcm2708/patches-4.19/950-0642-drm-connector-Introduce-a-TV-margins-structure.patch
new file mode 100644 (file)
index 0000000..7c6f415
--- /dev/null
@@ -0,0 +1,81 @@
+From 6261047a83258900e57a0a699ec7954360c6e7f3 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:51 +0200
+Subject: [PATCH] drm/connector: Introduce a TV margins structure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 22045e8e52bd802f743f0471242782fc3b479707 upstream.
+
+The TV margins has been defined as a structure inside the
+drm_connector_state structure so far. However, we will need it in other
+structures as well, so let's move that structure definition so that it can
+be reused.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/38b773b03f15ec7a135cdf8f7db669e5ada20cf2.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ include/drm/drm_connector.h | 41 +++++++++++++++++++++++++++----------
+ 1 file changed, 30 insertions(+), 11 deletions(-)
+
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -344,13 +344,37 @@ int drm_display_info_set_bus_formats(str
+                                    unsigned int num_formats);
+ /**
++ * struct drm_connector_tv_margins - TV connector related margins
++ *
++ * Describes the margins in pixels to put around the image on TV
++ * connectors to deal with overscan.
++ */
++struct drm_connector_tv_margins {
++      /**
++       * @bottom: Bottom margin in pixels.
++       */
++      unsigned int bottom;
++
++      /**
++       * @left: Left margin in pixels.
++       */
++      unsigned int left;
++
++      /**
++       * @right: Right margin in pixels.
++       */
++      unsigned int right;
++
++      /**
++       * @top: Top margin in pixels.
++       */
++      unsigned int top;
++};
++
++/**
+  * struct drm_tv_connector_state - TV connector related states
+  * @subconnector: selected subconnector
+- * @margins: margins (all margins are expressed in pixels)
+- * @margins.left: left margin
+- * @margins.right: right margin
+- * @margins.top: top margin
+- * @margins.bottom: bottom margin
++ * @margins: TV margins
+  * @mode: TV mode
+  * @brightness: brightness in percent
+  * @contrast: contrast in percent
+@@ -361,12 +385,7 @@ int drm_display_info_set_bus_formats(str
+  */
+ struct drm_tv_connector_state {
+       enum drm_mode_subconnector subconnector;
+-      struct {
+-              unsigned int left;
+-              unsigned int right;
+-              unsigned int top;
+-              unsigned int bottom;
+-      } margins;
++      struct drm_connector_tv_margins margins;
+       unsigned int mode;
+       unsigned int brightness;
+       unsigned int contrast;
diff --git a/target/linux/brcm2708/patches-4.19/950-0642-drm-modes-Support-modes-names-on-the-command-line.patch b/target/linux/brcm2708/patches-4.19/950-0642-drm-modes-Support-modes-names-on-the-command-line.patch
deleted file mode 100644 (file)
index 1cacab2..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-From 2cea4924c69b6be5cfe8d976810ccf76a3991230 Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:50 +0200
-Subject: [PATCH] drm/modes: Support modes names on the command line
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 3aeeb13d899627fe2b86bdbdcd0927cf7192234f upstream.
-Minor conflict resolution as upstream has moved functions
-from drm_fb_helper.c to a new drm_client_modeset.c
-
-The drm subsystem also uses the video= kernel parameter, and in the
-documentation refers to the fbdev documentation for that parameter.
-
-However, that documentation also says that instead of giving the mode using
-its resolution we can also give a name. However, DRM doesn't handle that
-case at the moment. Even though in most case it shouldn't make any
-difference, it might be useful for analog modes, where different standards
-might have the same resolution, but still have a few different parameters
-that are not encoded in the modes (NTSC vs NTSC-J vs PAL-M for example).
-
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/18443e0c3bdbbd16cea4ec63bc7f2079b820b43b.1560783090.git-series.maxime.ripard@bootlin.com
----
- drivers/gpu/drm/drm_connector.c |  3 +-
- drivers/gpu/drm/drm_fb_helper.c |  4 +++
- drivers/gpu/drm/drm_modes.c     | 62 ++++++++++++++++++++++++---------
- include/drm/drm_connector.h     |  7 ++++
- 4 files changed, 59 insertions(+), 17 deletions(-)
-
---- a/drivers/gpu/drm/drm_connector.c
-+++ b/drivers/gpu/drm/drm_connector.c
-@@ -135,8 +135,9 @@ static void drm_connector_get_cmdline_mo
-               connector->force = mode->force;
-       }
--      DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
-+      DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
-                     connector->name,
-+                    mode->name ? mode->name : "",
-                     mode->xres, mode->yres,
-                     mode->refresh_specified ? mode->refresh : 60,
-                     mode->rb ? " reduced blanking" : "",
---- a/drivers/gpu/drm/drm_fb_helper.c
-+++ b/drivers/gpu/drm/drm_fb_helper.c
-@@ -2104,6 +2104,10 @@ struct drm_display_mode *drm_pick_cmdlin
-       prefer_non_interlace = !cmdline_mode->interlace;
- again:
-       list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
-+              /* Check (optional) mode name first */
-+              if (!strcmp(mode->name, cmdline_mode->name))
-+                      return mode;
-+
-               /* check width/height */
-               if (mode->hdisplay != cmdline_mode->xres ||
-                   mode->vdisplay != cmdline_mode->yres)
---- a/drivers/gpu/drm/drm_modes.c
-+++ b/drivers/gpu/drm/drm_modes.c
-@@ -1586,7 +1586,7 @@ bool drm_mode_parse_command_line_for_con
-                                              struct drm_cmdline_mode *mode)
- {
-       const char *name;
--      bool parse_extras = false;
-+      bool named_mode = false, parse_extras = false;
-       unsigned int bpp_off = 0, refresh_off = 0;
-       unsigned int mode_end = 0;
-       char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
-@@ -1605,8 +1605,22 @@ bool drm_mode_parse_command_line_for_con
-       name = mode_option;
--      if (!isdigit(name[0]))
--              return false;
-+      /*
-+       * This is a bit convoluted. To differentiate between the
-+       * named modes and poorly formatted resolutions, we need a
-+       * bunch of things:
-+       *   - We need to make sure that the first character (which
-+       *     would be our resolution in X) is a digit.
-+       *   - However, if the X resolution is missing, then we end up
-+       *     with something like x<yres>, with our first character
-+       *     being an alpha-numerical character, which would be
-+       *     considered a named mode.
-+       *
-+       * If this isn't enough, we should add more heuristics here,
-+       * and matching unit-tests.
-+       */
-+      if (!isdigit(name[0]) && name[0] != 'x')
-+              named_mode = true;
-       /* Try to locate the bpp and refresh specifiers, if any */
-       bpp_ptr = strchr(name, '-');
-@@ -1617,6 +1631,9 @@ bool drm_mode_parse_command_line_for_con
-       refresh_ptr = strchr(name, '@');
-       if (refresh_ptr) {
-+              if (named_mode)
-+                      return false;
-+
-               refresh_off = refresh_ptr - name;
-               mode->refresh_specified = true;
-       }
-@@ -1633,12 +1650,16 @@ bool drm_mode_parse_command_line_for_con
-               parse_extras = true;
-       }
--      ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
--                                            parse_extras,
--                                            connector,
--                                            mode);
--      if (ret)
--              return false;
-+      if (named_mode) {
-+              strncpy(mode->name, name, mode_end);
-+      } else {
-+              ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
-+                                                    parse_extras,
-+                                                    connector,
-+                                                    mode);
-+              if (ret)
-+                      return false;
-+      }
-       mode->specified = true;
-       if (bpp_ptr) {
-@@ -1666,14 +1687,23 @@ bool drm_mode_parse_command_line_for_con
-               extra_ptr = refresh_end_ptr;
-       if (extra_ptr) {
--              int remaining = strlen(name) - (extra_ptr - name);
-+              if (!named_mode) {
-+                      int len = strlen(name) - (extra_ptr - name);
--              /*
--               * We still have characters to process, while
--               * we shouldn't have any
--               */
--              if (remaining > 0)
--                      return false;
-+                      ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
-+                                                         connector, mode);
-+                      if (ret)
-+                              return false;
-+              } else {
-+                      int remaining = strlen(name) - (extra_ptr - name);
-+
-+                      /*
-+                       * We still have characters to process, while
-+                       * we shouldn't have any
-+                       */
-+                      if (remaining > 0)
-+                              return false;
-+              }
-       }
-       return true;
---- a/include/drm/drm_connector.h
-+++ b/include/drm/drm_connector.h
-@@ -765,6 +765,13 @@ struct drm_connector_funcs {
-  */
- struct drm_cmdline_mode {
-       /**
-+       * @name:
-+       *
-+       * Name of the mode.
-+       */
-+      char name[DRM_DISPLAY_MODE_LEN];
-+
-+      /**
-        * @specified:
-        *
-        * Has a mode been read from the command-line?
diff --git a/target/linux/brcm2708/patches-4.19/950-0643-drm-modes-Allow-to-specify-rotation-and-reflection-o.patch b/target/linux/brcm2708/patches-4.19/950-0643-drm-modes-Allow-to-specify-rotation-and-reflection-o.patch
deleted file mode 100644 (file)
index 0b2a185..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-From 5a8ccd79b6bad32e52620a94199bf1af2e19708e Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:51 +0200
-Subject: [PATCH] drm/modes: Allow to specify rotation and reflection
- on the commandline
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Commit 1bf4e09227c345e246062285eba4b8fe660e512e upstream.
-Minor conflict resolution as upstream has moved functions
-from drm_fb_helper.c to a new drm_client_modeset.c
-
-Rotations and reflections setup are needed in some scenarios to initialise
-properly the initial framebuffer. Some drivers already had a bunch of
-quirks to deal with this, such as either a private kernel command line
-parameter (omapdss) or on the device tree (various panels).
-
-In order to accomodate this, let's create a video mode parameter to deal
-with the rotation and reflexion.
-
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/777da16e42db757c1f5b414b5ca34507097fed5c.1560783090.git-series.maxime.ripard@bootlin.com
----
- Documentation/fb/modedb.txt     |  12 ++++
- drivers/gpu/drm/drm_fb_helper.c |  30 +++++++++
- drivers/gpu/drm/drm_modes.c     | 114 ++++++++++++++++++++++++++------
- include/drm/drm_connector.h     |  10 +++
- 4 files changed, 146 insertions(+), 20 deletions(-)
-
---- a/Documentation/fb/modedb.txt
-+++ b/Documentation/fb/modedb.txt
-@@ -51,6 +51,18 @@ To force the VGA output to be enabled an
- Specifying the option multiple times for different ports is possible, e.g.:
-     video=LVDS-1:d video=HDMI-1:D
-+Options can also be passed after the mode, using commas as separator.
-+
-+       Sample usage: 720x480,rotate=180 - 720x480 mode, rotated by 180 degrees
-+
-+Valid options are:
-+
-+  - reflect_x (boolean): Perform an axial symmetry on the X axis
-+  - reflect_y (boolean): Perform an axial symmetry on the Y axis
-+  - rotate (integer): Rotate the initial framebuffer by x
-+    degrees. Valid values are 0, 90, 180 and 270.
-+
-+
- ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
- What is the VESA(TM) Coordinated Video Timings (CVT)?
---- a/drivers/gpu/drm/drm_fb_helper.c
-+++ b/drivers/gpu/drm/drm_fb_helper.c
-@@ -2469,6 +2469,7 @@ static void drm_setup_crtc_rotation(stru
-                                   struct drm_connector *connector)
- {
-       struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
-+      struct drm_cmdline_mode *cmdline;
-       uint64_t valid_mask = 0;
-       int i, rotation;
-@@ -2488,6 +2489,35 @@ static void drm_setup_crtc_rotation(stru
-               rotation = DRM_MODE_ROTATE_0;
-       }
-+      /**
-+       * The panel already defined the default rotation
-+       * through its orientation. Whatever has been provided
-+       * on the command line needs to be added to that.
-+       *
-+       * Unfortunately, the rotations are at different bit
-+       * indices, so the math to add them up are not as
-+       * trivial as they could.
-+       *
-+       * Reflections on the other hand are pretty trivial to deal with, a
-+       * simple XOR between the two handle the addition nicely.
-+       */
-+      cmdline = &connector->cmdline_mode;
-+      if (cmdline->specified) {
-+              unsigned int cmdline_rest, panel_rest;
-+              unsigned int cmdline_rot, panel_rot;
-+              unsigned int sum_rot, sum_rest;
-+
-+              panel_rot = ilog2(rotation & DRM_MODE_ROTATE_MASK);
-+              cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
-+              sum_rot = (panel_rot + cmdline_rot) % 4;
-+
-+              panel_rest = rotation & ~DRM_MODE_ROTATE_MASK;
-+              cmdline_rest = cmdline->rotation_reflection & ~DRM_MODE_ROTATE_MASK;
-+              sum_rest = panel_rest ^ cmdline_rest;
-+
-+              rotation = (1 << sum_rot) | sum_rest;
-+      }
-+
-       /*
-        * TODO: support 90 / 270 degree hardware rotation,
-        * depending on the hardware this may require the framebuffer
---- a/drivers/gpu/drm/drm_modes.c
-+++ b/drivers/gpu/drm/drm_modes.c
-@@ -1560,6 +1560,71 @@ static int drm_mode_parse_cmdline_res_mo
-       return 0;
- }
-+static int drm_mode_parse_cmdline_options(char *str, size_t len,
-+                                        struct drm_connector *connector,
-+                                        struct drm_cmdline_mode *mode)
-+{
-+      unsigned int rotation = 0;
-+      char *sep = str;
-+
-+      while ((sep = strchr(sep, ','))) {
-+              char *delim, *option;
-+
-+              option = sep + 1;
-+              delim = strchr(option, '=');
-+              if (!delim) {
-+                      delim = strchr(option, ',');
-+
-+                      if (!delim)
-+                              delim = str + len;
-+              }
-+
-+              if (!strncmp(option, "rotate", delim - option)) {
-+                      const char *value = delim + 1;
-+                      unsigned int deg;
-+
-+                      deg = simple_strtol(value, &sep, 10);
-+
-+                      /* Make sure we have parsed something */
-+                      if (sep == value)
-+                              return -EINVAL;
-+
-+                      switch (deg) {
-+                      case 0:
-+                              rotation |= DRM_MODE_ROTATE_0;
-+                              break;
-+
-+                      case 90:
-+                              rotation |= DRM_MODE_ROTATE_90;
-+                              break;
-+
-+                      case 180:
-+                              rotation |= DRM_MODE_ROTATE_180;
-+                              break;
-+
-+                      case 270:
-+                              rotation |= DRM_MODE_ROTATE_270;
-+                              break;
-+
-+                      default:
-+                              return -EINVAL;
-+                      }
-+              } else if (!strncmp(option, "reflect_x", delim - option)) {
-+                      rotation |= DRM_MODE_REFLECT_X;
-+                      sep = delim;
-+              } else if (!strncmp(option, "reflect_y", delim - option)) {
-+                      rotation |= DRM_MODE_REFLECT_Y;
-+                      sep = delim;
-+              } else {
-+                      return -EINVAL;
-+              }
-+      }
-+
-+      mode->rotation_reflection = rotation;
-+
-+      return 0;
-+}
-+
- /**
-  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
-  * @mode_option: optional per connector mode option
-@@ -1575,6 +1640,10 @@ static int drm_mode_parse_cmdline_res_mo
-  *
-  *    <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
-  *
-+ * Additionals options can be provided following the mode, using a comma to
-+ * separate each option. Valid options can be found in
-+ * Documentation/fb/modedb.txt.
-+ *
-  * The intermediate drm_cmdline_mode structure is required to store additional
-  * options from the command line modline like the force-enable/disable flag.
-  *
-@@ -1587,9 +1656,10 @@ bool drm_mode_parse_command_line_for_con
- {
-       const char *name;
-       bool named_mode = false, parse_extras = false;
--      unsigned int bpp_off = 0, refresh_off = 0;
-+      unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
-       unsigned int mode_end = 0;
-       char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
-+      char *options_ptr = NULL;
-       char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
-       int ret;
-@@ -1638,13 +1708,18 @@ bool drm_mode_parse_command_line_for_con
-               mode->refresh_specified = true;
-       }
-+      /* Locate the start of named options */
-+      options_ptr = strchr(name, ',');
-+      if (options_ptr)
-+              options_off = options_ptr - name;
-+
-       /* Locate the end of the name / resolution, and parse it */
--      if (bpp_ptr && refresh_ptr) {
--              mode_end = min(bpp_off, refresh_off);
--      } else if (bpp_ptr) {
-+      if (bpp_ptr) {
-               mode_end = bpp_off;
-       } else if (refresh_ptr) {
-               mode_end = refresh_off;
-+      } else if (options_ptr) {
-+              mode_end = options_off;
-       } else {
-               mode_end = strlen(name);
-               parse_extras = true;
-@@ -1686,24 +1761,23 @@ bool drm_mode_parse_command_line_for_con
-       else if (refresh_ptr)
-               extra_ptr = refresh_end_ptr;
--      if (extra_ptr) {
--              if (!named_mode) {
--                      int len = strlen(name) - (extra_ptr - name);
--
--                      ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
--                                                         connector, mode);
--                      if (ret)
--                              return false;
--              } else {
--                      int remaining = strlen(name) - (extra_ptr - name);
-+      if (extra_ptr &&
-+          extra_ptr != options_ptr) {
-+              int len = strlen(name) - (extra_ptr - name);
--                      /*
--                       * We still have characters to process, while
--                       * we shouldn't have any
--                       */
--                      if (remaining > 0)
--                              return false;
--              }
-+              ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
-+                                                 connector, mode);
-+              if (ret)
-+                      return false;
-+      }
-+
-+      if (options_ptr) {
-+              int len = strlen(name) - (options_ptr - name);
-+
-+              ret = drm_mode_parse_cmdline_options(options_ptr, len,
-+                                                   connector, mode);
-+              if (ret)
-+                      return false;
-       }
-       return true;
---- a/include/drm/drm_connector.h
-+++ b/include/drm/drm_connector.h
-@@ -857,6 +857,16 @@ struct drm_cmdline_mode {
-        * state to one of the DRM_FORCE_* values.
-        */
-       enum drm_connector_force force;
-+
-+      /**
-+       * @rotation_reflection:
-+       *
-+       * Initial rotation and reflection of the mode setup from the
-+       * command line. See DRM_MODE_ROTATE_* and
-+       * DRM_MODE_REFLECT_*. The only rotations supported are
-+       * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
-+       */
-+      unsigned int rotation_reflection;
- };
- /**
diff --git a/target/linux/brcm2708/patches-4.19/950-0643-drm-modes-Parse-overscan-properties.patch b/target/linux/brcm2708/patches-4.19/950-0643-drm-modes-Parse-overscan-properties.patch
new file mode 100644 (file)
index 0000000..f8de9b5
--- /dev/null
@@ -0,0 +1,102 @@
+From 99b367ee521e48beae92bea59515dd0f08f2e55b Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:51 +0200
+Subject: [PATCH] drm/modes: Parse overscan properties
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 3d46a3007cd8f73bae502bf5c171977b91d7aacc upstream.
+
+Properly configuring the overscan properties might be needed for the
+initial setup of the framebuffer for display that still have overscan.
+Let's allow for more properties on the kernel command line to setup each
+margin.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/e481f1628e3768ca49226ec2115cfa4dfcbd5e4c.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ Documentation/fb/modedb.txt |  2 ++
+ drivers/gpu/drm/drm_modes.c | 44 +++++++++++++++++++++++++++++++++++++
+ include/drm/drm_connector.h |  5 +++++
+ 3 files changed, 51 insertions(+)
+
+--- a/Documentation/fb/modedb.txt
++++ b/Documentation/fb/modedb.txt
+@@ -57,6 +57,8 @@ Options can also be passed after the mod
+ Valid options are:
++  - margin_top, margin_bottom, margin_left, margin_right (integer):
++    Number of pixels in the margins, typically to deal with overscan on TVs
+   - reflect_x (boolean): Perform an axial symmetry on the X axis
+   - reflect_y (boolean): Perform an axial symmetry on the Y axis
+   - rotate (integer): Rotate the initial framebuffer by x
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1615,6 +1615,50 @@ static int drm_mode_parse_cmdline_option
+               } else if (!strncmp(option, "reflect_y", delim - option)) {
+                       rotation |= DRM_MODE_REFLECT_Y;
+                       sep = delim;
++              } else if (!strncmp(option, "margin_right", delim - option)) {
++                      const char *value = delim + 1;
++                      unsigned int margin;
++
++                      margin = simple_strtol(value, &sep, 10);
++
++                      /* Make sure we have parsed something */
++                      if (sep == value)
++                              return -EINVAL;
++
++                      mode->tv_margins.right = margin;
++              } else if (!strncmp(option, "margin_left", delim - option)) {
++                      const char *value = delim + 1;
++                      unsigned int margin;
++
++                      margin = simple_strtol(value, &sep, 10);
++
++                      /* Make sure we have parsed something */
++                      if (sep == value)
++                              return -EINVAL;
++
++                      mode->tv_margins.left = margin;
++              } else if (!strncmp(option, "margin_top", delim - option)) {
++                      const char *value = delim + 1;
++                      unsigned int margin;
++
++                      margin = simple_strtol(value, &sep, 10);
++
++                      /* Make sure we have parsed something */
++                      if (sep == value)
++                              return -EINVAL;
++
++                      mode->tv_margins.top = margin;
++              } else if (!strncmp(option, "margin_bottom", delim - option)) {
++                      const char *value = delim + 1;
++                      unsigned int margin;
++
++                      margin = simple_strtol(value, &sep, 10);
++
++                      /* Make sure we have parsed something */
++                      if (sep == value)
++                              return -EINVAL;
++
++                      mode->tv_margins.bottom = margin;
+               } else {
+                       return -EINVAL;
+               }
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -886,6 +886,11 @@ struct drm_cmdline_mode {
+        * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
+        */
+       unsigned int rotation_reflection;
++
++      /**
++       * @tv_margins: TV margins to apply to the mode.
++       */
++      struct drm_connector_tv_margins tv_margins;
+ };
+ /**
diff --git a/target/linux/brcm2708/patches-4.19/950-0644-drm-atomic-Add-a-function-to-reset-connector-TV-prop.patch b/target/linux/brcm2708/patches-4.19/950-0644-drm-atomic-Add-a-function-to-reset-connector-TV-prop.patch
new file mode 100644 (file)
index 0000000..9f50943
--- /dev/null
@@ -0,0 +1,63 @@
+From 8dd1e4d73fdbc4a533a58c2c74a72877257c558c Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:52 +0200
+Subject: [PATCH] drm/atomic: Add a function to reset connector TV
+ properties
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 731514b446fe6748d5a55a3dff202efb45c7d8df upstream.
+Reworked as functions have been moved from drm_atomic_helper.[c|h]
+to drm_atomic_state_helper.[c|h].
+
+During the connector reset, if that connector has a TV property, it needs
+to be reset to the value provided on the command line.
+
+Provide a helper to do that.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/84a7b657f09303a2850e1cc79e68f623547f3fdd.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/drm_atomic_helper.c | 18 ++++++++++++++++++
+ include/drm/drm_atomic_helper.h     |  1 +
+ 2 files changed, 19 insertions(+)
+
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -3737,6 +3737,24 @@ void drm_atomic_helper_connector_reset(s
+ EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
+ /**
++ * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
++ * @connector: DRM connector
++ *
++ * Resets the TV-related properties attached to a connector.
++ */
++void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
++{
++      struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
++      struct drm_connector_state *state = connector->state;
++
++      state->tv.margins.left = cmdline->tv_margins.left;
++      state->tv.margins.right = cmdline->tv_margins.right;
++      state->tv.margins.top = cmdline->tv_margins.top;
++      state->tv.margins.bottom = cmdline->tv_margins.bottom;
++}
++EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
++
++/**
+  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
+  * @connector: connector object
+  * @state: atomic connector state
+--- a/include/drm/drm_atomic_helper.h
++++ b/include/drm/drm_atomic_helper.h
+@@ -168,6 +168,7 @@ void drm_atomic_helper_plane_destroy_sta
+ void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
+                                        struct drm_connector_state *conn_state);
+ void drm_atomic_helper_connector_reset(struct drm_connector *connector);
++void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
+ void
+ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+                                          struct drm_connector_state *state);
diff --git a/target/linux/brcm2708/patches-4.19/950-0644-drm-connector-Introduce-a-TV-margins-structure.patch b/target/linux/brcm2708/patches-4.19/950-0644-drm-connector-Introduce-a-TV-margins-structure.patch
deleted file mode 100644 (file)
index 7c6f415..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-From 6261047a83258900e57a0a699ec7954360c6e7f3 Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:51 +0200
-Subject: [PATCH] drm/connector: Introduce a TV margins structure
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Commit 22045e8e52bd802f743f0471242782fc3b479707 upstream.
-
-The TV margins has been defined as a structure inside the
-drm_connector_state structure so far. However, we will need it in other
-structures as well, so let's move that structure definition so that it can
-be reused.
-
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/38b773b03f15ec7a135cdf8f7db669e5ada20cf2.1560783090.git-series.maxime.ripard@bootlin.com
----
- include/drm/drm_connector.h | 41 +++++++++++++++++++++++++++----------
- 1 file changed, 30 insertions(+), 11 deletions(-)
-
---- a/include/drm/drm_connector.h
-+++ b/include/drm/drm_connector.h
-@@ -344,13 +344,37 @@ int drm_display_info_set_bus_formats(str
-                                    unsigned int num_formats);
- /**
-+ * struct drm_connector_tv_margins - TV connector related margins
-+ *
-+ * Describes the margins in pixels to put around the image on TV
-+ * connectors to deal with overscan.
-+ */
-+struct drm_connector_tv_margins {
-+      /**
-+       * @bottom: Bottom margin in pixels.
-+       */
-+      unsigned int bottom;
-+
-+      /**
-+       * @left: Left margin in pixels.
-+       */
-+      unsigned int left;
-+
-+      /**
-+       * @right: Right margin in pixels.
-+       */
-+      unsigned int right;
-+
-+      /**
-+       * @top: Top margin in pixels.
-+       */
-+      unsigned int top;
-+};
-+
-+/**
-  * struct drm_tv_connector_state - TV connector related states
-  * @subconnector: selected subconnector
-- * @margins: margins (all margins are expressed in pixels)
-- * @margins.left: left margin
-- * @margins.right: right margin
-- * @margins.top: top margin
-- * @margins.bottom: bottom margin
-+ * @margins: TV margins
-  * @mode: TV mode
-  * @brightness: brightness in percent
-  * @contrast: contrast in percent
-@@ -361,12 +385,7 @@ int drm_display_info_set_bus_formats(str
-  */
- struct drm_tv_connector_state {
-       enum drm_mode_subconnector subconnector;
--      struct {
--              unsigned int left;
--              unsigned int right;
--              unsigned int top;
--              unsigned int bottom;
--      } margins;
-+      struct drm_connector_tv_margins margins;
-       unsigned int mode;
-       unsigned int brightness;
-       unsigned int contrast;
diff --git a/target/linux/brcm2708/patches-4.19/950-0645-drm-modes-Parse-overscan-properties.patch b/target/linux/brcm2708/patches-4.19/950-0645-drm-modes-Parse-overscan-properties.patch
deleted file mode 100644 (file)
index f8de9b5..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From 99b367ee521e48beae92bea59515dd0f08f2e55b Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:51 +0200
-Subject: [PATCH] drm/modes: Parse overscan properties
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Commit 3d46a3007cd8f73bae502bf5c171977b91d7aacc upstream.
-
-Properly configuring the overscan properties might be needed for the
-initial setup of the framebuffer for display that still have overscan.
-Let's allow for more properties on the kernel command line to setup each
-margin.
-
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/e481f1628e3768ca49226ec2115cfa4dfcbd5e4c.1560783090.git-series.maxime.ripard@bootlin.com
----
- Documentation/fb/modedb.txt |  2 ++
- drivers/gpu/drm/drm_modes.c | 44 +++++++++++++++++++++++++++++++++++++
- include/drm/drm_connector.h |  5 +++++
- 3 files changed, 51 insertions(+)
-
---- a/Documentation/fb/modedb.txt
-+++ b/Documentation/fb/modedb.txt
-@@ -57,6 +57,8 @@ Options can also be passed after the mod
- Valid options are:
-+  - margin_top, margin_bottom, margin_left, margin_right (integer):
-+    Number of pixels in the margins, typically to deal with overscan on TVs
-   - reflect_x (boolean): Perform an axial symmetry on the X axis
-   - reflect_y (boolean): Perform an axial symmetry on the Y axis
-   - rotate (integer): Rotate the initial framebuffer by x
---- a/drivers/gpu/drm/drm_modes.c
-+++ b/drivers/gpu/drm/drm_modes.c
-@@ -1615,6 +1615,50 @@ static int drm_mode_parse_cmdline_option
-               } else if (!strncmp(option, "reflect_y", delim - option)) {
-                       rotation |= DRM_MODE_REFLECT_Y;
-                       sep = delim;
-+              } else if (!strncmp(option, "margin_right", delim - option)) {
-+                      const char *value = delim + 1;
-+                      unsigned int margin;
-+
-+                      margin = simple_strtol(value, &sep, 10);
-+
-+                      /* Make sure we have parsed something */
-+                      if (sep == value)
-+                              return -EINVAL;
-+
-+                      mode->tv_margins.right = margin;
-+              } else if (!strncmp(option, "margin_left", delim - option)) {
-+                      const char *value = delim + 1;
-+                      unsigned int margin;
-+
-+                      margin = simple_strtol(value, &sep, 10);
-+
-+                      /* Make sure we have parsed something */
-+                      if (sep == value)
-+                              return -EINVAL;
-+
-+                      mode->tv_margins.left = margin;
-+              } else if (!strncmp(option, "margin_top", delim - option)) {
-+                      const char *value = delim + 1;
-+                      unsigned int margin;
-+
-+                      margin = simple_strtol(value, &sep, 10);
-+
-+                      /* Make sure we have parsed something */
-+                      if (sep == value)
-+                              return -EINVAL;
-+
-+                      mode->tv_margins.top = margin;
-+              } else if (!strncmp(option, "margin_bottom", delim - option)) {
-+                      const char *value = delim + 1;
-+                      unsigned int margin;
-+
-+                      margin = simple_strtol(value, &sep, 10);
-+
-+                      /* Make sure we have parsed something */
-+                      if (sep == value)
-+                              return -EINVAL;
-+
-+                      mode->tv_margins.bottom = margin;
-               } else {
-                       return -EINVAL;
-               }
---- a/include/drm/drm_connector.h
-+++ b/include/drm/drm_connector.h
-@@ -886,6 +886,11 @@ struct drm_cmdline_mode {
-        * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
-        */
-       unsigned int rotation_reflection;
-+
-+      /**
-+       * @tv_margins: TV margins to apply to the mode.
-+       */
-+      struct drm_connector_tv_margins tv_margins;
- };
- /**
diff --git a/target/linux/brcm2708/patches-4.19/950-0645-drm-vc4-hdmi-Set-default-state-margin-at-reset.patch b/target/linux/brcm2708/patches-4.19/950-0645-drm-vc4-hdmi-Set-default-state-margin-at-reset.patch
new file mode 100644 (file)
index 0000000..b1b554e
--- /dev/null
@@ -0,0 +1,41 @@
+From 1adef5f9443f148db0817099504df0a7fb7350dd Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:53 +0200
+Subject: [PATCH] drm/vc4: hdmi: Set default state margin at reset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Now that the TV margins are properly parsed and filled into
+drm_cmdline_mode, we just need to initialise the first state at reset to
+get those values and start using them.
+
+Acked-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/44e24172e300be6a41578517021ef6a6e90ed682.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -292,11 +292,17 @@ static int vc4_hdmi_connector_get_modes(
+       return ret;
+ }
++static void vc4_hdmi_connector_reset(struct drm_connector *connector)
++{
++      drm_atomic_helper_connector_reset(connector);
++      drm_atomic_helper_connector_tv_reset(connector);
++}
++
+ static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
+       .detect = vc4_hdmi_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = vc4_hdmi_connector_destroy,
+-      .reset = drm_atomic_helper_connector_reset,
++      .reset = vc4_hdmi_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0646-drm-atomic-Add-a-function-to-reset-connector-TV-prop.patch b/target/linux/brcm2708/patches-4.19/950-0646-drm-atomic-Add-a-function-to-reset-connector-TV-prop.patch
deleted file mode 100644 (file)
index 9f50943..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From 8dd1e4d73fdbc4a533a58c2c74a72877257c558c Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:52 +0200
-Subject: [PATCH] drm/atomic: Add a function to reset connector TV
- properties
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Commit 731514b446fe6748d5a55a3dff202efb45c7d8df upstream.
-Reworked as functions have been moved from drm_atomic_helper.[c|h]
-to drm_atomic_state_helper.[c|h].
-
-During the connector reset, if that connector has a TV property, it needs
-to be reset to the value provided on the command line.
-
-Provide a helper to do that.
-
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/84a7b657f09303a2850e1cc79e68f623547f3fdd.1560783090.git-series.maxime.ripard@bootlin.com
----
- drivers/gpu/drm/drm_atomic_helper.c | 18 ++++++++++++++++++
- include/drm/drm_atomic_helper.h     |  1 +
- 2 files changed, 19 insertions(+)
-
---- a/drivers/gpu/drm/drm_atomic_helper.c
-+++ b/drivers/gpu/drm/drm_atomic_helper.c
-@@ -3737,6 +3737,24 @@ void drm_atomic_helper_connector_reset(s
- EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
- /**
-+ * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
-+ * @connector: DRM connector
-+ *
-+ * Resets the TV-related properties attached to a connector.
-+ */
-+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
-+{
-+      struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
-+      struct drm_connector_state *state = connector->state;
-+
-+      state->tv.margins.left = cmdline->tv_margins.left;
-+      state->tv.margins.right = cmdline->tv_margins.right;
-+      state->tv.margins.top = cmdline->tv_margins.top;
-+      state->tv.margins.bottom = cmdline->tv_margins.bottom;
-+}
-+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
-+
-+/**
-  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
-  * @connector: connector object
-  * @state: atomic connector state
---- a/include/drm/drm_atomic_helper.h
-+++ b/include/drm/drm_atomic_helper.h
-@@ -168,6 +168,7 @@ void drm_atomic_helper_plane_destroy_sta
- void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
-                                        struct drm_connector_state *conn_state);
- void drm_atomic_helper_connector_reset(struct drm_connector *connector);
-+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
- void
- __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
-                                          struct drm_connector_state *state);
diff --git a/target/linux/brcm2708/patches-4.19/950-0646-drm-vc4-fkms-Set-default-state-margin-at-reset.patch b/target/linux/brcm2708/patches-4.19/950-0646-drm-vc4-fkms-Set-default-state-margin-at-reset.patch
new file mode 100644 (file)
index 0000000..c9e095f
--- /dev/null
@@ -0,0 +1,34 @@
+From 2cf6bd979b0a5fdb179842308b1670691f6a2ce4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 23 Jul 2019 11:09:26 +0100
+Subject: [PATCH] drm/vc4: fkms: Set default state margin at reset
+
+Now that the TV margins are properly parsed and filled into
+drm_cmdline_mode, we just need to initialise the first state at reset to
+get those values and start using them.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1457,10 +1457,17 @@ int vc4_connector_atomic_set_property(st
+       return -EINVAL;
+ }
++static void vc4_hdmi_connector_reset(struct drm_connector *connector)
++{
++      drm_atomic_helper_connector_reset(connector);
++      drm_atomic_helper_connector_tv_reset(connector);
++}
++
+ static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
+       .detect = vc4_fkms_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = vc4_fkms_connector_destroy,
++      .reset = vc4_hdmi_connector_reset,
+       .atomic_duplicate_state = vc4_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+       .atomic_get_property = vc4_connector_atomic_get_property,
diff --git a/target/linux/brcm2708/patches-4.19/950-0647-drm-modes-Don-t-apply-cmdline-s-rotation-if-it-wasn-.patch b/target/linux/brcm2708/patches-4.19/950-0647-drm-modes-Don-t-apply-cmdline-s-rotation-if-it-wasn-.patch
new file mode 100644 (file)
index 0000000..b97d018
--- /dev/null
@@ -0,0 +1,34 @@
+From 6eb9a89c28590203658c0ebcbf29d5b41eb8596a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 23 Jul 2019 14:10:31 +0100
+Subject: [PATCH] drm/modes: Don't apply cmdline's rotation if it
+ wasn't specified
+
+Taken from the dri-devel mailing list (11/7/2019) to fixup the cmdline
+parsing, but requires changes as things have moved between 4.19 and 5.2.
+
+From: Dmitry Osipenko <digetx@gmail.com>
+
+The rotation mode from cmdline shouldn't be taken into account if it
+wasn't specified in the cmdline. This fixes ignored default display
+orientation when display mode is given using cmdline without the
+rotation being specified.
+
+Fixes: 1bf4e09227c3 ("drm/modes: Allow to specify rotation and reflection on the commandline")
+Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/drm_fb_helper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -2502,7 +2502,7 @@ static void drm_setup_crtc_rotation(stru
+        * simple XOR between the two handle the addition nicely.
+        */
+       cmdline = &connector->cmdline_mode;
+-      if (cmdline->specified) {
++      if (cmdline->specified && cmdline->rotation_reflection) {
+               unsigned int cmdline_rest, panel_rest;
+               unsigned int cmdline_rot, panel_rot;
+               unsigned int sum_rot, sum_rest;
diff --git a/target/linux/brcm2708/patches-4.19/950-0647-drm-vc4-hdmi-Set-default-state-margin-at-reset.patch b/target/linux/brcm2708/patches-4.19/950-0647-drm-vc4-hdmi-Set-default-state-margin-at-reset.patch
deleted file mode 100644 (file)
index b1b554e..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From 1adef5f9443f148db0817099504df0a7fb7350dd Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@bootlin.com>
-Date: Wed, 19 Jun 2019 12:17:53 +0200
-Subject: [PATCH] drm/vc4: hdmi: Set default state margin at reset
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Now that the TV margins are properly parsed and filled into
-drm_cmdline_mode, we just need to initialise the first state at reset to
-get those values and start using them.
-
-Acked-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/44e24172e300be6a41578517021ef6a6e90ed682.1560783090.git-series.maxime.ripard@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_hdmi.c
-+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
-@@ -292,11 +292,17 @@ static int vc4_hdmi_connector_get_modes(
-       return ret;
- }
-+static void vc4_hdmi_connector_reset(struct drm_connector *connector)
-+{
-+      drm_atomic_helper_connector_reset(connector);
-+      drm_atomic_helper_connector_tv_reset(connector);
-+}
-+
- static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
-       .detect = vc4_hdmi_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = vc4_hdmi_connector_destroy,
--      .reset = drm_atomic_helper_connector_reset,
-+      .reset = vc4_hdmi_connector_reset,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0648-drm-vc4-fkms-Set-default-state-margin-at-reset.patch b/target/linux/brcm2708/patches-4.19/950-0648-drm-vc4-fkms-Set-default-state-margin-at-reset.patch
deleted file mode 100644 (file)
index c9e095f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 2cf6bd979b0a5fdb179842308b1670691f6a2ce4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 23 Jul 2019 11:09:26 +0100
-Subject: [PATCH] drm/vc4: fkms: Set default state margin at reset
-
-Now that the TV margins are properly parsed and filled into
-drm_cmdline_mode, we just need to initialise the first state at reset to
-get those values and start using them.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1457,10 +1457,17 @@ int vc4_connector_atomic_set_property(st
-       return -EINVAL;
- }
-+static void vc4_hdmi_connector_reset(struct drm_connector *connector)
-+{
-+      drm_atomic_helper_connector_reset(connector);
-+      drm_atomic_helper_connector_tv_reset(connector);
-+}
-+
- static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
-       .detect = vc4_fkms_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = vc4_fkms_connector_destroy,
-+      .reset = vc4_hdmi_connector_reset,
-       .atomic_duplicate_state = vc4_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-       .atomic_get_property = vc4_connector_atomic_get_property,
diff --git a/target/linux/brcm2708/patches-4.19/950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch b/target/linux/brcm2708/patches-4.19/950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch
new file mode 100644 (file)
index 0000000..ce590c9
--- /dev/null
@@ -0,0 +1,351 @@
+From cb053a15c5c23e775647d6b65fef4c378bf34b5b Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Thu, 18 Jul 2019 17:07:05 +0800
+Subject: [PATCH] staging: bcm2835-codec: switch to multi-planar API
+
+There are two APIs for mem2mem devices, the older single-planar API and
+the newer multi-planar one. Without making things overly complex, the
+driver can only support one or the other. However the userspace libv4l2
+library has a plugin that allows multi-planar API devices to service
+single-planar consumers.
+
+Chromium supports the multi-planar API exclusively, though this is
+currently limited to ChromiumOS. It would be possible to add support
+for generic Linux.
+
+Switching to the multi-planar API would allow usage of both APIs from
+userspace.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 145 +++++++++---------
+ 1 file changed, 76 insertions(+), 69 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -504,7 +504,7 @@ static struct bcm2835_codec_fmt *find_fo
+       for (k = 0; k < fmts->num_entries; k++) {
+               fmt = &fmts->list[k];
+-              if (fmt->fourcc == f->fmt.pix.pixelformat)
++              if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+                       break;
+       }
+       if (k == fmts->num_entries)
+@@ -522,9 +522,9 @@ static struct bcm2835_codec_q_data *get_
+                                              enum v4l2_buf_type type)
+ {
+       switch (type) {
+-      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++      case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               return &ctx->q_data[V4L2_M2M_SRC];
+-      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++      case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               return &ctx->q_data[V4L2_M2M_DST];
+       default:
+               v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
+@@ -541,9 +541,9 @@ static struct vchiq_mmal_port *get_port_
+               return NULL;
+       switch (type) {
+-      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++      case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               return &ctx->component->input[0];
+-      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++      case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               return &ctx->component->output[0];
+       default:
+               v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
+@@ -752,7 +752,7 @@ static void handle_fmt_changed(struct bc
+                format->es.video.crop.width, format->es.video.crop.height,
+                format->es.video.color_space);
+-      q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
++      q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+       q_data->crop_width = format->es.video.crop.width;
+       q_data->crop_height = format->es.video.crop.height;
+       q_data->bytesperline = format->es.video.crop.width;
+@@ -945,7 +945,7 @@ static int vidioc_querycap(struct file *
+       strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                MEM2MEM_NAME);
+-      cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
++      cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+ }
+@@ -996,16 +996,20 @@ static int vidioc_g_fmt(struct bcm2835_c
+       q_data = get_q_data(ctx, f->type);
+-      f->fmt.pix.width        = q_data->crop_width;
+-      f->fmt.pix.height       = q_data->height;
+-      f->fmt.pix.field        = V4L2_FIELD_NONE;
+-      f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
+-      f->fmt.pix.bytesperline = q_data->bytesperline;
+-      f->fmt.pix.sizeimage    = q_data->sizeimage;
+-      f->fmt.pix.colorspace   = ctx->colorspace;
+-      f->fmt.pix.xfer_func    = ctx->xfer_func;
+-      f->fmt.pix.ycbcr_enc    = ctx->ycbcr_enc;
+-      f->fmt.pix.quantization = ctx->quant;
++      f->fmt.pix_mp.width                     = q_data->crop_width;
++      f->fmt.pix_mp.height                    = q_data->height;
++      f->fmt.pix_mp.pixelformat               = q_data->fmt->fourcc;
++      f->fmt.pix_mp.field                     = V4L2_FIELD_NONE;
++      f->fmt.pix_mp.colorspace                = ctx->colorspace;
++      f->fmt.pix_mp.plane_fmt[0].sizeimage    = q_data->sizeimage;
++      f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
++      f->fmt.pix_mp.num_planes                = 1;
++      f->fmt.pix_mp.ycbcr_enc                 = ctx->ycbcr_enc;
++      f->fmt.pix_mp.quantization              = ctx->quant;
++      f->fmt.pix_mp.xfer_func                 = ctx->xfer_func;
++
++      memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
++             sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
+       return 0;
+ }
+@@ -1029,17 +1033,17 @@ static int vidioc_try_fmt(struct bcm2835
+        * The V4L2 specification requires the driver to correct the format
+        * struct if any of the dimensions is unsupported
+        */
+-      if (f->fmt.pix.width > MAX_W)
+-              f->fmt.pix.width = MAX_W;
+-      if (f->fmt.pix.height > MAX_H)
+-              f->fmt.pix.height = MAX_H;
++      if (f->fmt.pix_mp.width > MAX_W)
++              f->fmt.pix_mp.width = MAX_W;
++      if (f->fmt.pix_mp.height > MAX_H)
++              f->fmt.pix_mp.height = MAX_H;
+       if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
+               /* Only clip min w/h on capture. Treat 0x0 as unknown. */
+-              if (f->fmt.pix.width < MIN_W)
+-                      f->fmt.pix.width = MIN_W;
+-              if (f->fmt.pix.height < MIN_H)
+-                      f->fmt.pix.height = MIN_H;
++              if (f->fmt.pix_mp.width < MIN_W)
++                      f->fmt.pix_mp.width = MIN_W;
++              if (f->fmt.pix_mp.height < MIN_H)
++                      f->fmt.pix_mp.height = MIN_H;
+               /*
+                * For codecs the buffer must have a vertical alignment of 16
+@@ -1048,16 +1052,18 @@ static int vidioc_try_fmt(struct bcm2835
+                * some of the pixels are active.
+                */
+               if (ctx->dev->role != ISP)
+-                      f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
++                      f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
+       }
+-      f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
+-                                                 fmt);
+-      f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
+-                                           f->fmt.pix.width,
+-                                           f->fmt.pix.height,
+-                                           fmt);
++      f->fmt.pix_mp.num_planes = 1;
++      f->fmt.pix_mp.plane_fmt[0].bytesperline =
++              get_bytesperline(f->fmt.pix_mp.width, fmt);
++      f->fmt.pix_mp.plane_fmt[0].sizeimage =
++              get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline,
++                            f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt);
++      memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
++             sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
+-      f->fmt.pix.field = V4L2_FIELD_NONE;
++      f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+       return 0;
+ }
+@@ -1070,8 +1076,8 @@ static int vidioc_try_fmt_vid_cap(struct
+       fmt = find_format(f, ctx->dev, true);
+       if (!fmt) {
+-              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+-                                                          true)->fourcc;
++              f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
++                                                             true)->fourcc;
+               fmt = find_format(f, ctx->dev, true);
+       }
+@@ -1086,13 +1092,13 @@ static int vidioc_try_fmt_vid_out(struct
+       fmt = find_format(f, ctx->dev, false);
+       if (!fmt) {
+-              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+-                                                          false)->fourcc;
++              f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
++                                                             false)->fourcc;
+               fmt = find_format(f, ctx->dev, false);
+       }
+-      if (!f->fmt.pix.colorspace)
+-              f->fmt.pix.colorspace = ctx->colorspace;
++      if (!f->fmt.pix_mp.colorspace)
++              f->fmt.pix_mp.colorspace = ctx->colorspace;
+       return vidioc_try_fmt(ctx, f, fmt);
+ }
+@@ -1106,9 +1112,10 @@ static int vidioc_s_fmt(struct bcm2835_c
+       bool update_capture_port = false;
+       int ret;
+-      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
+-               f->type, f->fmt.pix.width, f->fmt.pix.height,
+-               f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
++               f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
++               f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
++
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
+@@ -1124,9 +1131,9 @@ static int vidioc_s_fmt(struct bcm2835_c
+       }
+       q_data->fmt = find_format(f, ctx->dev,
+-                                f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
+-      q_data->crop_width = f->fmt.pix.width;
+-      q_data->height = f->fmt.pix.height;
++                                f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
++      q_data->crop_width = f->fmt.pix_mp.width;
++      q_data->height = f->fmt.pix_mp.height;
+       if (!q_data->selection_set)
+               q_data->crop_height = requested_height;
+@@ -1134,21 +1141,21 @@ static int vidioc_s_fmt(struct bcm2835_c
+        * Copying the behaviour of vicodec which retains a single set of
+        * colorspace parameters for both input and output.
+        */
+-      ctx->colorspace = f->fmt.pix.colorspace;
+-      ctx->xfer_func = f->fmt.pix.xfer_func;
+-      ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
+-      ctx->quant = f->fmt.pix.quantization;
++      ctx->colorspace = f->fmt.pix_mp.colorspace;
++      ctx->xfer_func = f->fmt.pix_mp.xfer_func;
++      ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
++      ctx->quant = f->fmt.pix_mp.quantization;
+       /* All parameters should have been set correctly by try_fmt */
+-      q_data->bytesperline = f->fmt.pix.bytesperline;
+-      q_data->sizeimage = f->fmt.pix.sizeimage;
++      q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
++      q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
+       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
+                q_data->bytesperline, q_data->sizeimage);
+       if (ctx->dev->role == DECODE &&
+           q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
+-          f->fmt.pix.width && f->fmt.pix.height) {
++          q_data->crop_width && q_data->height) {
+               /*
+                * On the decoder, if provided with a resolution on the input
+                * side, then replicate that to the output side.
+@@ -1165,7 +1172,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+               q_data_dst->height = ALIGN(q_data->crop_height, 16);
+               q_data_dst->bytesperline =
+-                      get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
++                      get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt);
+               q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
+                                                     q_data_dst->crop_width,
+                                                     q_data_dst->height,
+@@ -1215,7 +1222,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+ {
+-      unsigned int height = f->fmt.pix.height;
++      unsigned int height = f->fmt.pix_mp.height;
+       int ret;
+       ret = vidioc_try_fmt_vid_cap(file, priv, f);
+@@ -1228,7 +1235,7 @@ static int vidioc_s_fmt_vid_cap(struct f
+ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+ {
+-      unsigned int height = f->fmt.pix.height;
++      unsigned int height = f->fmt.pix_mp.height;
+       int ret;
+       ret = vidioc_try_fmt_vid_out(file, priv, f);
+@@ -1244,7 +1251,7 @@ static int vidioc_g_selection(struct fil
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+       struct bcm2835_codec_q_data *q_data;
+-      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
++      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
+                                                               true : false;
+       if ((ctx->dev->role == DECODE && !capture_queue) ||
+@@ -1307,7 +1314,7 @@ static int vidioc_s_selection(struct fil
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+       struct bcm2835_codec_q_data *q_data = NULL;
+-      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
++      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
+                                                               true : false;
+       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
+@@ -1368,7 +1375,7 @@ static int vidioc_s_parm(struct file *fi
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return -EINVAL;
+       ctx->framerate_num =
+@@ -1738,15 +1745,15 @@ static int vidioc_encoder_cmd(struct fil
+ static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+-      .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+-      .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
+-      .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+-      .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
+-
+-      .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+-      .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
+-      .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
+-      .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
++      .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap,
++      .vidioc_g_fmt_vid_cap_mplane    = vidioc_g_fmt_vid_cap,
++      .vidioc_try_fmt_vid_cap_mplane  = vidioc_try_fmt_vid_cap,
++      .vidioc_s_fmt_vid_cap_mplane    = vidioc_s_fmt_vid_cap,
++
++      .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
++      .vidioc_g_fmt_vid_out_mplane    = vidioc_g_fmt_vid_out,
++      .vidioc_try_fmt_vid_out_mplane  = vidioc_try_fmt_vid_out,
++      .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out,
+       .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
+@@ -2089,7 +2096,7 @@ static int bcm2835_codec_start_streaming
+               ctx->component_enabled = true;
+       }
+-      if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
++      if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /*
+                * Create the EOS buffer.
+                * We only need the MMAL part, and want to NOT attach a memory
+@@ -2216,7 +2223,7 @@ static int queue_init(void *priv, struct
+       struct bcm2835_codec_ctx *ctx = priv;
+       int ret;
+-      src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++      src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
+@@ -2230,7 +2237,7 @@ static int queue_init(void *priv, struct
+       if (ret)
+               return ret;
+-      dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++      dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
diff --git a/target/linux/brcm2708/patches-4.19/950-0649-drm-modes-Don-t-apply-cmdline-s-rotation-if-it-wasn-.patch b/target/linux/brcm2708/patches-4.19/950-0649-drm-modes-Don-t-apply-cmdline-s-rotation-if-it-wasn-.patch
deleted file mode 100644 (file)
index b97d018..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 6eb9a89c28590203658c0ebcbf29d5b41eb8596a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 23 Jul 2019 14:10:31 +0100
-Subject: [PATCH] drm/modes: Don't apply cmdline's rotation if it
- wasn't specified
-
-Taken from the dri-devel mailing list (11/7/2019) to fixup the cmdline
-parsing, but requires changes as things have moved between 4.19 and 5.2.
-
-From: Dmitry Osipenko <digetx@gmail.com>
-
-The rotation mode from cmdline shouldn't be taken into account if it
-wasn't specified in the cmdline. This fixes ignored default display
-orientation when display mode is given using cmdline without the
-rotation being specified.
-
-Fixes: 1bf4e09227c3 ("drm/modes: Allow to specify rotation and reflection on the commandline")
-Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/drm_fb_helper.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/drm_fb_helper.c
-+++ b/drivers/gpu/drm/drm_fb_helper.c
-@@ -2502,7 +2502,7 @@ static void drm_setup_crtc_rotation(stru
-        * simple XOR between the two handle the addition nicely.
-        */
-       cmdline = &connector->cmdline_mode;
--      if (cmdline->specified) {
-+      if (cmdline->specified && cmdline->rotation_reflection) {
-               unsigned int cmdline_rest, panel_rest;
-               unsigned int cmdline_rot, panel_rot;
-               unsigned int sum_rot, sum_rest;
diff --git a/target/linux/brcm2708/patches-4.19/950-0649-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch b/target/linux/brcm2708/patches-4.19/950-0649-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch
new file mode 100644 (file)
index 0000000..cd19bc2
--- /dev/null
@@ -0,0 +1,46 @@
+From 1f524b04b040978e2d96380ff40c3e80feba49a5 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 22 Jul 2019 22:13:30 +0800
+Subject: [PATCH] staging: bcm2835-codec: implement
+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE
+
+The stateful decoder specification shows an optional step for retrieving
+the miminum number of capture buffers required for the decoder to
+proceed. While not a required parameter, having it makes some
+applications happy.
+
+bcm2835-codec is a little different from other decoder implementations
+in that there is an intermediate format conversion between the hardware
+and V4L2 buffers. The number of capture buffers required is therefore
+independent of the stream and DPB etc.
+
+There are plans to remove the conversion, but it requires a fair amount
+of rework within the firmware. Until that is done, simply return a value
+of 1.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -2357,6 +2357,18 @@ static int bcm2835_codec_open(struct fil
+               }
+               ctx->fh.ctrl_handler = hdl;
+               v4l2_ctrl_handler_setup(hdl);
++      } else if (dev->role == DECODE) {
++              v4l2_ctrl_handler_init(hdl, 1);
++
++              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++                                V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
++                                1, 1, 1, 1);
++              if (hdl->error) {
++                      rc = hdl->error;
++                      goto free_ctrl_handler;
++              }
++              ctx->fh.ctrl_handler = hdl;
++              v4l2_ctrl_handler_setup(hdl);
+       }
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
diff --git a/target/linux/brcm2708/patches-4.19/950-0650-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch b/target/linux/brcm2708/patches-4.19/950-0650-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch
new file mode 100644 (file)
index 0000000..f7243f3
--- /dev/null
@@ -0,0 +1,40 @@
+From c369e173f9ff254ed3c3b9062e04917122e3536e Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 22 Jul 2019 22:20:55 +0800
+Subject: [PATCH] staging: bcm2835-codec: set device_caps in struct
+ video_device
+
+Instead of filling in the struct v4l2_capability device_caps
+field, fill in the struct video_device device_caps field.
+
+That way the V4L2 core knows what the capabilities of the
+video device are.
+
+This is similar to a cleanup series by Hans Verkuil [1].
+
+[1] https://www.spinics.net/lists/linux-media/msg153313.html
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c   | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -945,8 +945,6 @@ static int vidioc_querycap(struct file *
+       strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                MEM2MEM_NAME);
+-      cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+-      cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+ }
+@@ -2600,6 +2598,7 @@ static int bcm2835_codec_create(struct p
+       vfd = &dev->vfd;
+       vfd->lock = &dev->dev_mutex;
+       vfd->v4l2_dev = &dev->v4l2_dev;
++      vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+       switch (role) {
+       case DECODE:
diff --git a/target/linux/brcm2708/patches-4.19/950-0650-staging-bcm2835-codec-switch-to-multi-planar-API.patch b/target/linux/brcm2708/patches-4.19/950-0650-staging-bcm2835-codec-switch-to-multi-planar-API.patch
deleted file mode 100644 (file)
index ce590c9..0000000
+++ /dev/null
@@ -1,351 +0,0 @@
-From cb053a15c5c23e775647d6b65fef4c378bf34b5b Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Thu, 18 Jul 2019 17:07:05 +0800
-Subject: [PATCH] staging: bcm2835-codec: switch to multi-planar API
-
-There are two APIs for mem2mem devices, the older single-planar API and
-the newer multi-planar one. Without making things overly complex, the
-driver can only support one or the other. However the userspace libv4l2
-library has a plugin that allows multi-planar API devices to service
-single-planar consumers.
-
-Chromium supports the multi-planar API exclusively, though this is
-currently limited to ChromiumOS. It would be possible to add support
-for generic Linux.
-
-Switching to the multi-planar API would allow usage of both APIs from
-userspace.
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 145 +++++++++---------
- 1 file changed, 76 insertions(+), 69 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -504,7 +504,7 @@ static struct bcm2835_codec_fmt *find_fo
-       for (k = 0; k < fmts->num_entries; k++) {
-               fmt = &fmts->list[k];
--              if (fmt->fourcc == f->fmt.pix.pixelformat)
-+              if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
-                       break;
-       }
-       if (k == fmts->num_entries)
-@@ -522,9 +522,9 @@ static struct bcm2835_codec_q_data *get_
-                                              enum v4l2_buf_type type)
- {
-       switch (type) {
--      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+      case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               return &ctx->q_data[V4L2_M2M_SRC];
--      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+      case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               return &ctx->q_data[V4L2_M2M_DST];
-       default:
-               v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
-@@ -541,9 +541,9 @@ static struct vchiq_mmal_port *get_port_
-               return NULL;
-       switch (type) {
--      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+      case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               return &ctx->component->input[0];
--      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+      case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               return &ctx->component->output[0];
-       default:
-               v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
-@@ -752,7 +752,7 @@ static void handle_fmt_changed(struct bc
-                format->es.video.crop.width, format->es.video.crop.height,
-                format->es.video.color_space);
--      q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-+      q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-       q_data->crop_width = format->es.video.crop.width;
-       q_data->crop_height = format->es.video.crop.height;
-       q_data->bytesperline = format->es.video.crop.width;
-@@ -945,7 +945,7 @@ static int vidioc_querycap(struct file *
-       strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                MEM2MEM_NAME);
--      cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
-+      cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-       return 0;
- }
-@@ -996,16 +996,20 @@ static int vidioc_g_fmt(struct bcm2835_c
-       q_data = get_q_data(ctx, f->type);
--      f->fmt.pix.width        = q_data->crop_width;
--      f->fmt.pix.height       = q_data->height;
--      f->fmt.pix.field        = V4L2_FIELD_NONE;
--      f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
--      f->fmt.pix.bytesperline = q_data->bytesperline;
--      f->fmt.pix.sizeimage    = q_data->sizeimage;
--      f->fmt.pix.colorspace   = ctx->colorspace;
--      f->fmt.pix.xfer_func    = ctx->xfer_func;
--      f->fmt.pix.ycbcr_enc    = ctx->ycbcr_enc;
--      f->fmt.pix.quantization = ctx->quant;
-+      f->fmt.pix_mp.width                     = q_data->crop_width;
-+      f->fmt.pix_mp.height                    = q_data->height;
-+      f->fmt.pix_mp.pixelformat               = q_data->fmt->fourcc;
-+      f->fmt.pix_mp.field                     = V4L2_FIELD_NONE;
-+      f->fmt.pix_mp.colorspace                = ctx->colorspace;
-+      f->fmt.pix_mp.plane_fmt[0].sizeimage    = q_data->sizeimage;
-+      f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
-+      f->fmt.pix_mp.num_planes                = 1;
-+      f->fmt.pix_mp.ycbcr_enc                 = ctx->ycbcr_enc;
-+      f->fmt.pix_mp.quantization              = ctx->quant;
-+      f->fmt.pix_mp.xfer_func                 = ctx->xfer_func;
-+
-+      memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
-+             sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
-       return 0;
- }
-@@ -1029,17 +1033,17 @@ static int vidioc_try_fmt(struct bcm2835
-        * The V4L2 specification requires the driver to correct the format
-        * struct if any of the dimensions is unsupported
-        */
--      if (f->fmt.pix.width > MAX_W)
--              f->fmt.pix.width = MAX_W;
--      if (f->fmt.pix.height > MAX_H)
--              f->fmt.pix.height = MAX_H;
-+      if (f->fmt.pix_mp.width > MAX_W)
-+              f->fmt.pix_mp.width = MAX_W;
-+      if (f->fmt.pix_mp.height > MAX_H)
-+              f->fmt.pix_mp.height = MAX_H;
-       if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
-               /* Only clip min w/h on capture. Treat 0x0 as unknown. */
--              if (f->fmt.pix.width < MIN_W)
--                      f->fmt.pix.width = MIN_W;
--              if (f->fmt.pix.height < MIN_H)
--                      f->fmt.pix.height = MIN_H;
-+              if (f->fmt.pix_mp.width < MIN_W)
-+                      f->fmt.pix_mp.width = MIN_W;
-+              if (f->fmt.pix_mp.height < MIN_H)
-+                      f->fmt.pix_mp.height = MIN_H;
-               /*
-                * For codecs the buffer must have a vertical alignment of 16
-@@ -1048,16 +1052,18 @@ static int vidioc_try_fmt(struct bcm2835
-                * some of the pixels are active.
-                */
-               if (ctx->dev->role != ISP)
--                      f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
-+                      f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
-       }
--      f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
--                                                 fmt);
--      f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
--                                           f->fmt.pix.width,
--                                           f->fmt.pix.height,
--                                           fmt);
-+      f->fmt.pix_mp.num_planes = 1;
-+      f->fmt.pix_mp.plane_fmt[0].bytesperline =
-+              get_bytesperline(f->fmt.pix_mp.width, fmt);
-+      f->fmt.pix_mp.plane_fmt[0].sizeimage =
-+              get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline,
-+                            f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt);
-+      memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
-+             sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
--      f->fmt.pix.field = V4L2_FIELD_NONE;
-+      f->fmt.pix_mp.field = V4L2_FIELD_NONE;
-       return 0;
- }
-@@ -1070,8 +1076,8 @@ static int vidioc_try_fmt_vid_cap(struct
-       fmt = find_format(f, ctx->dev, true);
-       if (!fmt) {
--              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
--                                                          true)->fourcc;
-+              f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
-+                                                             true)->fourcc;
-               fmt = find_format(f, ctx->dev, true);
-       }
-@@ -1086,13 +1092,13 @@ static int vidioc_try_fmt_vid_out(struct
-       fmt = find_format(f, ctx->dev, false);
-       if (!fmt) {
--              f->fmt.pix.pixelformat = get_default_format(ctx->dev,
--                                                          false)->fourcc;
-+              f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
-+                                                             false)->fourcc;
-               fmt = find_format(f, ctx->dev, false);
-       }
--      if (!f->fmt.pix.colorspace)
--              f->fmt.pix.colorspace = ctx->colorspace;
-+      if (!f->fmt.pix_mp.colorspace)
-+              f->fmt.pix_mp.colorspace = ctx->colorspace;
-       return vidioc_try_fmt(ctx, f, fmt);
- }
-@@ -1106,9 +1112,10 @@ static int vidioc_s_fmt(struct bcm2835_c
-       bool update_capture_port = false;
-       int ret;
--      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
--               f->type, f->fmt.pix.width, f->fmt.pix.height,
--               f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
-+               f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
-+               f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
-+
-       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-       if (!vq)
-@@ -1124,9 +1131,9 @@ static int vidioc_s_fmt(struct bcm2835_c
-       }
-       q_data->fmt = find_format(f, ctx->dev,
--                                f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
--      q_data->crop_width = f->fmt.pix.width;
--      q_data->height = f->fmt.pix.height;
-+                                f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-+      q_data->crop_width = f->fmt.pix_mp.width;
-+      q_data->height = f->fmt.pix_mp.height;
-       if (!q_data->selection_set)
-               q_data->crop_height = requested_height;
-@@ -1134,21 +1141,21 @@ static int vidioc_s_fmt(struct bcm2835_c
-        * Copying the behaviour of vicodec which retains a single set of
-        * colorspace parameters for both input and output.
-        */
--      ctx->colorspace = f->fmt.pix.colorspace;
--      ctx->xfer_func = f->fmt.pix.xfer_func;
--      ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
--      ctx->quant = f->fmt.pix.quantization;
-+      ctx->colorspace = f->fmt.pix_mp.colorspace;
-+      ctx->xfer_func = f->fmt.pix_mp.xfer_func;
-+      ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
-+      ctx->quant = f->fmt.pix_mp.quantization;
-       /* All parameters should have been set correctly by try_fmt */
--      q_data->bytesperline = f->fmt.pix.bytesperline;
--      q_data->sizeimage = f->fmt.pix.sizeimage;
-+      q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
-+      q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
-       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
-                q_data->bytesperline, q_data->sizeimage);
-       if (ctx->dev->role == DECODE &&
-           q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
--          f->fmt.pix.width && f->fmt.pix.height) {
-+          q_data->crop_width && q_data->height) {
-               /*
-                * On the decoder, if provided with a resolution on the input
-                * side, then replicate that to the output side.
-@@ -1165,7 +1172,7 @@ static int vidioc_s_fmt(struct bcm2835_c
-               q_data_dst->height = ALIGN(q_data->crop_height, 16);
-               q_data_dst->bytesperline =
--                      get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
-+                      get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt);
-               q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
-                                                     q_data_dst->crop_width,
-                                                     q_data_dst->height,
-@@ -1215,7 +1222,7 @@ static int vidioc_s_fmt(struct bcm2835_c
- static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
- {
--      unsigned int height = f->fmt.pix.height;
-+      unsigned int height = f->fmt.pix_mp.height;
-       int ret;
-       ret = vidioc_try_fmt_vid_cap(file, priv, f);
-@@ -1228,7 +1235,7 @@ static int vidioc_s_fmt_vid_cap(struct f
- static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
-                               struct v4l2_format *f)
- {
--      unsigned int height = f->fmt.pix.height;
-+      unsigned int height = f->fmt.pix_mp.height;
-       int ret;
-       ret = vidioc_try_fmt_vid_out(file, priv, f);
-@@ -1244,7 +1251,7 @@ static int vidioc_g_selection(struct fil
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
-       struct bcm2835_codec_q_data *q_data;
--      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
-+      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
-                                                               true : false;
-       if ((ctx->dev->role == DECODE && !capture_queue) ||
-@@ -1307,7 +1314,7 @@ static int vidioc_s_selection(struct fil
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
-       struct bcm2835_codec_q_data *q_data = NULL;
--      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
-+      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
-                                                               true : false;
-       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
-@@ -1368,7 +1375,7 @@ static int vidioc_s_parm(struct file *fi
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return -EINVAL;
-       ctx->framerate_num =
-@@ -1738,15 +1745,15 @@ static int vidioc_encoder_cmd(struct fil
- static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
-       .vidioc_querycap        = vidioc_querycap,
--      .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
--      .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
--      .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
--      .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
--
--      .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
--      .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
--      .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
--      .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
-+      .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap,
-+      .vidioc_g_fmt_vid_cap_mplane    = vidioc_g_fmt_vid_cap,
-+      .vidioc_try_fmt_vid_cap_mplane  = vidioc_try_fmt_vid_cap,
-+      .vidioc_s_fmt_vid_cap_mplane    = vidioc_s_fmt_vid_cap,
-+
-+      .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
-+      .vidioc_g_fmt_vid_out_mplane    = vidioc_g_fmt_vid_out,
-+      .vidioc_try_fmt_vid_out_mplane  = vidioc_try_fmt_vid_out,
-+      .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out,
-       .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
-       .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
-@@ -2089,7 +2096,7 @@ static int bcm2835_codec_start_streaming
-               ctx->component_enabled = true;
-       }
--      if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-+      if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               /*
-                * Create the EOS buffer.
-                * We only need the MMAL part, and want to NOT attach a memory
-@@ -2216,7 +2223,7 @@ static int queue_init(void *priv, struct
-       struct bcm2835_codec_ctx *ctx = priv;
-       int ret;
--      src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-+      src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-       src_vq->drv_priv = ctx;
-       src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
-@@ -2230,7 +2237,7 @@ static int queue_init(void *priv, struct
-       if (ret)
-               return ret;
--      dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+      dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-       dst_vq->drv_priv = ctx;
-       dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
diff --git a/target/linux/brcm2708/patches-4.19/950-0651-Add-HDMI1-facility-to-the-driver.patch b/target/linux/brcm2708/patches-4.19/950-0651-Add-HDMI1-facility-to-the-driver.patch
new file mode 100644 (file)
index 0000000..7594d16
--- /dev/null
@@ -0,0 +1,85 @@
+From 0a37470a112260ef1c9a016a400fdf1f8792eadc Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Tue, 16 Jul 2019 12:18:21 +0100
+Subject: [PATCH] Add HDMI1 facility to the driver.
+
+For generic ALSA, all you need is the bcm2835.h change, but
+have also added structures for IEC958 HDMI. Not sure how to
+test those.
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c     | 29 ++++++++++++++++---
+ .../vc04_services/bcm2835-audio/bcm2835.h     |  4 ++-
+ 2 files changed, 28 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -79,7 +79,11 @@ static int bcm2835_audio_alsa_newpcm(str
+       if (err)
+               return err;
+-      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
++      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, AUDIO_DEST_HDMI0, 1, true);
++      if (err)
++              return err;
++
++      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI1", 2, AUDIO_DEST_HDMI1, 1, true);
+       if (err)
+               return err;
+@@ -106,7 +110,7 @@ static struct bcm2835_audio_driver bcm28
+       .newctl = snd_bcm2835_new_ctl,
+ };
+-static struct bcm2835_audio_driver bcm2835_audio_hdmi = {
++static struct bcm2835_audio_driver bcm2835_audio_hdmi0 = {
+       .driver = {
+               .name = "bcm2835_hdmi",
+               .owner = THIS_MODULE,
+@@ -116,7 +120,20 @@ static struct bcm2835_audio_driver bcm28
+       .minchannels = 1,
+       .newpcm = bcm2835_audio_simple_newpcm,
+       .newctl = snd_bcm2835_new_hdmi_ctl,
+-      .route = AUDIO_DEST_HDMI
++      .route = AUDIO_DEST_HDMI0
++};
++
++static struct bcm2835_audio_driver bcm2835_audio_hdmi1 = {
++      .driver = {
++              .name = "bcm2835_hdmi",
++              .owner = THIS_MODULE,
++      },
++      .shortname = "bcm2835 HDMI 1",
++      .longname  = "bcm2835 HDMI 1",
++      .minchannels = 1,
++      .newpcm = bcm2835_audio_simple_newpcm,
++      .newctl = snd_bcm2835_new_hdmi_ctl,
++      .route = AUDIO_DEST_HDMI1
+ };
+ static struct bcm2835_audio_driver bcm2835_audio_headphones = {
+@@ -143,7 +160,11 @@ static struct bcm2835_audio_drivers chil
+               .is_enabled = &enable_compat_alsa,
+       },
+       {
+-              .audio_driver = &bcm2835_audio_hdmi,
++              .audio_driver = &bcm2835_audio_hdmi0,
++              .is_enabled = &enable_hdmi,
++      },
++      {
++              .audio_driver = &bcm2835_audio_hdmi1,
+               .is_enabled = &enable_hdmi,
+       },
+       {
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -33,7 +33,9 @@ enum {
+ enum snd_bcm2835_route {
+       AUDIO_DEST_AUTO = 0,
+       AUDIO_DEST_HEADPHONES = 1,
+-      AUDIO_DEST_HDMI = 2,
++      AUDIO_DEST_HDMI = 2,  // for backwards compatibility.
++      AUDIO_DEST_HDMI0 = 2,
++      AUDIO_DEST_HDMI1 = 3,
+       AUDIO_DEST_MAX,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0651-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch b/target/linux/brcm2708/patches-4.19/950-0651-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch
deleted file mode 100644 (file)
index cd19bc2..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From 1f524b04b040978e2d96380ff40c3e80feba49a5 Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Mon, 22 Jul 2019 22:13:30 +0800
-Subject: [PATCH] staging: bcm2835-codec: implement
- V4L2_CID_MIN_BUFFERS_FOR_CAPTURE
-
-The stateful decoder specification shows an optional step for retrieving
-the miminum number of capture buffers required for the decoder to
-proceed. While not a required parameter, having it makes some
-applications happy.
-
-bcm2835-codec is a little different from other decoder implementations
-in that there is an intermediate format conversion between the hardware
-and V4L2 buffers. The number of capture buffers required is therefore
-independent of the stream and DPB etc.
-
-There are plans to remove the conversion, but it requires a fair amount
-of rework within the firmware. Until that is done, simply return a value
-of 1.
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -2357,6 +2357,18 @@ static int bcm2835_codec_open(struct fil
-               }
-               ctx->fh.ctrl_handler = hdl;
-               v4l2_ctrl_handler_setup(hdl);
-+      } else if (dev->role == DECODE) {
-+              v4l2_ctrl_handler_init(hdl, 1);
-+
-+              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+                                V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
-+                                1, 1, 1, 1);
-+              if (hdl->error) {
-+                      rc = hdl->error;
-+                      goto free_ctrl_handler;
-+              }
-+              ctx->fh.ctrl_handler = hdl;
-+              v4l2_ctrl_handler_setup(hdl);
-       }
-       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
diff --git a/target/linux/brcm2708/patches-4.19/950-0652-overlays-Add-baudrate-parameter-to-i2c3-i2c6.patch b/target/linux/brcm2708/patches-4.19/950-0652-overlays-Add-baudrate-parameter-to-i2c3-i2c6.patch
new file mode 100644 (file)
index 0000000..5ec631f
--- /dev/null
@@ -0,0 +1,194 @@
+From 114845b6010b6e6a320804f2d86ab4d5dc5a06de Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 5 Aug 2019 14:17:14 +0100
+Subject: [PATCH] overlays: Add baudrate parameter to i2c3-i2c6
+
+The overlays for enabling the new BCM2711 I2C interfaces were lacking
+the means to configure the baud/clock rate.
+
+Also explictly set the default pins, rather than relying on the values
+in the base DTB.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README           |  8 ++++++++
+ arch/arm/boot/dts/overlays/i2c3-overlay.dts | 15 ++++++++++++---
+ arch/arm/boot/dts/overlays/i2c4-overlay.dts | 15 ++++++++++++---
+ arch/arm/boot/dts/overlays/i2c5-overlay.dts | 15 ++++++++++++---
+ arch/arm/boot/dts/overlays/i2c6-overlay.dts | 15 ++++++++++++---
+ 5 files changed, 56 insertions(+), 12 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1221,6 +1221,8 @@ Info:   Enable the i2c3 bus
+ Load:   dtoverlay=i2c3,<param>
+ Params: pins_2_3                Use GPIOs 2 and 3
+         pins_4_5                Use GPIOs 4 and 5 (default)
++        baudrate                Set the baudrate for the interface (default
++                                "100000")
+ Name:   i2c4
+@@ -1228,6 +1230,8 @@ Info:   Enable the i2c4 bus
+ Load:   dtoverlay=i2c4,<param>
+ Params: pins_6_7                Use GPIOs 6 and 7
+         pins_8_9                Use GPIOs 8 and 9 (default)
++        baudrate                Set the baudrate for the interface (default
++                                "100000")
+ Name:   i2c5
+@@ -1235,6 +1239,8 @@ Info:   Enable the i2c5 bus
+ Load:   dtoverlay=i2c5,<param>
+ Params: pins_10_11              Use GPIOs 10 and 11
+         pins_12_13              Use GPIOs 12 and 13 (default)
++        baudrate                Set the baudrate for the interface (default
++                                "100000")
+ Name:   i2c6
+@@ -1242,6 +1248,8 @@ Info:   Enable the i2c6 bus
+ Load:   dtoverlay=i2c6,<param>
+ Params: pins_0_1                Use GPIOs 0 and 1
+         pins_22_23              Use GPIOs 22 and 23 (default)
++        baudrate                Set the baudrate for the interface (default
++                                "100000")
+ Name:   i2s-gpio28-31
+--- a/arch/arm/boot/dts/overlays/i2c3-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
+@@ -6,10 +6,11 @@
+       fragment@0 {
+               target = <&i2c3>;
+-              __overlay__ {
++              frag0: __overlay__ {
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c3_pins>;
++                      clock-frequency = <100000>;
+               };
+       };
+@@ -20,8 +21,16 @@
+               };
+       };
++      fragment@2 {
++              target = <&i2c3_pins>;
++              __overlay__ {
++                      brcm,pins = <4 5>;
++              };
++      };
++
+       __overrides__ {
+-              pins_2_3 = <0>,"=1";
+-              pins_4_5 = <0>,"!1";
++              pins_2_3 = <0>,"=1!2";
++              pins_4_5 = <0>,"!1=2";
++              baudrate = <&frag0>, "clock-frequency:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/i2c4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
+@@ -6,10 +6,11 @@
+       fragment@0 {
+               target = <&i2c4>;
+-              __overlay__ {
++              frag0: __overlay__ {
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c4_pins>;
++                      clock-frequency = <100000>;
+               };
+       };
+@@ -20,8 +21,16 @@
+               };
+       };
++      fragment@2 {
++              target = <&i2c4_pins>;
++              __overlay__ {
++                      brcm,pins = <8 9>;
++              };
++      };
++
+       __overrides__ {
+-              pins_6_7 = <0>,"=1";
+-              pins_8_9 = <0>,"!1";
++              pins_6_7 = <0>,"=1!2";
++              pins_8_9 = <0>,"!1=2";
++              baudrate = <&frag0>, "clock-frequency:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/i2c5-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
+@@ -6,10 +6,11 @@
+       fragment@0 {
+               target = <&i2c5>;
+-              __overlay__ {
++              frag0: __overlay__ {
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c5_pins>;
++                      clock-frequency = <100000>;
+               };
+       };
+@@ -20,8 +21,16 @@
+               };
+       };
++      fragment@2 {
++              target = <&i2c5_pins>;
++              __overlay__ {
++                      brcm,pins = <12 13>;
++              };
++      };
++
+       __overrides__ {
+-              pins_10_11 = <0>,"=1";
+-              pins_12_13 = <0>,"!1";
++              pins_10_11 = <0>,"=1!2";
++              pins_12_13 = <0>,"!1=2";
++              baudrate = <&frag0>, "clock-frequency:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/i2c6-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
+@@ -6,10 +6,11 @@
+       fragment@0 {
+               target = <&i2c6>;
+-              __overlay__ {
++              frag0: __overlay__ {
+                       status = "okay";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c6_pins>;
++                      clock-frequency = <100000>;
+               };
+       };
+@@ -20,8 +21,16 @@
+               };
+       };
++      fragment@2 {
++              target = <&i2c6_pins>;
++              __overlay__ {
++                      brcm,pins = <22 23>;
++              };
++      };
++
+       __overrides__ {
+-              pins_0_1 = <0>,"=1";
+-              pins_22_23 = <0>,"!1";
++              pins_0_1 = <0>,"=1!2";
++              pins_22_23 = <0>,"!1=2";
++              baudrate = <&frag0>, "clock-frequency:0";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0652-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch b/target/linux/brcm2708/patches-4.19/950-0652-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch
deleted file mode 100644 (file)
index f7243f3..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From c369e173f9ff254ed3c3b9062e04917122e3536e Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Mon, 22 Jul 2019 22:20:55 +0800
-Subject: [PATCH] staging: bcm2835-codec: set device_caps in struct
- video_device
-
-Instead of filling in the struct v4l2_capability device_caps
-field, fill in the struct video_device device_caps field.
-
-That way the V4L2 core knows what the capabilities of the
-video device are.
-
-This is similar to a cleanup series by Hans Verkuil [1].
-
-[1] https://www.spinics.net/lists/linux-media/msg153313.html
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c   | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -945,8 +945,6 @@ static int vidioc_querycap(struct file *
-       strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                MEM2MEM_NAME);
--      cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
--      cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-       return 0;
- }
-@@ -2600,6 +2598,7 @@ static int bcm2835_codec_create(struct p
-       vfd = &dev->vfd;
-       vfd->lock = &dev->dev_mutex;
-       vfd->v4l2_dev = &dev->v4l2_dev;
-+      vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-       switch (role) {
-       case DECODE:
diff --git a/target/linux/brcm2708/patches-4.19/950-0653-Add-HDMI1-facility-to-the-driver.patch b/target/linux/brcm2708/patches-4.19/950-0653-Add-HDMI1-facility-to-the-driver.patch
deleted file mode 100644 (file)
index 7594d16..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-From 0a37470a112260ef1c9a016a400fdf1f8792eadc Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Tue, 16 Jul 2019 12:18:21 +0100
-Subject: [PATCH] Add HDMI1 facility to the driver.
-
-For generic ALSA, all you need is the bcm2835.h change, but
-have also added structures for IEC958 HDMI. Not sure how to
-test those.
----
- .../vc04_services/bcm2835-audio/bcm2835.c     | 29 ++++++++++++++++---
- .../vc04_services/bcm2835-audio/bcm2835.h     |  4 ++-
- 2 files changed, 28 insertions(+), 5 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -79,7 +79,11 @@ static int bcm2835_audio_alsa_newpcm(str
-       if (err)
-               return err;
--      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
-+      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, AUDIO_DEST_HDMI0, 1, true);
-+      if (err)
-+              return err;
-+
-+      err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI1", 2, AUDIO_DEST_HDMI1, 1, true);
-       if (err)
-               return err;
-@@ -106,7 +110,7 @@ static struct bcm2835_audio_driver bcm28
-       .newctl = snd_bcm2835_new_ctl,
- };
--static struct bcm2835_audio_driver bcm2835_audio_hdmi = {
-+static struct bcm2835_audio_driver bcm2835_audio_hdmi0 = {
-       .driver = {
-               .name = "bcm2835_hdmi",
-               .owner = THIS_MODULE,
-@@ -116,7 +120,20 @@ static struct bcm2835_audio_driver bcm28
-       .minchannels = 1,
-       .newpcm = bcm2835_audio_simple_newpcm,
-       .newctl = snd_bcm2835_new_hdmi_ctl,
--      .route = AUDIO_DEST_HDMI
-+      .route = AUDIO_DEST_HDMI0
-+};
-+
-+static struct bcm2835_audio_driver bcm2835_audio_hdmi1 = {
-+      .driver = {
-+              .name = "bcm2835_hdmi",
-+              .owner = THIS_MODULE,
-+      },
-+      .shortname = "bcm2835 HDMI 1",
-+      .longname  = "bcm2835 HDMI 1",
-+      .minchannels = 1,
-+      .newpcm = bcm2835_audio_simple_newpcm,
-+      .newctl = snd_bcm2835_new_hdmi_ctl,
-+      .route = AUDIO_DEST_HDMI1
- };
- static struct bcm2835_audio_driver bcm2835_audio_headphones = {
-@@ -143,7 +160,11 @@ static struct bcm2835_audio_drivers chil
-               .is_enabled = &enable_compat_alsa,
-       },
-       {
--              .audio_driver = &bcm2835_audio_hdmi,
-+              .audio_driver = &bcm2835_audio_hdmi0,
-+              .is_enabled = &enable_hdmi,
-+      },
-+      {
-+              .audio_driver = &bcm2835_audio_hdmi1,
-               .is_enabled = &enable_hdmi,
-       },
-       {
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -33,7 +33,9 @@ enum {
- enum snd_bcm2835_route {
-       AUDIO_DEST_AUTO = 0,
-       AUDIO_DEST_HEADPHONES = 1,
--      AUDIO_DEST_HDMI = 2,
-+      AUDIO_DEST_HDMI = 2,  // for backwards compatibility.
-+      AUDIO_DEST_HDMI0 = 2,
-+      AUDIO_DEST_HDMI1 = 3,
-       AUDIO_DEST_MAX,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0653-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch b/target/linux/brcm2708/patches-4.19/950-0653-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch
new file mode 100644 (file)
index 0000000..e88bfc6
--- /dev/null
@@ -0,0 +1,100 @@
+From df276f0a5aa865c7926d9d148605d1a59d1d4fbb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 25 Jul 2019 17:27:44 +0100
+Subject: [PATCH] drm/vc4: Resolve the vblank warnings on mode
+ switching
+
+The details over when and how a driver is to service the
+vblank events are sketchy, and the fkms driver was triggering
+a kernel warning every time the crtc was enabled or disabled.
+
+Copy the event handling as used by the vc4-kms driver slightly
+more closely, and we avoid the warnings.
+
+https://github.com/raspberrypi/linux/issues/3020
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++--------
+ 1 file changed, 33 insertions(+), 15 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -933,6 +933,7 @@ static void vc4_crtc_mode_set_nofb(struc
+ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++      struct drm_device *dev = crtc->dev;
+       struct drm_plane *plane;
+       DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
+@@ -948,6 +949,35 @@ static void vc4_crtc_disable(struct drm_
+       drm_atomic_crtc_for_each_plane(plane, crtc)
+               vc4_plane_atomic_disable(plane, plane->state);
++
++      /*
++       * Make sure we issue a vblank event after disabling the CRTC if
++       * someone was waiting it.
++       */
++      if (crtc->state->event) {
++              unsigned long flags;
++
++              spin_lock_irqsave(&dev->event_lock, flags);
++              drm_crtc_send_vblank_event(crtc, crtc->state->event);
++              crtc->state->event = NULL;
++              spin_unlock_irqrestore(&dev->event_lock, flags);
++      }
++}
++
++static void vc4_crtc_consume_event(struct drm_crtc *crtc)
++{
++      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++      struct drm_device *dev = crtc->dev;
++      unsigned long flags;
++
++      crtc->state->event->pipe = drm_crtc_index(crtc);
++
++      WARN_ON(drm_crtc_vblank_get(crtc) != 0);
++
++      spin_lock_irqsave(&dev->event_lock, flags);
++      vc4_crtc->event = crtc->state->event;
++      crtc->state->event = NULL;
++      spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+@@ -957,6 +987,7 @@ static void vc4_crtc_enable(struct drm_c
+       DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
+                     crtc->base.id);
+       drm_crtc_vblank_on(crtc);
++      vc4_crtc_consume_event(crtc);
+       /* Unblank the planes (if they're supposed to be displayed). */
+       drm_atomic_crtc_for_each_plane(plane, crtc)
+@@ -1028,23 +1059,10 @@ static int vc4_crtc_atomic_check(struct
+ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
+                                 struct drm_crtc_state *old_state)
+ {
+-      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+-      struct drm_device *dev = crtc->dev;
+-
+       DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
+                     crtc->base.id);
+-      if (crtc->state->event) {
+-              unsigned long flags;
+-
+-              crtc->state->event->pipe = drm_crtc_index(crtc);
+-
+-              WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+-
+-              spin_lock_irqsave(&dev->event_lock, flags);
+-              vc4_crtc->event = crtc->state->event;
+-              crtc->state->event = NULL;
+-              spin_unlock_irqrestore(&dev->event_lock, flags);
+-      }
++      if (crtc->state->active && old_state->active && crtc->state->event)
++              vc4_crtc_consume_event(crtc);
+ }
+ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
diff --git a/target/linux/brcm2708/patches-4.19/950-0654-drm-vc4-Remove-unused-mode-variable.patch b/target/linux/brcm2708/patches-4.19/950-0654-drm-vc4-Remove-unused-mode-variable.patch
new file mode 100644 (file)
index 0000000..e12cac2
--- /dev/null
@@ -0,0 +1,27 @@
+From b2f463facb358b917380683b5e86c5d1cb3db123 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 25 Jul 2019 17:34:29 +0100
+Subject: [PATCH] drm/vc4: Remove unused mode variable
+
+"89d1376 drm/vc4: Add support for margins to fkms" removed
+the requirement for having the mode structure from vc4_plane_to_mb,
+but didn't remove it as a local to the function, causing a
+compiler warning.
+
+Remove the unused variable.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -523,7 +523,6 @@ static int vc4_plane_to_mb(struct drm_pl
+       const struct vc_image_format *vc_fmt =
+                                       vc4_get_vc_image_fmt(drm_fmt->format);
+       int num_planes = fb->format->num_planes;
+-      struct drm_display_mode *mode = &state->crtc->mode;
+       unsigned int rotation = SUPPORTED_ROTATIONS;
+       mb->plane.vc_image_type = vc_fmt->vc_image;
diff --git a/target/linux/brcm2708/patches-4.19/950-0654-overlays-Add-baudrate-parameter-to-i2c3-i2c6.patch b/target/linux/brcm2708/patches-4.19/950-0654-overlays-Add-baudrate-parameter-to-i2c3-i2c6.patch
deleted file mode 100644 (file)
index 5ec631f..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-From 114845b6010b6e6a320804f2d86ab4d5dc5a06de Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 5 Aug 2019 14:17:14 +0100
-Subject: [PATCH] overlays: Add baudrate parameter to i2c3-i2c6
-
-The overlays for enabling the new BCM2711 I2C interfaces were lacking
-the means to configure the baud/clock rate.
-
-Also explictly set the default pins, rather than relying on the values
-in the base DTB.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README           |  8 ++++++++
- arch/arm/boot/dts/overlays/i2c3-overlay.dts | 15 ++++++++++++---
- arch/arm/boot/dts/overlays/i2c4-overlay.dts | 15 ++++++++++++---
- arch/arm/boot/dts/overlays/i2c5-overlay.dts | 15 ++++++++++++---
- arch/arm/boot/dts/overlays/i2c6-overlay.dts | 15 ++++++++++++---
- 5 files changed, 56 insertions(+), 12 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1221,6 +1221,8 @@ Info:   Enable the i2c3 bus
- Load:   dtoverlay=i2c3,<param>
- Params: pins_2_3                Use GPIOs 2 and 3
-         pins_4_5                Use GPIOs 4 and 5 (default)
-+        baudrate                Set the baudrate for the interface (default
-+                                "100000")
- Name:   i2c4
-@@ -1228,6 +1230,8 @@ Info:   Enable the i2c4 bus
- Load:   dtoverlay=i2c4,<param>
- Params: pins_6_7                Use GPIOs 6 and 7
-         pins_8_9                Use GPIOs 8 and 9 (default)
-+        baudrate                Set the baudrate for the interface (default
-+                                "100000")
- Name:   i2c5
-@@ -1235,6 +1239,8 @@ Info:   Enable the i2c5 bus
- Load:   dtoverlay=i2c5,<param>
- Params: pins_10_11              Use GPIOs 10 and 11
-         pins_12_13              Use GPIOs 12 and 13 (default)
-+        baudrate                Set the baudrate for the interface (default
-+                                "100000")
- Name:   i2c6
-@@ -1242,6 +1248,8 @@ Info:   Enable the i2c6 bus
- Load:   dtoverlay=i2c6,<param>
- Params: pins_0_1                Use GPIOs 0 and 1
-         pins_22_23              Use GPIOs 22 and 23 (default)
-+        baudrate                Set the baudrate for the interface (default
-+                                "100000")
- Name:   i2s-gpio28-31
---- a/arch/arm/boot/dts/overlays/i2c3-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
-@@ -6,10 +6,11 @@
-       fragment@0 {
-               target = <&i2c3>;
--              __overlay__ {
-+              frag0: __overlay__ {
-                       status = "okay";
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&i2c3_pins>;
-+                      clock-frequency = <100000>;
-               };
-       };
-@@ -20,8 +21,16 @@
-               };
-       };
-+      fragment@2 {
-+              target = <&i2c3_pins>;
-+              __overlay__ {
-+                      brcm,pins = <4 5>;
-+              };
-+      };
-+
-       __overrides__ {
--              pins_2_3 = <0>,"=1";
--              pins_4_5 = <0>,"!1";
-+              pins_2_3 = <0>,"=1!2";
-+              pins_4_5 = <0>,"!1=2";
-+              baudrate = <&frag0>, "clock-frequency:0";
-       };
- };
---- a/arch/arm/boot/dts/overlays/i2c4-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
-@@ -6,10 +6,11 @@
-       fragment@0 {
-               target = <&i2c4>;
--              __overlay__ {
-+              frag0: __overlay__ {
-                       status = "okay";
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&i2c4_pins>;
-+                      clock-frequency = <100000>;
-               };
-       };
-@@ -20,8 +21,16 @@
-               };
-       };
-+      fragment@2 {
-+              target = <&i2c4_pins>;
-+              __overlay__ {
-+                      brcm,pins = <8 9>;
-+              };
-+      };
-+
-       __overrides__ {
--              pins_6_7 = <0>,"=1";
--              pins_8_9 = <0>,"!1";
-+              pins_6_7 = <0>,"=1!2";
-+              pins_8_9 = <0>,"!1=2";
-+              baudrate = <&frag0>, "clock-frequency:0";
-       };
- };
---- a/arch/arm/boot/dts/overlays/i2c5-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
-@@ -6,10 +6,11 @@
-       fragment@0 {
-               target = <&i2c5>;
--              __overlay__ {
-+              frag0: __overlay__ {
-                       status = "okay";
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&i2c5_pins>;
-+                      clock-frequency = <100000>;
-               };
-       };
-@@ -20,8 +21,16 @@
-               };
-       };
-+      fragment@2 {
-+              target = <&i2c5_pins>;
-+              __overlay__ {
-+                      brcm,pins = <12 13>;
-+              };
-+      };
-+
-       __overrides__ {
--              pins_10_11 = <0>,"=1";
--              pins_12_13 = <0>,"!1";
-+              pins_10_11 = <0>,"=1!2";
-+              pins_12_13 = <0>,"!1=2";
-+              baudrate = <&frag0>, "clock-frequency:0";
-       };
- };
---- a/arch/arm/boot/dts/overlays/i2c6-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
-@@ -6,10 +6,11 @@
-       fragment@0 {
-               target = <&i2c6>;
--              __overlay__ {
-+              frag0: __overlay__ {
-                       status = "okay";
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&i2c6_pins>;
-+                      clock-frequency = <100000>;
-               };
-       };
-@@ -20,8 +21,16 @@
-               };
-       };
-+      fragment@2 {
-+              target = <&i2c6_pins>;
-+              __overlay__ {
-+                      brcm,pins = <22 23>;
-+              };
-+      };
-+
-       __overrides__ {
--              pins_0_1 = <0>,"=1";
--              pins_22_23 = <0>,"!1";
-+              pins_0_1 = <0>,"=1!2";
-+              pins_22_23 = <0>,"!1=2";
-+              baudrate = <&frag0>, "clock-frequency:0";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0655-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch b/target/linux/brcm2708/patches-4.19/950-0655-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch
deleted file mode 100644 (file)
index e88bfc6..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-From df276f0a5aa865c7926d9d148605d1a59d1d4fbb Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 25 Jul 2019 17:27:44 +0100
-Subject: [PATCH] drm/vc4: Resolve the vblank warnings on mode
- switching
-
-The details over when and how a driver is to service the
-vblank events are sketchy, and the fkms driver was triggering
-a kernel warning every time the crtc was enabled or disabled.
-
-Copy the event handling as used by the vc4-kms driver slightly
-more closely, and we avoid the warnings.
-
-https://github.com/raspberrypi/linux/issues/3020
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++--------
- 1 file changed, 33 insertions(+), 15 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -933,6 +933,7 @@ static void vc4_crtc_mode_set_nofb(struc
- static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+      struct drm_device *dev = crtc->dev;
-       struct drm_plane *plane;
-       DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
-@@ -948,6 +949,35 @@ static void vc4_crtc_disable(struct drm_
-       drm_atomic_crtc_for_each_plane(plane, crtc)
-               vc4_plane_atomic_disable(plane, plane->state);
-+
-+      /*
-+       * Make sure we issue a vblank event after disabling the CRTC if
-+       * someone was waiting it.
-+       */
-+      if (crtc->state->event) {
-+              unsigned long flags;
-+
-+              spin_lock_irqsave(&dev->event_lock, flags);
-+              drm_crtc_send_vblank_event(crtc, crtc->state->event);
-+              crtc->state->event = NULL;
-+              spin_unlock_irqrestore(&dev->event_lock, flags);
-+      }
-+}
-+
-+static void vc4_crtc_consume_event(struct drm_crtc *crtc)
-+{
-+      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+      struct drm_device *dev = crtc->dev;
-+      unsigned long flags;
-+
-+      crtc->state->event->pipe = drm_crtc_index(crtc);
-+
-+      WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-+
-+      spin_lock_irqsave(&dev->event_lock, flags);
-+      vc4_crtc->event = crtc->state->event;
-+      crtc->state->event = NULL;
-+      spin_unlock_irqrestore(&dev->event_lock, flags);
- }
- static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
-@@ -957,6 +987,7 @@ static void vc4_crtc_enable(struct drm_c
-       DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
-                     crtc->base.id);
-       drm_crtc_vblank_on(crtc);
-+      vc4_crtc_consume_event(crtc);
-       /* Unblank the planes (if they're supposed to be displayed). */
-       drm_atomic_crtc_for_each_plane(plane, crtc)
-@@ -1028,23 +1059,10 @@ static int vc4_crtc_atomic_check(struct
- static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
-                                 struct drm_crtc_state *old_state)
- {
--      struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
--      struct drm_device *dev = crtc->dev;
--
-       DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
-                     crtc->base.id);
--      if (crtc->state->event) {
--              unsigned long flags;
--
--              crtc->state->event->pipe = drm_crtc_index(crtc);
--
--              WARN_ON(drm_crtc_vblank_get(crtc) != 0);
--
--              spin_lock_irqsave(&dev->event_lock, flags);
--              vc4_crtc->event = crtc->state->event;
--              crtc->state->event = NULL;
--              spin_unlock_irqrestore(&dev->event_lock, flags);
--      }
-+      if (crtc->state->active && old_state->active && crtc->state->event)
-+              vc4_crtc_consume_event(crtc);
- }
- static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
diff --git a/target/linux/brcm2708/patches-4.19/950-0655-staging-bcm2835-codec-Expand-logging-on-format-setti.patch b/target/linux/brcm2708/patches-4.19/950-0655-staging-bcm2835-codec-Expand-logging-on-format-setti.patch
new file mode 100644 (file)
index 0000000..f74fc4b
--- /dev/null
@@ -0,0 +1,42 @@
+From 9a9ef8123467579c431ced1e98827364d66c615f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 11 Jul 2019 14:57:09 +0100
+Subject: [PATCH] staging:bcm2835-codec: Expand logging on format
+ setting
+
+Adds some more useful logging during format changed events and
+s_fmt.
+
+Reported by: zillevdr <zillevdr@gmx.de>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c   | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -753,6 +753,10 @@ static void handle_fmt_changed(struct bc
+                format->es.video.color_space);
+       q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format was %ux%u, crop %ux%u\n",
++               __func__, q_data->bytesperline, q_data->height,
++               q_data->crop_width, q_data->crop_height);
++
+       q_data->crop_width = format->es.video.crop.width;
+       q_data->crop_height = format->es.video.crop.height;
+       q_data->bytesperline = format->es.video.crop.width;
+@@ -1110,10 +1114,10 @@ static int vidioc_s_fmt(struct bcm2835_c
+       bool update_capture_port = false;
+       int ret;
+-      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
++      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: " V4L2_FOURCC_CONV ", size %u\n",
+                f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+-               f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
+-
++               V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat),
++               f->fmt.pix_mp.plane_fmt[0].sizeimage);
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
diff --git a/target/linux/brcm2708/patches-4.19/950-0656-drm-vc4-Remove-unused-mode-variable.patch b/target/linux/brcm2708/patches-4.19/950-0656-drm-vc4-Remove-unused-mode-variable.patch
deleted file mode 100644 (file)
index e12cac2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From b2f463facb358b917380683b5e86c5d1cb3db123 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 25 Jul 2019 17:34:29 +0100
-Subject: [PATCH] drm/vc4: Remove unused mode variable
-
-"89d1376 drm/vc4: Add support for margins to fkms" removed
-the requirement for having the mode structure from vc4_plane_to_mb,
-but didn't remove it as a local to the function, causing a
-compiler warning.
-
-Remove the unused variable.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -523,7 +523,6 @@ static int vc4_plane_to_mb(struct drm_pl
-       const struct vc_image_format *vc_fmt =
-                                       vc4_get_vc_image_fmt(drm_fmt->format);
-       int num_planes = fb->format->num_planes;
--      struct drm_display_mode *mode = &state->crtc->mode;
-       unsigned int rotation = SUPPORTED_ROTATIONS;
-       mb->plane.vc_image_type = vc_fmt->vc_image;
diff --git a/target/linux/brcm2708/patches-4.19/950-0656-staging-bcm2835-codec-Correct-bytesperline-on-format.patch b/target/linux/brcm2708/patches-4.19/950-0656-staging-bcm2835-codec-Correct-bytesperline-on-format.patch
new file mode 100644 (file)
index 0000000..96f3351
--- /dev/null
@@ -0,0 +1,30 @@
+From bcb6e267ca61ce685ed2debc0cee327527cea20d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 11 Jul 2019 14:58:35 +0100
+Subject: [PATCH] staging: bcm2835-codec: Correct bytesperline on
+ format changed
+
+The handling of format changed events incorrectly set bytesperline
+to the cropped width, which ignored padding and formats with
+more than 8bpp.
+Fix these.
+
+Reported by: zillevdr <zillevdr@gmx.de>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c  | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -759,7 +759,9 @@ static void handle_fmt_changed(struct bc
+       q_data->crop_width = format->es.video.crop.width;
+       q_data->crop_height = format->es.video.crop.height;
+-      q_data->bytesperline = format->es.video.crop.width;
++      q_data->bytesperline = get_bytesperline(format->es.video.width,
++                                              q_data->fmt);
++
+       q_data->height = format->es.video.height;
+       q_data->sizeimage = format->buffer_size_min;
+       if (format->es.video.color_space)
diff --git a/target/linux/brcm2708/patches-4.19/950-0657-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch b/target/linux/brcm2708/patches-4.19/950-0657-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch
new file mode 100644 (file)
index 0000000..8a97747
--- /dev/null
@@ -0,0 +1,28 @@
+From cbe5c2a67fb145b210652be20a84690e09e4eb25 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 7 Aug 2019 11:31:08 +0100
+Subject: [PATCH] drm/vc4: Add missing NULL check to
+ vc4_crtc_consume_event
+
+vc4_crtc_consume_event wasn't checking crtc->state->event was
+set before dereferencing it, leading to an OOPS.
+
+Fixes "a5b534b drm/vc4: Resolve the vblank warnings on mode switching"
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -969,6 +969,9 @@ static void vc4_crtc_consume_event(struc
+       struct drm_device *dev = crtc->dev;
+       unsigned long flags;
++      if (!crtc->state->event)
++              return;
++
+       crtc->state->event->pipe = drm_crtc_index(crtc);
+       WARN_ON(drm_crtc_vblank_get(crtc) != 0);
diff --git a/target/linux/brcm2708/patches-4.19/950-0657-staging-bcm2835-codec-Expand-logging-on-format-setti.patch b/target/linux/brcm2708/patches-4.19/950-0657-staging-bcm2835-codec-Expand-logging-on-format-setti.patch
deleted file mode 100644 (file)
index f74fc4b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 9a9ef8123467579c431ced1e98827364d66c615f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 11 Jul 2019 14:57:09 +0100
-Subject: [PATCH] staging:bcm2835-codec: Expand logging on format
- setting
-
-Adds some more useful logging during format changed events and
-s_fmt.
-
-Reported by: zillevdr <zillevdr@gmx.de>
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c   | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -753,6 +753,10 @@ static void handle_fmt_changed(struct bc
-                format->es.video.color_space);
-       q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format was %ux%u, crop %ux%u\n",
-+               __func__, q_data->bytesperline, q_data->height,
-+               q_data->crop_width, q_data->crop_height);
-+
-       q_data->crop_width = format->es.video.crop.width;
-       q_data->crop_height = format->es.video.crop.height;
-       q_data->bytesperline = format->es.video.crop.width;
-@@ -1110,10 +1114,10 @@ static int vidioc_s_fmt(struct bcm2835_c
-       bool update_capture_port = false;
-       int ret;
--      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
-+      v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: " V4L2_FOURCC_CONV ", size %u\n",
-                f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
--               f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
--
-+               V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat),
-+               f->fmt.pix_mp.plane_fmt[0].sizeimage);
-       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-       if (!vq)
diff --git a/target/linux/brcm2708/patches-4.19/950-0658-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch b/target/linux/brcm2708/patches-4.19/950-0658-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch
new file mode 100644 (file)
index 0000000..beeeb2f
--- /dev/null
@@ -0,0 +1,52 @@
+From 103afc4641ab8d6587e981a5e3fda27427a8bf4b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 9 Aug 2019 08:51:43 +0100
+Subject: [PATCH] net: bcmgenet: Workaround #2 for Pi4 Ethernet fail
+
+Some combinations of Pi 4Bs and Ethernet switches don't reliably get a
+DCHP-assigned IP address, leaving the unit with a self=assigned 169.254
+address. In the failure case, the Pi is left able to receive packets
+but not send them, suggesting that the MAC<->PHY link is getting into
+a bad state.
+
+It has been found empirically that skipping a reset step by the genet
+driver prevents the failures. No downsides have been discovered yet,
+and unlike the forced renegotiation it doesn't increase the time to
+get an IP address, so the workaround is enabled by default; add
+
+  genet.skip_umac_reset=n
+
+to the command line to disable it.
+
+See: https://github.com/raspberrypi/linux/issues/3108
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -72,6 +72,10 @@
+ #define GENET_RDMA_REG_OFF    (priv->hw_params->rdma_offset + \
+                               TOTAL_DESC * DMA_DESC_SIZE)
++static bool skip_umac_reset = true;
++module_param(skip_umac_reset, bool, 0444);
++MODULE_PARM_DESC(skip_umac_reset, "Skip UMAC reset step");
++
+ static inline void bcmgenet_writel(u32 value, void __iomem *offset)
+ {
+       /* MIPS chips strapped for BE will automagically configure the
+@@ -1993,6 +1997,11 @@ static void reset_umac(struct bcmgenet_p
+       bcmgenet_rbuf_ctrl_set(priv, 0);
+       udelay(10);
++      if (skip_umac_reset) {
++              pr_warn("Skipping UMAC reset\n");
++              return;
++      }
++
+       /* disable MAC while updating its registers */
+       bcmgenet_umac_writel(priv, 0, UMAC_CMD);
diff --git a/target/linux/brcm2708/patches-4.19/950-0658-staging-bcm2835-codec-Correct-bytesperline-on-format.patch b/target/linux/brcm2708/patches-4.19/950-0658-staging-bcm2835-codec-Correct-bytesperline-on-format.patch
deleted file mode 100644 (file)
index 96f3351..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From bcb6e267ca61ce685ed2debc0cee327527cea20d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 11 Jul 2019 14:58:35 +0100
-Subject: [PATCH] staging: bcm2835-codec: Correct bytesperline on
- format changed
-
-The handling of format changed events incorrectly set bytesperline
-to the cropped width, which ignored padding and formats with
-more than 8bpp.
-Fix these.
-
-Reported by: zillevdr <zillevdr@gmx.de>
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c  | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -759,7 +759,9 @@ static void handle_fmt_changed(struct bc
-       q_data->crop_width = format->es.video.crop.width;
-       q_data->crop_height = format->es.video.crop.height;
--      q_data->bytesperline = format->es.video.crop.width;
-+      q_data->bytesperline = get_bytesperline(format->es.video.width,
-+                                              q_data->fmt);
-+
-       q_data->height = format->es.video.height;
-       q_data->sizeimage = format->buffer_size_min;
-       if (format->es.video.color_space)
diff --git a/target/linux/brcm2708/patches-4.19/950-0659-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch b/target/linux/brcm2708/patches-4.19/950-0659-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch
deleted file mode 100644 (file)
index 8a97747..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From cbe5c2a67fb145b210652be20a84690e09e4eb25 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 7 Aug 2019 11:31:08 +0100
-Subject: [PATCH] drm/vc4: Add missing NULL check to
- vc4_crtc_consume_event
-
-vc4_crtc_consume_event wasn't checking crtc->state->event was
-set before dereferencing it, leading to an OOPS.
-
-Fixes "a5b534b drm/vc4: Resolve the vblank warnings on mode switching"
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -969,6 +969,9 @@ static void vc4_crtc_consume_event(struc
-       struct drm_device *dev = crtc->dev;
-       unsigned long flags;
-+      if (!crtc->state->event)
-+              return;
-+
-       crtc->state->event->pipe = drm_crtc_index(crtc);
-       WARN_ON(drm_crtc_vblank_get(crtc) != 0);
diff --git a/target/linux/brcm2708/patches-4.19/950-0659-drm-vc4-Fix-TILE_Y_OFFSET-definitions.patch b/target/linux/brcm2708/patches-4.19/950-0659-drm-vc4-Fix-TILE_Y_OFFSET-definitions.patch
new file mode 100644 (file)
index 0000000..bffed9e
--- /dev/null
@@ -0,0 +1,27 @@
+From c1fffc2a7dbf7e59aaef36378fb14d1c3dc016a6 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 3 Aug 2018 11:22:27 +0200
+Subject: [PATCH] drm/vc4: Fix TILE_Y_OFFSET definitions
+
+Y_OFFSET field starts at bit 8 not 7.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-1-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_regs.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -1043,8 +1043,8 @@ enum hvs_pixel_format {
+ #define SCALER_PITCH0_TILE_LINE_DIR           BIT(15)
+ #define SCALER_PITCH0_TILE_INITIAL_LINE_DIR   BIT(14)
+ /* Y offset within a tile. */
+-#define SCALER_PITCH0_TILE_Y_OFFSET_MASK      VC4_MASK(13, 7)
+-#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT     7
++#define SCALER_PITCH0_TILE_Y_OFFSET_MASK      VC4_MASK(13, 8)
++#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT     8
+ #define SCALER_PITCH0_TILE_WIDTH_R_MASK               VC4_MASK(6, 0)
+ #define SCALER_PITCH0_TILE_WIDTH_R_SHIFT      0
diff --git a/target/linux/brcm2708/patches-4.19/950-0660-drm-vc4-Define-missing-PITCH0_SINK_PIX-field.patch b/target/linux/brcm2708/patches-4.19/950-0660-drm-vc4-Define-missing-PITCH0_SINK_PIX-field.patch
new file mode 100644 (file)
index 0000000..b1be632
--- /dev/null
@@ -0,0 +1,28 @@
+From d0b90f9c68a96f2bee66d796cb33367d205e586a Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 3 Aug 2018 11:22:28 +0200
+Subject: [PATCH] drm/vc4: Define missing PITCH0_SINK_PIX field
+
+This is needed to support X/Y negative placement of planes using
+T-format buffers.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-2-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_regs.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -1037,6 +1037,10 @@ enum hvs_pixel_format {
+ #define SCALER_TILE_HEIGHT_MASK                       VC4_MASK(15, 0)
+ #define SCALER_TILE_HEIGHT_SHIFT              0
++/* Common PITCH0 fields */
++#define SCALER_PITCH0_SINK_PIX_MASK           VC4_MASK(31, 26)
++#define SCALER_PITCH0_SINK_PIX_SHIFT          26
++
+ /* PITCH0 fields for T-tiled. */
+ #define SCALER_PITCH0_TILE_WIDTH_L_MASK               VC4_MASK(22, 16)
+ #define SCALER_PITCH0_TILE_WIDTH_L_SHIFT      16
diff --git a/target/linux/brcm2708/patches-4.19/950-0660-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch b/target/linux/brcm2708/patches-4.19/950-0660-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch
deleted file mode 100644 (file)
index beeeb2f..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 103afc4641ab8d6587e981a5e3fda27427a8bf4b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 9 Aug 2019 08:51:43 +0100
-Subject: [PATCH] net: bcmgenet: Workaround #2 for Pi4 Ethernet fail
-
-Some combinations of Pi 4Bs and Ethernet switches don't reliably get a
-DCHP-assigned IP address, leaving the unit with a self=assigned 169.254
-address. In the failure case, the Pi is left able to receive packets
-but not send them, suggesting that the MAC<->PHY link is getting into
-a bad state.
-
-It has been found empirically that skipping a reset step by the genet
-driver prevents the failures. No downsides have been discovered yet,
-and unlike the forced renegotiation it doesn't increase the time to
-get an IP address, so the workaround is enabled by default; add
-
-  genet.skip_umac_reset=n
-
-to the command line to disable it.
-
-See: https://github.com/raspberrypi/linux/issues/3108
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
---- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-@@ -72,6 +72,10 @@
- #define GENET_RDMA_REG_OFF    (priv->hw_params->rdma_offset + \
-                               TOTAL_DESC * DMA_DESC_SIZE)
-+static bool skip_umac_reset = true;
-+module_param(skip_umac_reset, bool, 0444);
-+MODULE_PARM_DESC(skip_umac_reset, "Skip UMAC reset step");
-+
- static inline void bcmgenet_writel(u32 value, void __iomem *offset)
- {
-       /* MIPS chips strapped for BE will automagically configure the
-@@ -1993,6 +1997,11 @@ static void reset_umac(struct bcmgenet_p
-       bcmgenet_rbuf_ctrl_set(priv, 0);
-       udelay(10);
-+      if (skip_umac_reset) {
-+              pr_warn("Skipping UMAC reset\n");
-+              return;
-+      }
-+
-       /* disable MAC while updating its registers */
-       bcmgenet_umac_writel(priv, 0, UMAC_CMD);
diff --git a/target/linux/brcm2708/patches-4.19/950-0661-drm-vc4-Fix-TILE_Y_OFFSET-definitions.patch b/target/linux/brcm2708/patches-4.19/950-0661-drm-vc4-Fix-TILE_Y_OFFSET-definitions.patch
deleted file mode 100644 (file)
index bffed9e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From c1fffc2a7dbf7e59aaef36378fb14d1c3dc016a6 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 3 Aug 2018 11:22:27 +0200
-Subject: [PATCH] drm/vc4: Fix TILE_Y_OFFSET definitions
-
-Y_OFFSET field starts at bit 8 not 7.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-1-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_regs.h | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_regs.h
-+++ b/drivers/gpu/drm/vc4/vc4_regs.h
-@@ -1043,8 +1043,8 @@ enum hvs_pixel_format {
- #define SCALER_PITCH0_TILE_LINE_DIR           BIT(15)
- #define SCALER_PITCH0_TILE_INITIAL_LINE_DIR   BIT(14)
- /* Y offset within a tile. */
--#define SCALER_PITCH0_TILE_Y_OFFSET_MASK      VC4_MASK(13, 7)
--#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT     7
-+#define SCALER_PITCH0_TILE_Y_OFFSET_MASK      VC4_MASK(13, 8)
-+#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT     8
- #define SCALER_PITCH0_TILE_WIDTH_R_MASK               VC4_MASK(6, 0)
- #define SCALER_PITCH0_TILE_WIDTH_R_SHIFT      0
diff --git a/target/linux/brcm2708/patches-4.19/950-0661-drm-vc4-Use-drm_atomic_helper_check_plane_state-to-s.patch b/target/linux/brcm2708/patches-4.19/950-0661-drm-vc4-Use-drm_atomic_helper_check_plane_state-to-s.patch
new file mode 100644 (file)
index 0000000..3ead02c
--- /dev/null
@@ -0,0 +1,157 @@
+From 2a98dc34696c6510a49a684eb56d3a9c2a150571 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Fri, 3 Aug 2018 11:22:29 +0200
+Subject: [PATCH] drm/vc4: Use drm_atomic_helper_check_plane_state() to
+ simplify the logic
+
+drm_atomic_helper_check_plane_state() takes care of checking the
+scaling capabilities and calculating the clipped X/Y offsets for us.
+
+Rely on this function instead of open-coding the logic.
+
+Incidentally, it seems to fix a problem we had with negative X/Y
+positioning of YUV planes.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-3-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 103 ++++++++++++++++----------------
+ 1 file changed, 52 insertions(+), 51 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -313,31 +313,59 @@ static int vc4_plane_setup_clipping_and_
+       u32 subpixel_src_mask = (1 << 16) - 1;
+       u32 format = fb->format->format;
+       int num_planes = fb->format->num_planes;
+-      u32 h_subsample = 1;
+-      u32 v_subsample = 1;
+-      int ret;
+-      int i;
++      int min_scale = 1, max_scale = INT_MAX;
++      struct drm_crtc_state *crtc_state;
++      u32 h_subsample, v_subsample;
++      int i, ret;
++
++      crtc_state = drm_atomic_get_existing_crtc_state(state->state,
++                                                      state->crtc);
++      if (!crtc_state) {
++              DRM_DEBUG_KMS("Invalid crtc state\n");
++              return -EINVAL;
++      }
++
++      /* No configuring scaling on the cursor plane, since it gets
++       * non-vblank-synced updates, and scaling requires LBM changes which
++       * have to be vblank-synced.
++       */
++      if (plane->type == DRM_PLANE_TYPE_CURSOR) {
++              min_scale = DRM_PLANE_HELPER_NO_SCALING;
++              max_scale = DRM_PLANE_HELPER_NO_SCALING;
++      } else {
++              min_scale = 1;
++              max_scale = INT_MAX;
++      }
++
++      ret = drm_atomic_helper_check_plane_state(state, crtc_state,
++                                                min_scale, max_scale,
++                                                true, true);
++      if (ret)
++              return ret;
++
++      h_subsample = drm_format_horz_chroma_subsampling(format);
++      v_subsample = drm_format_vert_chroma_subsampling(format);
+       for (i = 0; i < num_planes; i++)
+               vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
+       /* We don't support subpixel source positioning for scaling. */
+-      if ((state->src_x & subpixel_src_mask) ||
+-          (state->src_y & subpixel_src_mask) ||
+-          (state->src_w & subpixel_src_mask) ||
+-          (state->src_h & subpixel_src_mask)) {
++      if ((state->src.x1 & subpixel_src_mask) ||
++          (state->src.x2 & subpixel_src_mask) ||
++          (state->src.y1 & subpixel_src_mask) ||
++          (state->src.y2 & subpixel_src_mask)) {
+               return -EINVAL;
+       }
+-      vc4_state->src_x = state->src_x >> 16;
+-      vc4_state->src_y = state->src_y >> 16;
+-      vc4_state->src_w[0] = state->src_w >> 16;
+-      vc4_state->src_h[0] = state->src_h >> 16;
+-
+-      vc4_state->crtc_x = state->crtc_x;
+-      vc4_state->crtc_y = state->crtc_y;
+-      vc4_state->crtc_w = state->crtc_w;
+-      vc4_state->crtc_h = state->crtc_h;
++      vc4_state->src_x = state->src.x1 >> 16;
++      vc4_state->src_y = state->src.y1 >> 16;
++      vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16;
++      vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16;
++
++      vc4_state->crtc_x = state->dst.x1;
++      vc4_state->crtc_y = state->dst.y1;
++      vc4_state->crtc_w = state->dst.x2 - state->dst.x1;
++      vc4_state->crtc_h = state->dst.y2 - state->dst.y1;
+       ret = vc4_plane_margins_adj(state);
+       if (ret)
+@@ -354,8 +382,6 @@ static int vc4_plane_setup_clipping_and_
+       if (num_planes > 1) {
+               vc4_state->is_yuv = true;
+-              h_subsample = drm_format_horz_chroma_subsampling(format);
+-              v_subsample = drm_format_vert_chroma_subsampling(format);
+               vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample;
+               vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample;
+@@ -380,39 +406,14 @@ static int vc4_plane_setup_clipping_and_
+               vc4_state->y_scaling[1] = VC4_SCALING_NONE;
+       }
+-      /* No configuring scaling on the cursor plane, since it gets
+-         non-vblank-synced updates, and scaling requires requires
+-         LBM changes which have to be vblank-synced.
+-       */
+-      if (plane->type == DRM_PLANE_TYPE_CURSOR && !vc4_state->is_unity)
+-              return -EINVAL;
+-
+-      /* Clamp the on-screen start x/y to 0.  The hardware doesn't
+-       * support negative y, and negative x wastes bandwidth.
+-       */
+-      if (vc4_state->crtc_x < 0) {
+-              for (i = 0; i < num_planes; i++) {
+-                      u32 cpp = fb->format->cpp[i];
+-                      u32 subs = ((i == 0) ? 1 : h_subsample);
+-
+-                      vc4_state->offsets[i] += (cpp *
+-                                                (-vc4_state->crtc_x) / subs);
+-              }
+-              vc4_state->src_w[0] += vc4_state->crtc_x;
+-              vc4_state->src_w[1] += vc4_state->crtc_x / h_subsample;
+-              vc4_state->crtc_x = 0;
+-      }
+-
+-      if (vc4_state->crtc_y < 0) {
+-              for (i = 0; i < num_planes; i++) {
+-                      u32 subs = ((i == 0) ? 1 : v_subsample);
+-
+-                      vc4_state->offsets[i] += (fb->pitches[i] *
+-                                                (-vc4_state->crtc_y) / subs);
+-              }
+-              vc4_state->src_h[0] += vc4_state->crtc_y;
+-              vc4_state->src_h[1] += vc4_state->crtc_y / v_subsample;
+-              vc4_state->crtc_y = 0;
++      /* Adjust the base pointer to the first pixel to be scanned out. */
++      for (i = 0; i < num_planes; i++) {
++              vc4_state->offsets[i] += (vc4_state->src_y /
++                                        (i ? v_subsample : 1)) *
++                                       fb->pitches[i];
++              vc4_state->offsets[i] += (vc4_state->src_x /
++                                        (i ? h_subsample : 1)) *
++                                       fb->format->cpp[i];
+       }
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0662-drm-vc4-Define-missing-PITCH0_SINK_PIX-field.patch b/target/linux/brcm2708/patches-4.19/950-0662-drm-vc4-Define-missing-PITCH0_SINK_PIX-field.patch
deleted file mode 100644 (file)
index b1be632..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From d0b90f9c68a96f2bee66d796cb33367d205e586a Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 3 Aug 2018 11:22:28 +0200
-Subject: [PATCH] drm/vc4: Define missing PITCH0_SINK_PIX field
-
-This is needed to support X/Y negative placement of planes using
-T-format buffers.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-2-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_regs.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_regs.h
-+++ b/drivers/gpu/drm/vc4/vc4_regs.h
-@@ -1037,6 +1037,10 @@ enum hvs_pixel_format {
- #define SCALER_TILE_HEIGHT_MASK                       VC4_MASK(15, 0)
- #define SCALER_TILE_HEIGHT_SHIFT              0
-+/* Common PITCH0 fields */
-+#define SCALER_PITCH0_SINK_PIX_MASK           VC4_MASK(31, 26)
-+#define SCALER_PITCH0_SINK_PIX_SHIFT          26
-+
- /* PITCH0 fields for T-tiled. */
- #define SCALER_PITCH0_TILE_WIDTH_L_MASK               VC4_MASK(22, 16)
- #define SCALER_PITCH0_TILE_WIDTH_L_SHIFT      16
diff --git a/target/linux/brcm2708/patches-4.19/950-0662-drm-vc4-Move-offsets-adjustment-out-of-setup_clippin.patch b/target/linux/brcm2708/patches-4.19/950-0662-drm-vc4-Move-offsets-adjustment-out-of-setup_clippin.patch
new file mode 100644 (file)
index 0000000..9820c91
--- /dev/null
@@ -0,0 +1,73 @@
+From 58a92eae6ed463c294381e72eefec701d23fcdaf Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Fri, 3 Aug 2018 11:22:30 +0200
+Subject: [PATCH] adjustment out of
+ setup_clipping_and_scaling()
+
+The offset adjustment depends on the framebuffer modified, so let's
+just move this operation in the DRM_FORMAT_MOD_LINEAR case inside
+vc4_plane_mode_set().
+
+This we'll be able to fix offset calculation for
+DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED and DRM_FORMAT_MOD_BROADCOM_SANDXXX.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-4-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -406,16 +406,6 @@ static int vc4_plane_setup_clipping_and_
+               vc4_state->y_scaling[1] = VC4_SCALING_NONE;
+       }
+-      /* Adjust the base pointer to the first pixel to be scanned out. */
+-      for (i = 0; i < num_planes; i++) {
+-              vc4_state->offsets[i] += (vc4_state->src_y /
+-                                        (i ? v_subsample : 1)) *
+-                                       fb->pitches[i];
+-              vc4_state->offsets[i] += (vc4_state->src_x /
+-                                        (i ? h_subsample : 1)) *
+-                                       fb->format->cpp[i];
+-      }
+-
+       return 0;
+ }
+@@ -523,6 +513,7 @@ static int vc4_plane_mode_set(struct drm
+       const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
+       u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
+       int num_planes = drm_format_num_planes(format->drm);
++      u32 h_subsample, v_subsample;
+       bool mix_plane_alpha;
+       bool covers_screen;
+       u32 scl0, scl1, pitch0;
+@@ -568,10 +559,25 @@ static int vc4_plane_mode_set(struct drm
+               scl1 = vc4_get_scl_field(state, 0);
+       }
++      h_subsample = drm_format_horz_chroma_subsampling(format->drm);
++      v_subsample = drm_format_vert_chroma_subsampling(format->drm);
++
+       switch (base_format_mod) {
+       case DRM_FORMAT_MOD_LINEAR:
+               tiling = SCALER_CTL0_TILING_LINEAR;
+               pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
++
++              /* Adjust the base pointer to the first pixel to be scanned
++               * out.
++               */
++              for (i = 0; i < num_planes; i++) {
++                      vc4_state->offsets[i] += vc4_state->src_y /
++                                               (i ? v_subsample : 1) *
++                                               fb->pitches[i];
++                      vc4_state->offsets[i] += vc4_state->src_x /
++                                               (i ? h_subsample : 1) *
++                                               fb->format->cpp[i];
++              }
+               break;
+       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
diff --git a/target/linux/brcm2708/patches-4.19/950-0663-drm-vc4-Fix-X-Y-positioning-of-planes-using-T_TILES-.patch b/target/linux/brcm2708/patches-4.19/950-0663-drm-vc4-Fix-X-Y-positioning-of-planes-using-T_TILES-.patch
new file mode 100644 (file)
index 0000000..6197d90
--- /dev/null
@@ -0,0 +1,86 @@
+From 010e3665babdf589e26e2fb098ac1f39e519c0f6 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Fri, 3 Aug 2018 11:22:31 +0200
+Subject: [PATCH] drm/vc4: Fix X/Y positioning of planes using T_TILES
+ modifier
+
+X/Y positioning of T-format buffers is quite tricky and the current
+implementation was failing to position a plane using this format
+correctly when the CRTC X, Y or both X and Y offsets were negative.
+It was also failing when the SRC X/Y offsets were != 0.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-5-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 50 ++++++++++++++++++++++++++++-----
+ 1 file changed, 43 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -578,22 +578,58 @@ static int vc4_plane_mode_set(struct drm
+                                                (i ? h_subsample : 1) *
+                                                fb->format->cpp[i];
+               }
++
+               break;
+       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
+-              /* For T-tiled, the FB pitch is "how many bytes from
+-               * one row to the next, such that pitch * tile_h ==
+-               * tile_size * tiles_per_row."
+-               */
+               u32 tile_size_shift = 12; /* T tiles are 4kb */
++              /* Whole-tile offsets, mostly for setting the pitch. */
++              u32 tile_w_shift = fb->format->cpp[0] == 2 ? 6 : 5;
+               u32 tile_h_shift = 5; /* 16 and 32bpp are 32 pixels high */
++              u32 tile_w_mask = (1 << tile_w_shift) - 1;
++              /* The height mask on 32-bit-per-pixel tiles is 63, i.e. twice
++               * the height (in pixels) of a 4k tile.
++               */
++              u32 tile_h_mask = (2 << tile_h_shift) - 1;
++              /* For T-tiled, the FB pitch is "how many bytes from one row to
++               * the next, such that
++               *
++               *      pitch * tile_h == tile_size * tiles_per_row
++               */
+               u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
++              u32 tiles_l = vc4_state->src_x >> tile_w_shift;
++              u32 tiles_r = tiles_w - tiles_l;
++              u32 tiles_t = vc4_state->src_y >> tile_h_shift;
++              /* Intra-tile offsets, which modify the base address (the
++               * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
++               * base address).
++               */
++              u32 tile_y = (vc4_state->src_y >> 4) & 1;
++              u32 subtile_y = (vc4_state->src_y >> 2) & 3;
++              u32 utile_y = vc4_state->src_y & 3;
++              u32 x_off = vc4_state->src_x & tile_w_mask;
++              u32 y_off = vc4_state->src_y & tile_h_mask;
+               tiling = SCALER_CTL0_TILING_256B_OR_T;
++              pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
++                        VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
++                        VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
++                        VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
++              vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift);
++              vc4_state->offsets[0] += subtile_y << 8;
++              vc4_state->offsets[0] += utile_y << 4;
++
++              /* Rows of tiles alternate left-to-right and right-to-left. */
++              if (tiles_t & 1) {
++                      pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
++                      vc4_state->offsets[0] += (tiles_w - tiles_l) <<
++                                               tile_size_shift;
++                      vc4_state->offsets[0] -= (1 + !tile_y) << 10;
++              } else {
++                      vc4_state->offsets[0] += tiles_l << tile_size_shift;
++                      vc4_state->offsets[0] += tile_y << 10;
++              }
+-              pitch0 = (VC4_SET_FIELD(0, SCALER_PITCH0_TILE_Y_OFFSET) |
+-                        VC4_SET_FIELD(0, SCALER_PITCH0_TILE_WIDTH_L) |
+-                        VC4_SET_FIELD(tiles_w, SCALER_PITCH0_TILE_WIDTH_R));
+               break;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0663-drm-vc4-Use-drm_atomic_helper_check_plane_state-to-s.patch b/target/linux/brcm2708/patches-4.19/950-0663-drm-vc4-Use-drm_atomic_helper_check_plane_state-to-s.patch
deleted file mode 100644 (file)
index 3ead02c..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-From 2a98dc34696c6510a49a684eb56d3a9c2a150571 Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Fri, 3 Aug 2018 11:22:29 +0200
-Subject: [PATCH] drm/vc4: Use drm_atomic_helper_check_plane_state() to
- simplify the logic
-
-drm_atomic_helper_check_plane_state() takes care of checking the
-scaling capabilities and calculating the clipped X/Y offsets for us.
-
-Rely on this function instead of open-coding the logic.
-
-Incidentally, it seems to fix a problem we had with negative X/Y
-positioning of YUV planes.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-3-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_plane.c | 103 ++++++++++++++++----------------
- 1 file changed, 52 insertions(+), 51 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -313,31 +313,59 @@ static int vc4_plane_setup_clipping_and_
-       u32 subpixel_src_mask = (1 << 16) - 1;
-       u32 format = fb->format->format;
-       int num_planes = fb->format->num_planes;
--      u32 h_subsample = 1;
--      u32 v_subsample = 1;
--      int ret;
--      int i;
-+      int min_scale = 1, max_scale = INT_MAX;
-+      struct drm_crtc_state *crtc_state;
-+      u32 h_subsample, v_subsample;
-+      int i, ret;
-+
-+      crtc_state = drm_atomic_get_existing_crtc_state(state->state,
-+                                                      state->crtc);
-+      if (!crtc_state) {
-+              DRM_DEBUG_KMS("Invalid crtc state\n");
-+              return -EINVAL;
-+      }
-+
-+      /* No configuring scaling on the cursor plane, since it gets
-+       * non-vblank-synced updates, and scaling requires LBM changes which
-+       * have to be vblank-synced.
-+       */
-+      if (plane->type == DRM_PLANE_TYPE_CURSOR) {
-+              min_scale = DRM_PLANE_HELPER_NO_SCALING;
-+              max_scale = DRM_PLANE_HELPER_NO_SCALING;
-+      } else {
-+              min_scale = 1;
-+              max_scale = INT_MAX;
-+      }
-+
-+      ret = drm_atomic_helper_check_plane_state(state, crtc_state,
-+                                                min_scale, max_scale,
-+                                                true, true);
-+      if (ret)
-+              return ret;
-+
-+      h_subsample = drm_format_horz_chroma_subsampling(format);
-+      v_subsample = drm_format_vert_chroma_subsampling(format);
-       for (i = 0; i < num_planes; i++)
-               vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
-       /* We don't support subpixel source positioning for scaling. */
--      if ((state->src_x & subpixel_src_mask) ||
--          (state->src_y & subpixel_src_mask) ||
--          (state->src_w & subpixel_src_mask) ||
--          (state->src_h & subpixel_src_mask)) {
-+      if ((state->src.x1 & subpixel_src_mask) ||
-+          (state->src.x2 & subpixel_src_mask) ||
-+          (state->src.y1 & subpixel_src_mask) ||
-+          (state->src.y2 & subpixel_src_mask)) {
-               return -EINVAL;
-       }
--      vc4_state->src_x = state->src_x >> 16;
--      vc4_state->src_y = state->src_y >> 16;
--      vc4_state->src_w[0] = state->src_w >> 16;
--      vc4_state->src_h[0] = state->src_h >> 16;
--
--      vc4_state->crtc_x = state->crtc_x;
--      vc4_state->crtc_y = state->crtc_y;
--      vc4_state->crtc_w = state->crtc_w;
--      vc4_state->crtc_h = state->crtc_h;
-+      vc4_state->src_x = state->src.x1 >> 16;
-+      vc4_state->src_y = state->src.y1 >> 16;
-+      vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16;
-+      vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16;
-+
-+      vc4_state->crtc_x = state->dst.x1;
-+      vc4_state->crtc_y = state->dst.y1;
-+      vc4_state->crtc_w = state->dst.x2 - state->dst.x1;
-+      vc4_state->crtc_h = state->dst.y2 - state->dst.y1;
-       ret = vc4_plane_margins_adj(state);
-       if (ret)
-@@ -354,8 +382,6 @@ static int vc4_plane_setup_clipping_and_
-       if (num_planes > 1) {
-               vc4_state->is_yuv = true;
--              h_subsample = drm_format_horz_chroma_subsampling(format);
--              v_subsample = drm_format_vert_chroma_subsampling(format);
-               vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample;
-               vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample;
-@@ -380,39 +406,14 @@ static int vc4_plane_setup_clipping_and_
-               vc4_state->y_scaling[1] = VC4_SCALING_NONE;
-       }
--      /* No configuring scaling on the cursor plane, since it gets
--         non-vblank-synced updates, and scaling requires requires
--         LBM changes which have to be vblank-synced.
--       */
--      if (plane->type == DRM_PLANE_TYPE_CURSOR && !vc4_state->is_unity)
--              return -EINVAL;
--
--      /* Clamp the on-screen start x/y to 0.  The hardware doesn't
--       * support negative y, and negative x wastes bandwidth.
--       */
--      if (vc4_state->crtc_x < 0) {
--              for (i = 0; i < num_planes; i++) {
--                      u32 cpp = fb->format->cpp[i];
--                      u32 subs = ((i == 0) ? 1 : h_subsample);
--
--                      vc4_state->offsets[i] += (cpp *
--                                                (-vc4_state->crtc_x) / subs);
--              }
--              vc4_state->src_w[0] += vc4_state->crtc_x;
--              vc4_state->src_w[1] += vc4_state->crtc_x / h_subsample;
--              vc4_state->crtc_x = 0;
--      }
--
--      if (vc4_state->crtc_y < 0) {
--              for (i = 0; i < num_planes; i++) {
--                      u32 subs = ((i == 0) ? 1 : v_subsample);
--
--                      vc4_state->offsets[i] += (fb->pitches[i] *
--                                                (-vc4_state->crtc_y) / subs);
--              }
--              vc4_state->src_h[0] += vc4_state->crtc_y;
--              vc4_state->src_h[1] += vc4_state->crtc_y / v_subsample;
--              vc4_state->crtc_y = 0;
-+      /* Adjust the base pointer to the first pixel to be scanned out. */
-+      for (i = 0; i < num_planes; i++) {
-+              vc4_state->offsets[i] += (vc4_state->src_y /
-+                                        (i ? v_subsample : 1)) *
-+                                       fb->pitches[i];
-+              vc4_state->offsets[i] += (vc4_state->src_x /
-+                                        (i ? h_subsample : 1)) *
-+                                       fb->format->cpp[i];
-       }
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0664-drm-vc4-Fix-NULL-pointer-dereference-in-the-async-up.patch b/target/linux/brcm2708/patches-4.19/950-0664-drm-vc4-Fix-NULL-pointer-dereference-in-the-async-up.patch
new file mode 100644 (file)
index 0000000..c9e7798
--- /dev/null
@@ -0,0 +1,57 @@
+From 0e81807e647c5e12fd897f3d520252ea60de3ff9 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 15 Nov 2018 11:58:51 +0100
+Subject: [PATCH] drm/vc4: Fix NULL pointer dereference in the async
+ update path
+
+vc4_plane_atomic_async_update() calls vc4_plane_atomic_check()
+which in turn calls vc4_plane_setup_clipping_and_scaling(), and since
+commit 58a6a36fe8e0 ("drm/vc4: Use
+drm_atomic_helper_check_plane_state() to simplify the logic"), this
+function accesses plane_state->state which will be NULL when called
+from the async update path because we're passing the current plane
+state, and plane_state->state has been assigned to NULL in
+drm_atomic_helper_swap_state().
+
+Pass the new state instead of the current one (the new state has
+->state set to a non-NULL value).
+
+Fixes: 58a6a36fe8e0 ("drm/vc4: Use drm_atomic_helper_check_plane_state() to simplify the logic")
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181115105852.9844-1-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -905,7 +905,7 @@ void vc4_plane_async_set_fb(struct drm_p
+ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
+                                         struct drm_plane_state *state)
+ {
+-      struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
++      struct vc4_plane_state *vc4_state, *new_vc4_state;
+       if (plane->state->fb != state->fb) {
+               vc4_plane_async_set_fb(plane, state->fb);
+@@ -927,7 +927,18 @@ static void vc4_plane_atomic_async_updat
+       plane->state->src_y = state->src_y;
+       /* Update the display list based on the new crtc_x/y. */
+-      vc4_plane_atomic_check(plane, plane->state);
++      vc4_plane_atomic_check(plane, state);
++
++      new_vc4_state = to_vc4_plane_state(state);
++      vc4_state = to_vc4_plane_state(plane->state);
++
++      /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */
++      vc4_state->dlist[vc4_state->pos0_offset] =
++              new_vc4_state->dlist[vc4_state->pos0_offset];
++      vc4_state->dlist[vc4_state->pos2_offset] =
++              new_vc4_state->dlist[vc4_state->pos2_offset];
++      vc4_state->dlist[vc4_state->ptr0_offset] =
++              new_vc4_state->dlist[vc4_state->ptr0_offset];
+       /* Note that we can't just call vc4_plane_write_dlist()
+        * because that would smash the context data that the HVS is
diff --git a/target/linux/brcm2708/patches-4.19/950-0664-drm-vc4-Move-offsets-adjustment-out-of-setup_clippin.patch b/target/linux/brcm2708/patches-4.19/950-0664-drm-vc4-Move-offsets-adjustment-out-of-setup_clippin.patch
deleted file mode 100644 (file)
index 9820c91..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From 58a92eae6ed463c294381e72eefec701d23fcdaf Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Fri, 3 Aug 2018 11:22:30 +0200
-Subject: [PATCH] adjustment out of
- setup_clipping_and_scaling()
-
-The offset adjustment depends on the framebuffer modified, so let's
-just move this operation in the DRM_FORMAT_MOD_LINEAR case inside
-vc4_plane_mode_set().
-
-This we'll be able to fix offset calculation for
-DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED and DRM_FORMAT_MOD_BROADCOM_SANDXXX.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-4-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_plane.c | 26 ++++++++++++++++----------
- 1 file changed, 16 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -406,16 +406,6 @@ static int vc4_plane_setup_clipping_and_
-               vc4_state->y_scaling[1] = VC4_SCALING_NONE;
-       }
--      /* Adjust the base pointer to the first pixel to be scanned out. */
--      for (i = 0; i < num_planes; i++) {
--              vc4_state->offsets[i] += (vc4_state->src_y /
--                                        (i ? v_subsample : 1)) *
--                                       fb->pitches[i];
--              vc4_state->offsets[i] += (vc4_state->src_x /
--                                        (i ? h_subsample : 1)) *
--                                       fb->format->cpp[i];
--      }
--
-       return 0;
- }
-@@ -523,6 +513,7 @@ static int vc4_plane_mode_set(struct drm
-       const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
-       u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
-       int num_planes = drm_format_num_planes(format->drm);
-+      u32 h_subsample, v_subsample;
-       bool mix_plane_alpha;
-       bool covers_screen;
-       u32 scl0, scl1, pitch0;
-@@ -568,10 +559,25 @@ static int vc4_plane_mode_set(struct drm
-               scl1 = vc4_get_scl_field(state, 0);
-       }
-+      h_subsample = drm_format_horz_chroma_subsampling(format->drm);
-+      v_subsample = drm_format_vert_chroma_subsampling(format->drm);
-+
-       switch (base_format_mod) {
-       case DRM_FORMAT_MOD_LINEAR:
-               tiling = SCALER_CTL0_TILING_LINEAR;
-               pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
-+
-+              /* Adjust the base pointer to the first pixel to be scanned
-+               * out.
-+               */
-+              for (i = 0; i < num_planes; i++) {
-+                      vc4_state->offsets[i] += vc4_state->src_y /
-+                                               (i ? v_subsample : 1) *
-+                                               fb->pitches[i];
-+                      vc4_state->offsets[i] += vc4_state->src_x /
-+                                               (i ? h_subsample : 1) *
-+                                               fb->format->cpp[i];
-+              }
-               break;
-       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
diff --git a/target/linux/brcm2708/patches-4.19/950-0665-ARM-dts-bcm2711-rpi-4-b-I2C-aliases-and-pulls.patch b/target/linux/brcm2708/patches-4.19/950-0665-ARM-dts-bcm2711-rpi-4-b-I2C-aliases-and-pulls.patch
new file mode 100644 (file)
index 0000000..daae20c
--- /dev/null
@@ -0,0 +1,67 @@
+From 188bd7c0085ac5b3d966aa899c6be644907157ea Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 12 Aug 2019 15:48:39 +0100
+Subject: [PATCH] ARM: dts: bcm2711-rpi-4-b: I2C aliases and pulls
+
+The I2C interface nodes need aliases to give them fixed bus numbers,
+and setting the pulls on the GPIOs (particularly 9-13) increases the
+chances of the bus working with weak or absent external pulls.
+
+See: https://www.raspberrypi.org/forums/posting.php?mode=reply&f=107&t=248439
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -23,6 +23,10 @@
+               mmc0 = &emmc2;
+               mmc1 = &mmcnr;
+               mmc2 = &sdhost;
++              i2c3 = &i2c3;
++              i2c4 = &i2c4;
++              i2c5 = &i2c5;
++              i2c6 = &i2c6;
+               /delete-property/ ethernet;
+               /delete-property/ intc;
+               ethernet0 = &genet;
+@@ -207,31 +211,37 @@
+       i2c0_pins: i2c0 {
+               brcm,pins = <0 1>;
+               brcm,function = <BCM2835_FSEL_ALT0>;
++              brcm,pull = <BCM2835_PUD_UP>;
+       };
+       i2c1_pins: i2c1 {
+               brcm,pins = <2 3>;
+               brcm,function = <BCM2835_FSEL_ALT0>;
++              brcm,pull = <BCM2835_PUD_UP>;
+       };
+       i2c3_pins: i2c3 {
+               brcm,pins = <4 5>;
+               brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
+       };
+       i2c4_pins: i2c4 {
+               brcm,pins = <8 9>;
+               brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
+       };
+       i2c5_pins: i2c5 {
+               brcm,pins = <12 13>;
+               brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
+       };
+       i2c6_pins: i2c6 {
+               brcm,pins = <22 23>;
+               brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
+       };
+       i2s_pins: i2s {
diff --git a/target/linux/brcm2708/patches-4.19/950-0665-drm-vc4-Fix-X-Y-positioning-of-planes-using-T_TILES-.patch b/target/linux/brcm2708/patches-4.19/950-0665-drm-vc4-Fix-X-Y-positioning-of-planes-using-T_TILES-.patch
deleted file mode 100644 (file)
index 6197d90..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-From 010e3665babdf589e26e2fb098ac1f39e519c0f6 Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Fri, 3 Aug 2018 11:22:31 +0200
-Subject: [PATCH] drm/vc4: Fix X/Y positioning of planes using T_TILES
- modifier
-
-X/Y positioning of T-format buffers is quite tricky and the current
-implementation was failing to position a plane using this format
-correctly when the CRTC X, Y or both X and Y offsets were negative.
-It was also failing when the SRC X/Y offsets were != 0.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-5-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_plane.c | 50 ++++++++++++++++++++++++++++-----
- 1 file changed, 43 insertions(+), 7 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -578,22 +578,58 @@ static int vc4_plane_mode_set(struct drm
-                                                (i ? h_subsample : 1) *
-                                                fb->format->cpp[i];
-               }
-+
-               break;
-       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
--              /* For T-tiled, the FB pitch is "how many bytes from
--               * one row to the next, such that pitch * tile_h ==
--               * tile_size * tiles_per_row."
--               */
-               u32 tile_size_shift = 12; /* T tiles are 4kb */
-+              /* Whole-tile offsets, mostly for setting the pitch. */
-+              u32 tile_w_shift = fb->format->cpp[0] == 2 ? 6 : 5;
-               u32 tile_h_shift = 5; /* 16 and 32bpp are 32 pixels high */
-+              u32 tile_w_mask = (1 << tile_w_shift) - 1;
-+              /* The height mask on 32-bit-per-pixel tiles is 63, i.e. twice
-+               * the height (in pixels) of a 4k tile.
-+               */
-+              u32 tile_h_mask = (2 << tile_h_shift) - 1;
-+              /* For T-tiled, the FB pitch is "how many bytes from one row to
-+               * the next, such that
-+               *
-+               *      pitch * tile_h == tile_size * tiles_per_row
-+               */
-               u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
-+              u32 tiles_l = vc4_state->src_x >> tile_w_shift;
-+              u32 tiles_r = tiles_w - tiles_l;
-+              u32 tiles_t = vc4_state->src_y >> tile_h_shift;
-+              /* Intra-tile offsets, which modify the base address (the
-+               * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
-+               * base address).
-+               */
-+              u32 tile_y = (vc4_state->src_y >> 4) & 1;
-+              u32 subtile_y = (vc4_state->src_y >> 2) & 3;
-+              u32 utile_y = vc4_state->src_y & 3;
-+              u32 x_off = vc4_state->src_x & tile_w_mask;
-+              u32 y_off = vc4_state->src_y & tile_h_mask;
-               tiling = SCALER_CTL0_TILING_256B_OR_T;
-+              pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
-+                        VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
-+                        VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
-+                        VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
-+              vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift);
-+              vc4_state->offsets[0] += subtile_y << 8;
-+              vc4_state->offsets[0] += utile_y << 4;
-+
-+              /* Rows of tiles alternate left-to-right and right-to-left. */
-+              if (tiles_t & 1) {
-+                      pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
-+                      vc4_state->offsets[0] += (tiles_w - tiles_l) <<
-+                                               tile_size_shift;
-+                      vc4_state->offsets[0] -= (1 + !tile_y) << 10;
-+              } else {
-+                      vc4_state->offsets[0] += tiles_l << tile_size_shift;
-+                      vc4_state->offsets[0] += tile_y << 10;
-+              }
--              pitch0 = (VC4_SET_FIELD(0, SCALER_PITCH0_TILE_Y_OFFSET) |
--                        VC4_SET_FIELD(0, SCALER_PITCH0_TILE_WIDTH_L) |
--                        VC4_SET_FIELD(tiles_w, SCALER_PITCH0_TILE_WIDTH_R));
-               break;
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0666-drm-vc4-Fix-NULL-pointer-dereference-in-the-async-up.patch b/target/linux/brcm2708/patches-4.19/950-0666-drm-vc4-Fix-NULL-pointer-dereference-in-the-async-up.patch
deleted file mode 100644 (file)
index c9e7798..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From 0e81807e647c5e12fd897f3d520252ea60de3ff9 Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Thu, 15 Nov 2018 11:58:51 +0100
-Subject: [PATCH] drm/vc4: Fix NULL pointer dereference in the async
- update path
-
-vc4_plane_atomic_async_update() calls vc4_plane_atomic_check()
-which in turn calls vc4_plane_setup_clipping_and_scaling(), and since
-commit 58a6a36fe8e0 ("drm/vc4: Use
-drm_atomic_helper_check_plane_state() to simplify the logic"), this
-function accesses plane_state->state which will be NULL when called
-from the async update path because we're passing the current plane
-state, and plane_state->state has been assigned to NULL in
-drm_atomic_helper_swap_state().
-
-Pass the new state instead of the current one (the new state has
-->state set to a non-NULL value).
-
-Fixes: 58a6a36fe8e0 ("drm/vc4: Use drm_atomic_helper_check_plane_state() to simplify the logic")
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181115105852.9844-1-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_plane.c | 15 +++++++++++++--
- 1 file changed, 13 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -905,7 +905,7 @@ void vc4_plane_async_set_fb(struct drm_p
- static void vc4_plane_atomic_async_update(struct drm_plane *plane,
-                                         struct drm_plane_state *state)
- {
--      struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
-+      struct vc4_plane_state *vc4_state, *new_vc4_state;
-       if (plane->state->fb != state->fb) {
-               vc4_plane_async_set_fb(plane, state->fb);
-@@ -927,7 +927,18 @@ static void vc4_plane_atomic_async_updat
-       plane->state->src_y = state->src_y;
-       /* Update the display list based on the new crtc_x/y. */
--      vc4_plane_atomic_check(plane, plane->state);
-+      vc4_plane_atomic_check(plane, state);
-+
-+      new_vc4_state = to_vc4_plane_state(state);
-+      vc4_state = to_vc4_plane_state(plane->state);
-+
-+      /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */
-+      vc4_state->dlist[vc4_state->pos0_offset] =
-+              new_vc4_state->dlist[vc4_state->pos0_offset];
-+      vc4_state->dlist[vc4_state->pos2_offset] =
-+              new_vc4_state->dlist[vc4_state->pos2_offset];
-+      vc4_state->dlist[vc4_state->ptr0_offset] =
-+              new_vc4_state->dlist[vc4_state->ptr0_offset];
-       /* Note that we can't just call vc4_plane_write_dlist()
-        * because that would smash the context data that the HVS is
diff --git a/target/linux/brcm2708/patches-4.19/950-0666-xhci-Use-more-event-ring-segment-table-entries.patch b/target/linux/brcm2708/patches-4.19/950-0666-xhci-Use-more-event-ring-segment-table-entries.patch
new file mode 100644 (file)
index 0000000..0949f97
--- /dev/null
@@ -0,0 +1,60 @@
+From c2e02902a3b75b24306dac06cb6f75b683fa0267 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 13 Aug 2019 15:53:29 +0100
+Subject: [PATCH] xhci: Use more event ring segment table entries
+
+Users have reported log spam created by "Event Ring Full" xHC event
+TRBs. These are caused by interrupt latency in conjunction with a very
+busy set of devices on the bus. The errors are benign, but throughput
+will suffer as the xHC will pause processing of transfers until the
+event ring is drained by the kernel. Expand the number of event TRB slots
+available by increasing the number of event ring segments in the ERST.
+
+Controllers have a hardware-defined limit as to the number of ERST
+entries they can process, so make the actual number in use
+min(ERST_MAX_SEGS, hw_max).
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/xhci-mem.c | 8 +++++---
+ drivers/usb/host/xhci.h     | 4 ++--
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -2495,9 +2495,11 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+        * Event ring setup: Allocate a normal ring, but also setup
+        * the event ring segment table (ERST).  Section 4.9.3.
+        */
++      val2 = 1 << HCS_ERST_MAX(xhci->hcs_params2);
++      val2 = min_t(unsigned int, ERST_MAX_SEGS, val2);
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Allocating event ring");
+-      xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT,
+-                                      0, flags);
++      xhci->event_ring = xhci_ring_alloc(xhci, val2, 1, TYPE_EVENT,
++                                         0, flags);
+       if (!xhci->event_ring)
+               goto fail;
+       if (xhci_check_trb_in_td_math(xhci) < 0)
+@@ -2510,7 +2512,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+       /* set ERST count with the number of entries in the segment table */
+       val = readl(&xhci->ir_set->erst_size);
+       val &= ERST_SIZE_MASK;
+-      val |= ERST_NUM_SEGS;
++      val |= val2;
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+                       "// Write ERST size = %i to ir_set 0 (some bits preserved)",
+                       val);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1643,8 +1643,8 @@ struct urb_priv {
+  * Each segment table entry is 4*32bits long.  1K seems like an ok size:
+  * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
+  * meaning 64 ring segments.
+- * Initial allocated size of the ERST, in number of entries */
+-#define       ERST_NUM_SEGS   1
++ * Maximum number of segments in the ERST */
++#define       ERST_MAX_SEGS   8
+ /* Initial allocated size of the ERST, in number of entries */
+ #define       ERST_SIZE       64
+ /* Initial number of event segment rings allocated */
diff --git a/target/linux/brcm2708/patches-4.19/950-0667-ARM-dts-bcm2711-rpi-4-b-I2C-aliases-and-pulls.patch b/target/linux/brcm2708/patches-4.19/950-0667-ARM-dts-bcm2711-rpi-4-b-I2C-aliases-and-pulls.patch
deleted file mode 100644 (file)
index daae20c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From 188bd7c0085ac5b3d966aa899c6be644907157ea Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 12 Aug 2019 15:48:39 +0100
-Subject: [PATCH] ARM: dts: bcm2711-rpi-4-b: I2C aliases and pulls
-
-The I2C interface nodes need aliases to give them fixed bus numbers,
-and setting the pulls on the GPIOs (particularly 9-13) increases the
-chances of the bus working with weak or absent external pulls.
-
-See: https://www.raspberrypi.org/forums/posting.php?mode=reply&f=107&t=248439
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -23,6 +23,10 @@
-               mmc0 = &emmc2;
-               mmc1 = &mmcnr;
-               mmc2 = &sdhost;
-+              i2c3 = &i2c3;
-+              i2c4 = &i2c4;
-+              i2c5 = &i2c5;
-+              i2c6 = &i2c6;
-               /delete-property/ ethernet;
-               /delete-property/ intc;
-               ethernet0 = &genet;
-@@ -207,31 +211,37 @@
-       i2c0_pins: i2c0 {
-               brcm,pins = <0 1>;
-               brcm,function = <BCM2835_FSEL_ALT0>;
-+              brcm,pull = <BCM2835_PUD_UP>;
-       };
-       i2c1_pins: i2c1 {
-               brcm,pins = <2 3>;
-               brcm,function = <BCM2835_FSEL_ALT0>;
-+              brcm,pull = <BCM2835_PUD_UP>;
-       };
-       i2c3_pins: i2c3 {
-               brcm,pins = <4 5>;
-               brcm,function = <BCM2835_FSEL_ALT5>;
-+              brcm,pull = <BCM2835_PUD_UP>;
-       };
-       i2c4_pins: i2c4 {
-               brcm,pins = <8 9>;
-               brcm,function = <BCM2835_FSEL_ALT5>;
-+              brcm,pull = <BCM2835_PUD_UP>;
-       };
-       i2c5_pins: i2c5 {
-               brcm,pins = <12 13>;
-               brcm,function = <BCM2835_FSEL_ALT5>;
-+              brcm,pull = <BCM2835_PUD_UP>;
-       };
-       i2c6_pins: i2c6 {
-               brcm,pins = <22 23>;
-               brcm,function = <BCM2835_FSEL_ALT5>;
-+              brcm,pull = <BCM2835_PUD_UP>;
-       };
-       i2s_pins: i2s {
diff --git a/target/linux/brcm2708/patches-4.19/950-0667-dwc_otg-use-align_buf-for-small-IN-control-transfers.patch b/target/linux/brcm2708/patches-4.19/950-0667-dwc_otg-use-align_buf-for-small-IN-control-transfers.patch
new file mode 100644 (file)
index 0000000..fbfef01
--- /dev/null
@@ -0,0 +1,59 @@
+From 0c6190fa3cfeafd773b51b751a473d6775c23309 Mon Sep 17 00:00:00 2001
+From: P33M <2474547+P33M@users.noreply.github.com>
+Date: Wed, 14 Aug 2019 14:35:50 +0100
+Subject: [PATCH] dwc_otg: use align_buf for small IN control transfers
+ (#3150)
+
+The hardware will do a 4-byte write to memory on any IN packet received
+that is between 1 and 3 bytes long. This tramples memory in the uvcvideo
+driver, as it uses a sequence of 1- and 2-byte control transfers to
+query the min/max/range/step of each individual camera control and
+gives us buffers that are offsets into a struct.
+
+Catch small control transfers in the data phase and use the align_buf
+to bounce the correct number of bytes into the URB's buffer.
+
+In general, short packets on non-control endpoints should be OK as URBs
+should have enough buffer space for a wMaxPacket size transfer.
+
+See: https://github.com/raspberrypi/linux/issues/3148
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -1182,6 +1182,7 @@ static void assign_and_init_hc(dwc_otg_h
+       dwc_otg_qtd_t *qtd;
+       dwc_otg_hcd_urb_t *urb;
+       void* ptr = NULL;
++      uint16_t wLength;
+       uint32_t intr_enable;
+       unsigned long flags;
+       gintmsk_data_t gintmsk = { .d32 = 0, };
+@@ -1293,6 +1294,23 @@ static void assign_and_init_hc(dwc_otg_h
+                       break;
+               case DWC_OTG_CONTROL_DATA:
+                       DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
++                      /*
++                       * Hardware bug: small IN packets with length < 4
++                       * cause a 4-byte write to memory. We can only catch
++                       * the case where we know a short packet is going to be
++                       * returned in a control transfer, as the length is
++                       * specified in the setup packet. This is only an issue
++                       * for drivers that insist on packing a device's various
++                       * properties into a struct and querying them one at a
++                       * time (uvcvideo).
++                       * Force the use of align_buf so that the subsequent
++                       * memcpy puts the right number of bytes in the URB's
++                       * buffer.
++                       */
++                      wLength = ((uint16_t *)urb->setup_packet)[3];
++                      if (hc->ep_is_in && wLength < 4)
++                              ptr = hc->xfer_buff;
++
+                       hc->data_pid_start = qtd->data_toggle;
+                       break;
+               case DWC_OTG_CONTROL_STATUS:
diff --git a/target/linux/brcm2708/patches-4.19/950-0668-Ported-pcie-brcmstb-bounce-buffer-implementation-to-.patch b/target/linux/brcm2708/patches-4.19/950-0668-Ported-pcie-brcmstb-bounce-buffer-implementation-to-.patch
new file mode 100644 (file)
index 0000000..c69a8ca
--- /dev/null
@@ -0,0 +1,818 @@
+From ccd23ce562e8223ba7c6acf7dcb7058ff89ff7ec Mon Sep 17 00:00:00 2001
+From: yaroslavros <yaroslavros@gmail.com>
+Date: Wed, 14 Aug 2019 15:22:55 +0100
+Subject: [PATCH] Ported pcie-brcmstb bounce buffer implementation to
+ ARM64. (#3144)
+
+Ported pcie-brcmstb bounce buffer implementation to ARM64.
+This enables full 4G RAM usage on Raspberry Pi in 64-bit mode.
+
+Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
+---
+ arch/arm64/include/asm/dma-mapping.h          |  21 +
+ arch/arm64/mm/dma-mapping.c                   |  50 ++
+ drivers/pci/controller/Makefile               |   3 +
+ drivers/pci/controller/pcie-brcmstb-bounce.h  |   2 +-
+ .../pci/controller/pcie-brcmstb-bounce64.c    | 576 ++++++++++++++++++
+ drivers/pci/controller/pcie-brcmstb.c         |  30 +-
+ 6 files changed, 658 insertions(+), 24 deletions(-)
+ create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce64.c
+
+--- a/arch/arm64/include/asm/dma-mapping.h
++++ b/arch/arm64/include/asm/dma-mapping.h
+@@ -24,6 +24,27 @@
+ #include <xen/xen.h>
+ #include <asm/xen/hypervisor.h>
++extern void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
++                         gfp_t gfp, unsigned long attrs);
++extern void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
++                       dma_addr_t handle, unsigned long attrs);
++extern int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
++                      void *cpu_addr, dma_addr_t dma_addr, size_t size,
++                      unsigned long attrs);
++extern int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
++              void *cpu_addr, dma_addr_t dma_addr, size_t size,
++              unsigned long attrs);
++extern int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
++              enum dma_data_direction dir, unsigned long attrs);
++extern void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int,
++              enum dma_data_direction dir, unsigned long attrs);
++extern void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
++              enum dma_data_direction dir);
++extern void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
++              enum dma_data_direction dir);
++
++
++
+ extern const struct dma_map_ops dummy_dma_ops;
+ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
+--- a/arch/arm64/mm/dma-mapping.c
++++ b/arch/arm64/mm/dma-mapping.c
+@@ -138,6 +138,12 @@ no_mem:
+       return NULL;
+ }
++void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
++                           gfp_t gfp, unsigned long attrs)
++{
++        return __dma_alloc(dev, size, handle, gfp, attrs);
++}
++
+ static void __dma_free(struct device *dev, size_t size,
+                      void *vaddr, dma_addr_t dma_handle,
+                      unsigned long attrs)
+@@ -154,6 +160,12 @@ static void __dma_free(struct device *de
+       swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs);
+ }
++void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
++                         dma_addr_t handle, unsigned long attrs)
++{
++        __dma_free(dev, size, cpu_addr, handle, attrs);
++}
++
+ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
+                                    unsigned long offset, size_t size,
+                                    enum dma_data_direction dir,
+@@ -197,6 +209,12 @@ static int __swiotlb_map_sg_attrs(struct
+       return ret;
+ }
++int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
++                enum dma_data_direction dir, unsigned long attrs)
++{
++      return __swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
++}
++
+ static void __swiotlb_unmap_sg_attrs(struct device *dev,
+                                    struct scatterlist *sgl, int nelems,
+                                    enum dma_data_direction dir,
+@@ -213,6 +231,12 @@ static void __swiotlb_unmap_sg_attrs(str
+       swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
+ }
++void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int nelems,
++                enum dma_data_direction dir, unsigned long attrs)
++{
++      __swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
++}
++
+ static void __swiotlb_sync_single_for_cpu(struct device *dev,
+                                         dma_addr_t dev_addr, size_t size,
+                                         enum dma_data_direction dir)
+@@ -245,6 +269,12 @@ static void __swiotlb_sync_sg_for_cpu(st
+       swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
+ }
++void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
++                enum dma_data_direction dir)
++{
++      __swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
++}
++
+ static void __swiotlb_sync_sg_for_device(struct device *dev,
+                                        struct scatterlist *sgl, int nelems,
+                                        enum dma_data_direction dir)
+@@ -259,6 +289,12 @@ static void __swiotlb_sync_sg_for_device
+                                      sg->length, dir);
+ }
++void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
++                enum dma_data_direction dir)
++{
++      __swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
++}
++
+ static int __swiotlb_mmap_pfn(struct vm_area_struct *vma,
+                             unsigned long pfn, size_t size)
+ {
+@@ -294,6 +330,13 @@ static int __swiotlb_mmap(struct device
+       return __swiotlb_mmap_pfn(vma, pfn, size);
+ }
++int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
++                        void *cpu_addr, dma_addr_t dma_addr, size_t size,
++                        unsigned long attrs)
++{
++      return __swiotlb_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
++}
++
+ static int __swiotlb_get_sgtable_page(struct sg_table *sgt,
+                                     struct page *page, size_t size)
+ {
+@@ -314,6 +357,13 @@ static int __swiotlb_get_sgtable(struct
+       return __swiotlb_get_sgtable_page(sgt, page, size);
+ }
++int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
++                void *cpu_addr, dma_addr_t dma_addr, size_t size,
++                unsigned long attrs)
++{
++      return __swiotlb_get_sgtable(dev, sgt, cpu_addr, dma_addr, size, attrs);
++}
++
+ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
+ {
+       if (swiotlb)
+--- a/drivers/pci/controller/Makefile
++++ b/drivers/pci/controller/Makefile
+@@ -32,6 +32,9 @@ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcms
+ ifdef CONFIG_ARM
+ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
+ endif
++ifdef CONFIG_ARM64
++obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce64.o
++endif
+ obj-$(CONFIG_VMD) += vmd.o
+ # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+--- a/drivers/pci/controller/pcie-brcmstb-bounce.h
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
+@@ -6,7 +6,7 @@
+ #ifndef _PCIE_BRCMSTB_BOUNCE_H
+ #define _PCIE_BRCMSTB_BOUNCE_H
+-#ifdef CONFIG_ARM
++#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
+                         dma_addr_t threshold);
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb-bounce64.c
+@@ -0,0 +1,576 @@
++/*
++ *  This code started out as a version of arch/arm/common/dmabounce.c,
++ *  modified to cope with highmem pages. Now it has been changed heavily -
++ *  it now preallocates a large block (currently 4MB) and carves it up
++ *  sequentially in ring fashion, and DMA is used to copy the data - to the
++ *  point where very little of the original remains.
++ *
++ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
++ *
++ *  Original version by Brad Parker (brad@heeltoe.com)
++ *  Re-written by Christopher Hoover <ch@murgatroid.com>
++ *  Made generic by Deepak Saxena <dsaxena@plexity.net>
++ *
++ *  Copyright (C) 2002 Hewlett Packard Company.
++ *  Copyright (C) 2004 MontaVista Software, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or
++ *  modify it under the terms of the GNU General Public License
++ *  version 2 as published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/page-flags.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/dma-direct.h>
++#include <linux/dmapool.h>
++#include <linux/list.h>
++#include <linux/scatterlist.h>
++#include <linux/bitmap.h>
++#include <linux/swiotlb.h>
++
++#include <asm/cacheflush.h>
++
++#define STATS
++
++#ifdef STATS
++#define DO_STATS(X) do { X ; } while (0)
++#else
++#define DO_STATS(X) do { } while (0)
++#endif
++
++/* ************************************************** */
++
++struct safe_buffer {
++      struct list_head node;
++
++      /* original request */
++      size_t          size;
++      int             direction;
++
++      struct dmabounce_pool *pool;
++      void            *safe;
++      dma_addr_t      unsafe_dma_addr;
++      dma_addr_t      safe_dma_addr;
++};
++
++struct dmabounce_pool {
++      unsigned long   pages;
++      void            *virt_addr;
++      dma_addr_t      dma_addr;
++      unsigned long   *alloc_map;
++      unsigned long   alloc_pos;
++      spinlock_t      lock;
++      struct device   *dev;
++      unsigned long   num_pages;
++#ifdef STATS
++      size_t          max_size;
++      unsigned long   num_bufs;
++      unsigned long   max_bufs;
++      unsigned long   max_pages;
++#endif
++};
++
++struct dmabounce_device_info {
++      struct device *dev;
++      dma_addr_t threshold;
++      struct list_head safe_buffers;
++      struct dmabounce_pool pool;
++      rwlock_t lock;
++#ifdef STATS
++      unsigned long map_count;
++      unsigned long unmap_count;
++      unsigned long sync_dev_count;
++      unsigned long sync_cpu_count;
++      unsigned long fail_count;
++      int attr_res;
++#endif
++};
++
++static struct dmabounce_device_info *g_dmabounce_device_info;
++
++extern int bcm2838_dma40_memcpy_init(void);
++extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
++
++#ifdef STATS
++static ssize_t
++bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++      return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
++              device_info->map_count,
++              device_info->unmap_count,
++              device_info->sync_dev_count,
++              device_info->sync_cpu_count,
++              device_info->fail_count,
++              device_info->pool.max_size,
++              device_info->pool.num_bufs,
++              device_info->pool.max_bufs,
++              device_info->pool.num_pages * PAGE_SIZE,
++              device_info->pool.max_pages * PAGE_SIZE);
++}
++
++static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
++#endif
++
++static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
++                       unsigned long buffer_size)
++{
++      int ret = -ENOMEM;
++      pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
++      pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
++      if (!pool->alloc_map)
++              goto err_bitmap;
++      pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
++                                           &pool->dma_addr, GFP_KERNEL);
++      if (!pool->virt_addr)
++              goto err_dmabuf;
++
++      pool->alloc_pos = 0;
++      spin_lock_init(&pool->lock);
++      pool->dev = dev;
++      pool->num_pages = 0;
++
++      DO_STATS(pool->max_size = 0);
++      DO_STATS(pool->num_bufs = 0);
++      DO_STATS(pool->max_bufs = 0);
++      DO_STATS(pool->max_pages = 0);
++
++      return  0;
++
++err_dmabuf:
++      bitmap_free(pool->alloc_map);
++err_bitmap:
++      return ret;
++}
++
++static void bounce_destroy(struct dmabounce_pool *pool)
++{
++      dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
++                        pool->dma_addr);
++
++      bitmap_free(pool->alloc_map);
++}
++
++static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
++                        dma_addr_t *dmaaddrp)
++{
++      unsigned long pages;
++      unsigned long flags;
++      unsigned long pos;
++
++      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
++
++      DO_STATS(pool->max_size = max(size, pool->max_size));
++
++      spin_lock_irqsave(&pool->lock, flags);
++      pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
++                                       pool->alloc_pos, pages, 0);
++      /* If not found, try from the start */
++      if (pos >= pool->pages && pool->alloc_pos)
++              pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
++                                               0, pages, 0);
++
++      if (pos >= pool->pages) {
++              spin_unlock_irqrestore(&pool->lock, flags);
++              return NULL;
++      }
++
++      bitmap_set(pool->alloc_map, pos, pages);
++      pool->alloc_pos = (pos + pages) % pool->pages;
++      pool->num_pages += pages;
++
++      DO_STATS(pool->num_bufs++);
++      DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
++      DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
++
++      spin_unlock_irqrestore(&pool->lock, flags);
++
++      *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
++
++      return pool->virt_addr + pos * PAGE_SIZE;
++}
++
++static void
++bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
++{
++      unsigned long pages;
++      unsigned long flags;
++      unsigned long pos;
++
++      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
++      pos = (buf - pool->virt_addr)/PAGE_SIZE;
++
++      BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
++
++      spin_lock_irqsave(&pool->lock, flags);
++      bitmap_clear(pool->alloc_map, pos, pages);
++      pool->num_pages -= pages;
++      if (pool->num_pages == 0)
++              pool->alloc_pos = 0;
++      DO_STATS(pool->num_bufs--);
++      spin_unlock_irqrestore(&pool->lock, flags);
++}
++
++/* allocate a 'safe' buffer and keep track of it */
++static struct safe_buffer *
++alloc_safe_buffer(struct dmabounce_device_info *device_info,
++                dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
++{
++      struct safe_buffer *buf;
++      struct dmabounce_pool *pool = &device_info->pool;
++      struct device *dev = device_info->dev;
++      unsigned long flags;
++
++      /*
++       * Although one might expect this to be called in thread context,
++       * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
++       * was previously used to select the appropriate allocation mode,
++       * but this is unsafe.
++       */
++      buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
++      if (!buf) {
++              dev_warn(dev, "%s: kmalloc failed\n", __func__);
++              return NULL;
++      }
++
++      buf->unsafe_dma_addr = dma_addr;
++      buf->size = size;
++      buf->direction = dir;
++      buf->pool = pool;
++
++      buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
++
++      if (!buf->safe) {
++              dev_warn(dev,
++                       "%s: could not alloc dma memory (size=%d)\n",
++                       __func__, size);
++              kfree(buf);
++              return NULL;
++      }
++
++      write_lock_irqsave(&device_info->lock, flags);
++      list_add(&buf->node, &device_info->safe_buffers);
++      write_unlock_irqrestore(&device_info->lock, flags);
++
++      return buf;
++}
++
++/* determine if a buffer is from our "safe" pool */
++static struct safe_buffer *
++find_safe_buffer(struct dmabounce_device_info *device_info,
++               dma_addr_t safe_dma_addr)
++{
++      struct safe_buffer *b, *rb = NULL;
++      unsigned long flags;
++
++      read_lock_irqsave(&device_info->lock, flags);
++
++      list_for_each_entry(b, &device_info->safe_buffers, node)
++              if (b->safe_dma_addr <= safe_dma_addr &&
++                  b->safe_dma_addr + b->size > safe_dma_addr) {
++                      rb = b;
++                      break;
++              }
++
++      read_unlock_irqrestore(&device_info->lock, flags);
++      return rb;
++}
++
++static void
++free_safe_buffer(struct dmabounce_device_info *device_info,
++               struct safe_buffer *buf)
++{
++      unsigned long flags;
++
++      write_lock_irqsave(&device_info->lock, flags);
++      list_del(&buf->node);
++      write_unlock_irqrestore(&device_info->lock, flags);
++
++      bounce_free(buf->pool, buf->safe, buf->size);
++
++      kfree(buf);
++}
++
++/* ************************************************** */
++
++static struct safe_buffer *
++find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
++{
++      if (!dev || !g_dmabounce_device_info)
++              return NULL;
++      if (dma_mapping_error(dev, dma_addr)) {
++              dev_err(dev, "Trying to %s invalid mapping\n", where);
++              return NULL;
++      }
++      return find_safe_buffer(g_dmabounce_device_info, dma_addr);
++}
++
++static dma_addr_t
++map_single(struct device *dev, struct safe_buffer *buf, size_t size,
++         enum dma_data_direction dir, unsigned long attrs)
++{
++      BUG_ON(buf->size != size);
++      BUG_ON(buf->direction != dir);
++
++      dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
++              (u64)buf->safe_dma_addr);
++
++      if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
++          !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
++              bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
++                                   size);
++
++      return buf->safe_dma_addr;
++}
++
++static dma_addr_t
++unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
++           enum dma_data_direction dir, unsigned long attrs)
++{
++      BUG_ON(buf->size != size);
++      BUG_ON(buf->direction != dir);
++
++      if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
++          !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
++              dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
++                      (u64)buf->unsafe_dma_addr);
++
++              bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
++                                   size);
++      }
++      return buf->unsafe_dma_addr;
++}
++
++/* ************************************************** */
++
++/*
++ * see if a buffer address is in an 'unsafe' range.  if it is
++ * allocate a 'safe' buffer and copy the unsafe buffer into it.
++ * substitute the safe buffer for the unsafe one.
++ * (basically move the buffer from an unsafe area to a safe one)
++ */
++static dma_addr_t
++dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
++                 size_t size, enum dma_data_direction dir,
++                 unsigned long attrs)
++{
++      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++      dma_addr_t dma_addr;
++
++      dma_addr = phys_to_dma(dev, page_to_phys(page)) + offset;
++
++      swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
++        if (!is_device_dma_coherent(dev))
++              __dma_map_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
++
++      if (device_info && (dma_addr + size) > device_info->threshold) {
++              struct safe_buffer *buf;
++
++              buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
++              if (!buf) {
++                      DO_STATS(device_info->fail_count++);
++                      return (~(dma_addr_t)0x0);
++              }
++
++              DO_STATS(device_info->map_count++);
++
++              dma_addr = map_single(dev, buf, size, dir, attrs);
++      }
++      return dma_addr;
++}
++
++/*
++ * see if a mapped address was really a "safe" buffer and if so, copy
++ * the data from the safe buffer back to the unsafe buffer and free up
++ * the safe buffer.  (basically return things back to the way they
++ * should be)
++ */
++static void
++dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
++                   enum dma_data_direction dir, unsigned long attrs)
++{
++      struct safe_buffer *buf;
++
++      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++      if (buf) {
++              DO_STATS(g_dmabounce_device_info->unmap_count++);
++              dma_addr = unmap_single(dev, buf, size, dir, attrs);
++              free_safe_buffer(g_dmabounce_device_info, buf);
++      }
++
++        if (!is_device_dma_coherent(dev))
++              __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
++      swiotlb_sync_single_for_cpu(dev, dma_addr, size, dir);
++}
++
++/*
++ * A version of dmabounce_map_page that assumes the mapping has already
++ * been created - intended for streaming operation.
++ */
++static void
++dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
++                        enum dma_data_direction dir)
++{
++      struct safe_buffer *buf;
++
++        swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
++        if (!is_device_dma_coherent(dev))
++                __dma_map_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
++
++      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++      if (buf) {
++              DO_STATS(g_dmabounce_device_info->sync_dev_count++);
++              map_single(dev, buf, size, dir, 0);
++      }
++}
++
++/*
++ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
++ * intended for streaming operation.
++ */
++static void
++dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
++                     size_t size, enum dma_data_direction dir)
++{
++      struct safe_buffer *buf;
++
++      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++      if (buf) {
++              DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
++              dma_addr = unmap_single(dev, buf, size, dir, 0);
++      }
++
++        if (!is_device_dma_coherent(dev))
++                __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
++        swiotlb_sync_single_for_cpu(dev, dma_addr, size, dir);
++}
++
++static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
++{
++      if (g_dmabounce_device_info)
++              return 0;
++
++      return swiotlb_dma_supported(dev, dma_mask);
++}
++
++static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++      return swiotlb_dma_mapping_error(dev, dma_addr);
++}
++
++static const struct dma_map_ops dmabounce_ops = {
++      .alloc                  = arm64_dma_alloc,
++      .free                   = arm64_dma_free,
++      .mmap                   = arm64_dma_mmap,
++      .get_sgtable            = arm64_dma_get_sgtable,
++      .map_page               = dmabounce_map_page,
++      .unmap_page             = dmabounce_unmap_page,
++      .sync_single_for_cpu    = dmabounce_sync_for_cpu,
++      .sync_single_for_device = dmabounce_sync_for_device,
++      .map_sg                 = arm64_dma_map_sg,
++      .unmap_sg               = arm64_dma_unmap_sg,
++      .sync_sg_for_cpu        = arm64_dma_sync_sg_for_cpu,
++      .sync_sg_for_device     = arm64_dma_sync_sg_for_device,
++      .dma_supported          = dmabounce_dma_supported,
++      .mapping_error          = dmabounce_mapping_error,
++};
++
++int brcm_pcie_bounce_init(struct device *dev,
++                        unsigned long buffer_size,
++                        dma_addr_t threshold)
++{
++      struct dmabounce_device_info *device_info;
++      int ret;
++
++      /* Only support a single client */
++      if (g_dmabounce_device_info)
++              return -EBUSY;
++
++      ret = bcm2838_dma40_memcpy_init();
++      if (ret)
++              return ret;
++
++      device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
++      if (!device_info) {
++              dev_err(dev,
++                      "Could not allocated dmabounce_device_info\n");
++              return -ENOMEM;
++      }
++
++      ret = bounce_create(&device_info->pool, dev, buffer_size);
++      if (ret) {
++              dev_err(dev,
++                      "dmabounce: could not allocate %ld byte DMA pool\n",
++                      buffer_size);
++              goto err_bounce;
++      }
++
++      device_info->dev = dev;
++      device_info->threshold = threshold;
++      INIT_LIST_HEAD(&device_info->safe_buffers);
++      rwlock_init(&device_info->lock);
++
++      DO_STATS(device_info->map_count = 0);
++      DO_STATS(device_info->unmap_count = 0);
++      DO_STATS(device_info->sync_dev_count = 0);
++      DO_STATS(device_info->sync_cpu_count = 0);
++      DO_STATS(device_info->fail_count = 0);
++      DO_STATS(device_info->attr_res =
++               device_create_file(dev, &dev_attr_dmabounce_stats));
++
++      g_dmabounce_device_info = device_info;
++
++      dev_err(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
++               buffer_size / 1024, &threshold);
++
++      return 0;
++
++ err_bounce:
++      kfree(device_info);
++      return ret;
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_init);
++
++void brcm_pcie_bounce_uninit(struct device *dev)
++{
++      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++
++      g_dmabounce_device_info = NULL;
++
++      if (!device_info) {
++              dev_warn(dev,
++                       "Never registered with dmabounce but attempting"
++                       "to unregister!\n");
++              return;
++      }
++
++      if (!list_empty(&device_info->safe_buffers)) {
++              dev_err(dev,
++                      "Removing from dmabounce with pending buffers!\n");
++              BUG();
++      }
++
++      bounce_destroy(&device_info->pool);
++
++      DO_STATS(if (device_info->attr_res == 0)
++                       device_remove_file(dev, &dev_attr_dmabounce_stats));
++
++      kfree(device_info);
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
++
++int brcm_pcie_bounce_register_dev(struct device *dev)
++{
++      set_dma_ops(dev, &dmabounce_ops);
++
++      return 0;
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
++
++MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
++MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
++MODULE_LICENSE("GPL");
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -617,28 +617,6 @@ static const struct dma_map_ops brcm_dma
+ static void brcm_set_dma_ops(struct device *dev)
+ {
+-      int ret;
+-
+-      if (IS_ENABLED(CONFIG_ARM64)) {
+-              /*
+-               * We are going to invoke get_dma_ops().  That
+-               * function, at this point in time, invokes
+-               * get_arch_dma_ops(), and for ARM64 that function
+-               * returns a pointer to dummy_dma_ops.  So then we'd
+-               * like to call arch_setup_dma_ops(), but that isn't
+-               * exported.  Instead, we call of_dma_configure(),
+-               * which is exported, and this calls
+-               * arch_setup_dma_ops().  Once we do this the call to
+-               * get_dma_ops() will work properly because
+-               * dev->dma_ops will be set.
+-               */
+-              ret = of_dma_configure(dev, dev->of_node, true);
+-              if (ret) {
+-                      dev_err(dev, "of_dma_configure() failed: %d\n", ret);
+-                      return;
+-              }
+-      }
+-
+       arch_dma_ops = get_dma_ops(dev);
+       if (!arch_dma_ops) {
+               dev_err(dev, "failed to get arch_dma_ops\n");
+@@ -657,12 +635,12 @@ static int brcmstb_platform_notifier(str
+       extern unsigned long max_pfn;
+       struct device *dev = __dev;
+       const char *rc_name = "0000:00:00.0";
++      int ret;
+       switch (event) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
+                   strcmp(dev->kobj.name, rc_name)) {
+-                      int ret;
+                       ret = brcm_pcie_bounce_register_dev(dev);
+                       if (ret) {
+@@ -671,6 +649,12 @@ static int brcmstb_platform_notifier(str
+                                       ret);
+                               return ret;
+                       }
++              } else if (IS_ENABLED(CONFIG_ARM64)) {
++                      ret = of_dma_configure(dev, dev->of_node, true);
++                      if (ret) {
++                              dev_err(dev, "of_dma_configure() failed: %d\n", ret);
++                              return;
++                      }
+               }
+               brcm_set_dma_ops(dev);
+               return NOTIFY_OK;
diff --git a/target/linux/brcm2708/patches-4.19/950-0668-xhci-Use-more-event-ring-segment-table-entries.patch b/target/linux/brcm2708/patches-4.19/950-0668-xhci-Use-more-event-ring-segment-table-entries.patch
deleted file mode 100644 (file)
index 0949f97..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From c2e02902a3b75b24306dac06cb6f75b683fa0267 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 13 Aug 2019 15:53:29 +0100
-Subject: [PATCH] xhci: Use more event ring segment table entries
-
-Users have reported log spam created by "Event Ring Full" xHC event
-TRBs. These are caused by interrupt latency in conjunction with a very
-busy set of devices on the bus. The errors are benign, but throughput
-will suffer as the xHC will pause processing of transfers until the
-event ring is drained by the kernel. Expand the number of event TRB slots
-available by increasing the number of event ring segments in the ERST.
-
-Controllers have a hardware-defined limit as to the number of ERST
-entries they can process, so make the actual number in use
-min(ERST_MAX_SEGS, hw_max).
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/host/xhci-mem.c | 8 +++++---
- drivers/usb/host/xhci.h     | 4 ++--
- 2 files changed, 7 insertions(+), 5 deletions(-)
-
---- a/drivers/usb/host/xhci-mem.c
-+++ b/drivers/usb/host/xhci-mem.c
-@@ -2495,9 +2495,11 @@ int xhci_mem_init(struct xhci_hcd *xhci,
-        * Event ring setup: Allocate a normal ring, but also setup
-        * the event ring segment table (ERST).  Section 4.9.3.
-        */
-+      val2 = 1 << HCS_ERST_MAX(xhci->hcs_params2);
-+      val2 = min_t(unsigned int, ERST_MAX_SEGS, val2);
-       xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Allocating event ring");
--      xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT,
--                                      0, flags);
-+      xhci->event_ring = xhci_ring_alloc(xhci, val2, 1, TYPE_EVENT,
-+                                         0, flags);
-       if (!xhci->event_ring)
-               goto fail;
-       if (xhci_check_trb_in_td_math(xhci) < 0)
-@@ -2510,7 +2512,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
-       /* set ERST count with the number of entries in the segment table */
-       val = readl(&xhci->ir_set->erst_size);
-       val &= ERST_SIZE_MASK;
--      val |= ERST_NUM_SEGS;
-+      val |= val2;
-       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-                       "// Write ERST size = %i to ir_set 0 (some bits preserved)",
-                       val);
---- a/drivers/usb/host/xhci.h
-+++ b/drivers/usb/host/xhci.h
-@@ -1643,8 +1643,8 @@ struct urb_priv {
-  * Each segment table entry is 4*32bits long.  1K seems like an ok size:
-  * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
-  * meaning 64 ring segments.
-- * Initial allocated size of the ERST, in number of entries */
--#define       ERST_NUM_SEGS   1
-+ * Maximum number of segments in the ERST */
-+#define       ERST_MAX_SEGS   8
- /* Initial allocated size of the ERST, in number of entries */
- #define       ERST_SIZE       64
- /* Initial number of event segment rings allocated */
diff --git a/target/linux/brcm2708/patches-4.19/950-0669-configs-arm64-vcm2711-Enable-V3D.patch b/target/linux/brcm2708/patches-4.19/950-0669-configs-arm64-vcm2711-Enable-V3D.patch
new file mode 100644 (file)
index 0000000..e09e57b
--- /dev/null
@@ -0,0 +1,27 @@
+From 709962264bec8f8483df374da5e946c982348e87 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 15 Aug 2019 12:02:34 +0100
+Subject: [PATCH] configs: arm64/vcm2711: Enable V3D
+
+Enable the V3D driver, which depends on BCM2835_POWER.
+
+Originally submitted by GitHub user 'phire' in a slightly different
+form.
+
+See: https://github.com/raspberrypi/linux/pull/3063
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/gpu/drm/v3d/Kconfig          | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/Kconfig
++++ b/drivers/gpu/drm/v3d/Kconfig
+@@ -1,6 +1,6 @@
+ config DRM_V3D
+       tristate "Broadcom V3D 3.x and newer"
+-      depends on ARCH_BCM || ARCH_BCMSTB || COMPILE_TEST
++      depends on ARCH_BCM || ARCH_BCMSTB || ARCH_BCM2835 || COMPILE_TEST
+       depends on DRM
+       depends on COMMON_CLK
+       depends on MMU
diff --git a/target/linux/brcm2708/patches-4.19/950-0669-dwc_otg-use-align_buf-for-small-IN-control-transfers.patch b/target/linux/brcm2708/patches-4.19/950-0669-dwc_otg-use-align_buf-for-small-IN-control-transfers.patch
deleted file mode 100644 (file)
index fbfef01..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 0c6190fa3cfeafd773b51b751a473d6775c23309 Mon Sep 17 00:00:00 2001
-From: P33M <2474547+P33M@users.noreply.github.com>
-Date: Wed, 14 Aug 2019 14:35:50 +0100
-Subject: [PATCH] dwc_otg: use align_buf for small IN control transfers
- (#3150)
-
-The hardware will do a 4-byte write to memory on any IN packet received
-that is between 1 and 3 bytes long. This tramples memory in the uvcvideo
-driver, as it uses a sequence of 1- and 2-byte control transfers to
-query the min/max/range/step of each individual camera control and
-gives us buffers that are offsets into a struct.
-
-Catch small control transfers in the data phase and use the align_buf
-to bounce the correct number of bytes into the URB's buffer.
-
-In general, short packets on non-control endpoints should be OK as URBs
-should have enough buffer space for a wMaxPacket size transfer.
-
-See: https://github.com/raspberrypi/linux/issues/3148
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 18 ++++++++++++++++++
- 1 file changed, 18 insertions(+)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -1182,6 +1182,7 @@ static void assign_and_init_hc(dwc_otg_h
-       dwc_otg_qtd_t *qtd;
-       dwc_otg_hcd_urb_t *urb;
-       void* ptr = NULL;
-+      uint16_t wLength;
-       uint32_t intr_enable;
-       unsigned long flags;
-       gintmsk_data_t gintmsk = { .d32 = 0, };
-@@ -1293,6 +1294,23 @@ static void assign_and_init_hc(dwc_otg_h
-                       break;
-               case DWC_OTG_CONTROL_DATA:
-                       DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
-+                      /*
-+                       * Hardware bug: small IN packets with length < 4
-+                       * cause a 4-byte write to memory. We can only catch
-+                       * the case where we know a short packet is going to be
-+                       * returned in a control transfer, as the length is
-+                       * specified in the setup packet. This is only an issue
-+                       * for drivers that insist on packing a device's various
-+                       * properties into a struct and querying them one at a
-+                       * time (uvcvideo).
-+                       * Force the use of align_buf so that the subsequent
-+                       * memcpy puts the right number of bytes in the URB's
-+                       * buffer.
-+                       */
-+                      wLength = ((uint16_t *)urb->setup_packet)[3];
-+                      if (hc->ep_is_in && wLength < 4)
-+                              ptr = hc->xfer_buff;
-+
-                       hc->data_pid_start = qtd->data_toggle;
-                       break;
-               case DWC_OTG_CONTROL_STATUS:
diff --git a/target/linux/brcm2708/patches-4.19/950-0670-Ported-pcie-brcmstb-bounce-buffer-implementation-to-.patch b/target/linux/brcm2708/patches-4.19/950-0670-Ported-pcie-brcmstb-bounce-buffer-implementation-to-.patch
deleted file mode 100644 (file)
index c69a8ca..0000000
+++ /dev/null
@@ -1,818 +0,0 @@
-From ccd23ce562e8223ba7c6acf7dcb7058ff89ff7ec Mon Sep 17 00:00:00 2001
-From: yaroslavros <yaroslavros@gmail.com>
-Date: Wed, 14 Aug 2019 15:22:55 +0100
-Subject: [PATCH] Ported pcie-brcmstb bounce buffer implementation to
- ARM64. (#3144)
-
-Ported pcie-brcmstb bounce buffer implementation to ARM64.
-This enables full 4G RAM usage on Raspberry Pi in 64-bit mode.
-
-Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
----
- arch/arm64/include/asm/dma-mapping.h          |  21 +
- arch/arm64/mm/dma-mapping.c                   |  50 ++
- drivers/pci/controller/Makefile               |   3 +
- drivers/pci/controller/pcie-brcmstb-bounce.h  |   2 +-
- .../pci/controller/pcie-brcmstb-bounce64.c    | 576 ++++++++++++++++++
- drivers/pci/controller/pcie-brcmstb.c         |  30 +-
- 6 files changed, 658 insertions(+), 24 deletions(-)
- create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce64.c
-
---- a/arch/arm64/include/asm/dma-mapping.h
-+++ b/arch/arm64/include/asm/dma-mapping.h
-@@ -24,6 +24,27 @@
- #include <xen/xen.h>
- #include <asm/xen/hypervisor.h>
-+extern void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-+                         gfp_t gfp, unsigned long attrs);
-+extern void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
-+                       dma_addr_t handle, unsigned long attrs);
-+extern int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
-+                      void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+                      unsigned long attrs);
-+extern int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
-+              void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+              unsigned long attrs);
-+extern int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
-+              enum dma_data_direction dir, unsigned long attrs);
-+extern void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int,
-+              enum dma_data_direction dir, unsigned long attrs);
-+extern void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
-+              enum dma_data_direction dir);
-+extern void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
-+              enum dma_data_direction dir);
-+
-+
-+
- extern const struct dma_map_ops dummy_dma_ops;
- static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
---- a/arch/arm64/mm/dma-mapping.c
-+++ b/arch/arm64/mm/dma-mapping.c
-@@ -138,6 +138,12 @@ no_mem:
-       return NULL;
- }
-+void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-+                           gfp_t gfp, unsigned long attrs)
-+{
-+        return __dma_alloc(dev, size, handle, gfp, attrs);
-+}
-+
- static void __dma_free(struct device *dev, size_t size,
-                      void *vaddr, dma_addr_t dma_handle,
-                      unsigned long attrs)
-@@ -154,6 +160,12 @@ static void __dma_free(struct device *de
-       swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs);
- }
-+void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
-+                         dma_addr_t handle, unsigned long attrs)
-+{
-+        __dma_free(dev, size, cpu_addr, handle, attrs);
-+}
-+
- static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
-                                    unsigned long offset, size_t size,
-                                    enum dma_data_direction dir,
-@@ -197,6 +209,12 @@ static int __swiotlb_map_sg_attrs(struct
-       return ret;
- }
-+int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
-+                enum dma_data_direction dir, unsigned long attrs)
-+{
-+      return __swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
-+}
-+
- static void __swiotlb_unmap_sg_attrs(struct device *dev,
-                                    struct scatterlist *sgl, int nelems,
-                                    enum dma_data_direction dir,
-@@ -213,6 +231,12 @@ static void __swiotlb_unmap_sg_attrs(str
-       swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
- }
-+void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int nelems,
-+                enum dma_data_direction dir, unsigned long attrs)
-+{
-+      __swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
-+}
-+
- static void __swiotlb_sync_single_for_cpu(struct device *dev,
-                                         dma_addr_t dev_addr, size_t size,
-                                         enum dma_data_direction dir)
-@@ -245,6 +269,12 @@ static void __swiotlb_sync_sg_for_cpu(st
-       swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
- }
-+void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
-+                enum dma_data_direction dir)
-+{
-+      __swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
-+}
-+
- static void __swiotlb_sync_sg_for_device(struct device *dev,
-                                        struct scatterlist *sgl, int nelems,
-                                        enum dma_data_direction dir)
-@@ -259,6 +289,12 @@ static void __swiotlb_sync_sg_for_device
-                                      sg->length, dir);
- }
-+void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
-+                enum dma_data_direction dir)
-+{
-+      __swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
-+}
-+
- static int __swiotlb_mmap_pfn(struct vm_area_struct *vma,
-                             unsigned long pfn, size_t size)
- {
-@@ -294,6 +330,13 @@ static int __swiotlb_mmap(struct device
-       return __swiotlb_mmap_pfn(vma, pfn, size);
- }
-+int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
-+                        void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+                        unsigned long attrs)
-+{
-+      return __swiotlb_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
-+}
-+
- static int __swiotlb_get_sgtable_page(struct sg_table *sgt,
-                                     struct page *page, size_t size)
- {
-@@ -314,6 +357,13 @@ static int __swiotlb_get_sgtable(struct
-       return __swiotlb_get_sgtable_page(sgt, page, size);
- }
-+int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
-+                void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+                unsigned long attrs)
-+{
-+      return __swiotlb_get_sgtable(dev, sgt, cpu_addr, dma_addr, size, attrs);
-+}
-+
- static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
- {
-       if (swiotlb)
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -32,6 +32,9 @@ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcms
- ifdef CONFIG_ARM
- obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
- endif
-+ifdef CONFIG_ARM64
-+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce64.o
-+endif
- obj-$(CONFIG_VMD) += vmd.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
---- a/drivers/pci/controller/pcie-brcmstb-bounce.h
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
-@@ -6,7 +6,7 @@
- #ifndef _PCIE_BRCMSTB_BOUNCE_H
- #define _PCIE_BRCMSTB_BOUNCE_H
--#ifdef CONFIG_ARM
-+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
- int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
-                         dma_addr_t threshold);
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce64.c
-@@ -0,0 +1,576 @@
-+/*
-+ *  This code started out as a version of arch/arm/common/dmabounce.c,
-+ *  modified to cope with highmem pages. Now it has been changed heavily -
-+ *  it now preallocates a large block (currently 4MB) and carves it up
-+ *  sequentially in ring fashion, and DMA is used to copy the data - to the
-+ *  point where very little of the original remains.
-+ *
-+ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
-+ *
-+ *  Original version by Brad Parker (brad@heeltoe.com)
-+ *  Re-written by Christopher Hoover <ch@murgatroid.com>
-+ *  Made generic by Deepak Saxena <dsaxena@plexity.net>
-+ *
-+ *  Copyright (C) 2002 Hewlett Packard Company.
-+ *  Copyright (C) 2004 MontaVista Software, Inc.
-+ *
-+ *  This program is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU General Public License
-+ *  version 2 as published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/page-flags.h>
-+#include <linux/device.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/dma-direct.h>
-+#include <linux/dmapool.h>
-+#include <linux/list.h>
-+#include <linux/scatterlist.h>
-+#include <linux/bitmap.h>
-+#include <linux/swiotlb.h>
-+
-+#include <asm/cacheflush.h>
-+
-+#define STATS
-+
-+#ifdef STATS
-+#define DO_STATS(X) do { X ; } while (0)
-+#else
-+#define DO_STATS(X) do { } while (0)
-+#endif
-+
-+/* ************************************************** */
-+
-+struct safe_buffer {
-+      struct list_head node;
-+
-+      /* original request */
-+      size_t          size;
-+      int             direction;
-+
-+      struct dmabounce_pool *pool;
-+      void            *safe;
-+      dma_addr_t      unsafe_dma_addr;
-+      dma_addr_t      safe_dma_addr;
-+};
-+
-+struct dmabounce_pool {
-+      unsigned long   pages;
-+      void            *virt_addr;
-+      dma_addr_t      dma_addr;
-+      unsigned long   *alloc_map;
-+      unsigned long   alloc_pos;
-+      spinlock_t      lock;
-+      struct device   *dev;
-+      unsigned long   num_pages;
-+#ifdef STATS
-+      size_t          max_size;
-+      unsigned long   num_bufs;
-+      unsigned long   max_bufs;
-+      unsigned long   max_pages;
-+#endif
-+};
-+
-+struct dmabounce_device_info {
-+      struct device *dev;
-+      dma_addr_t threshold;
-+      struct list_head safe_buffers;
-+      struct dmabounce_pool pool;
-+      rwlock_t lock;
-+#ifdef STATS
-+      unsigned long map_count;
-+      unsigned long unmap_count;
-+      unsigned long sync_dev_count;
-+      unsigned long sync_cpu_count;
-+      unsigned long fail_count;
-+      int attr_res;
-+#endif
-+};
-+
-+static struct dmabounce_device_info *g_dmabounce_device_info;
-+
-+extern int bcm2838_dma40_memcpy_init(void);
-+extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
-+
-+#ifdef STATS
-+static ssize_t
-+bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+      return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
-+              device_info->map_count,
-+              device_info->unmap_count,
-+              device_info->sync_dev_count,
-+              device_info->sync_cpu_count,
-+              device_info->fail_count,
-+              device_info->pool.max_size,
-+              device_info->pool.num_bufs,
-+              device_info->pool.max_bufs,
-+              device_info->pool.num_pages * PAGE_SIZE,
-+              device_info->pool.max_pages * PAGE_SIZE);
-+}
-+
-+static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
-+#endif
-+
-+static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
-+                       unsigned long buffer_size)
-+{
-+      int ret = -ENOMEM;
-+      pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
-+      pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
-+      if (!pool->alloc_map)
-+              goto err_bitmap;
-+      pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
-+                                           &pool->dma_addr, GFP_KERNEL);
-+      if (!pool->virt_addr)
-+              goto err_dmabuf;
-+
-+      pool->alloc_pos = 0;
-+      spin_lock_init(&pool->lock);
-+      pool->dev = dev;
-+      pool->num_pages = 0;
-+
-+      DO_STATS(pool->max_size = 0);
-+      DO_STATS(pool->num_bufs = 0);
-+      DO_STATS(pool->max_bufs = 0);
-+      DO_STATS(pool->max_pages = 0);
-+
-+      return  0;
-+
-+err_dmabuf:
-+      bitmap_free(pool->alloc_map);
-+err_bitmap:
-+      return ret;
-+}
-+
-+static void bounce_destroy(struct dmabounce_pool *pool)
-+{
-+      dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
-+                        pool->dma_addr);
-+
-+      bitmap_free(pool->alloc_map);
-+}
-+
-+static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
-+                        dma_addr_t *dmaaddrp)
-+{
-+      unsigned long pages;
-+      unsigned long flags;
-+      unsigned long pos;
-+
-+      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+
-+      DO_STATS(pool->max_size = max(size, pool->max_size));
-+
-+      spin_lock_irqsave(&pool->lock, flags);
-+      pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+                                       pool->alloc_pos, pages, 0);
-+      /* If not found, try from the start */
-+      if (pos >= pool->pages && pool->alloc_pos)
-+              pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+                                               0, pages, 0);
-+
-+      if (pos >= pool->pages) {
-+              spin_unlock_irqrestore(&pool->lock, flags);
-+              return NULL;
-+      }
-+
-+      bitmap_set(pool->alloc_map, pos, pages);
-+      pool->alloc_pos = (pos + pages) % pool->pages;
-+      pool->num_pages += pages;
-+
-+      DO_STATS(pool->num_bufs++);
-+      DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
-+      DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
-+
-+      spin_unlock_irqrestore(&pool->lock, flags);
-+
-+      *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
-+
-+      return pool->virt_addr + pos * PAGE_SIZE;
-+}
-+
-+static void
-+bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
-+{
-+      unsigned long pages;
-+      unsigned long flags;
-+      unsigned long pos;
-+
-+      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+      pos = (buf - pool->virt_addr)/PAGE_SIZE;
-+
-+      BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
-+
-+      spin_lock_irqsave(&pool->lock, flags);
-+      bitmap_clear(pool->alloc_map, pos, pages);
-+      pool->num_pages -= pages;
-+      if (pool->num_pages == 0)
-+              pool->alloc_pos = 0;
-+      DO_STATS(pool->num_bufs--);
-+      spin_unlock_irqrestore(&pool->lock, flags);
-+}
-+
-+/* allocate a 'safe' buffer and keep track of it */
-+static struct safe_buffer *
-+alloc_safe_buffer(struct dmabounce_device_info *device_info,
-+                dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+      struct dmabounce_pool *pool = &device_info->pool;
-+      struct device *dev = device_info->dev;
-+      unsigned long flags;
-+
-+      /*
-+       * Although one might expect this to be called in thread context,
-+       * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
-+       * was previously used to select the appropriate allocation mode,
-+       * but this is unsafe.
-+       */
-+      buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
-+      if (!buf) {
-+              dev_warn(dev, "%s: kmalloc failed\n", __func__);
-+              return NULL;
-+      }
-+
-+      buf->unsafe_dma_addr = dma_addr;
-+      buf->size = size;
-+      buf->direction = dir;
-+      buf->pool = pool;
-+
-+      buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
-+
-+      if (!buf->safe) {
-+              dev_warn(dev,
-+                       "%s: could not alloc dma memory (size=%d)\n",
-+                       __func__, size);
-+              kfree(buf);
-+              return NULL;
-+      }
-+
-+      write_lock_irqsave(&device_info->lock, flags);
-+      list_add(&buf->node, &device_info->safe_buffers);
-+      write_unlock_irqrestore(&device_info->lock, flags);
-+
-+      return buf;
-+}
-+
-+/* determine if a buffer is from our "safe" pool */
-+static struct safe_buffer *
-+find_safe_buffer(struct dmabounce_device_info *device_info,
-+               dma_addr_t safe_dma_addr)
-+{
-+      struct safe_buffer *b, *rb = NULL;
-+      unsigned long flags;
-+
-+      read_lock_irqsave(&device_info->lock, flags);
-+
-+      list_for_each_entry(b, &device_info->safe_buffers, node)
-+              if (b->safe_dma_addr <= safe_dma_addr &&
-+                  b->safe_dma_addr + b->size > safe_dma_addr) {
-+                      rb = b;
-+                      break;
-+              }
-+
-+      read_unlock_irqrestore(&device_info->lock, flags);
-+      return rb;
-+}
-+
-+static void
-+free_safe_buffer(struct dmabounce_device_info *device_info,
-+               struct safe_buffer *buf)
-+{
-+      unsigned long flags;
-+
-+      write_lock_irqsave(&device_info->lock, flags);
-+      list_del(&buf->node);
-+      write_unlock_irqrestore(&device_info->lock, flags);
-+
-+      bounce_free(buf->pool, buf->safe, buf->size);
-+
-+      kfree(buf);
-+}
-+
-+/* ************************************************** */
-+
-+static struct safe_buffer *
-+find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
-+{
-+      if (!dev || !g_dmabounce_device_info)
-+              return NULL;
-+      if (dma_mapping_error(dev, dma_addr)) {
-+              dev_err(dev, "Trying to %s invalid mapping\n", where);
-+              return NULL;
-+      }
-+      return find_safe_buffer(g_dmabounce_device_info, dma_addr);
-+}
-+
-+static dma_addr_t
-+map_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+         enum dma_data_direction dir, unsigned long attrs)
-+{
-+      BUG_ON(buf->size != size);
-+      BUG_ON(buf->direction != dir);
-+
-+      dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
-+              (u64)buf->safe_dma_addr);
-+
-+      if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+          !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-+              bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
-+                                   size);
-+
-+      return buf->safe_dma_addr;
-+}
-+
-+static dma_addr_t
-+unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+           enum dma_data_direction dir, unsigned long attrs)
-+{
-+      BUG_ON(buf->size != size);
-+      BUG_ON(buf->direction != dir);
-+
-+      if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+          !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
-+              dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
-+                      (u64)buf->unsafe_dma_addr);
-+
-+              bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
-+                                   size);
-+      }
-+      return buf->unsafe_dma_addr;
-+}
-+
-+/* ************************************************** */
-+
-+/*
-+ * see if a buffer address is in an 'unsafe' range.  if it is
-+ * allocate a 'safe' buffer and copy the unsafe buffer into it.
-+ * substitute the safe buffer for the unsafe one.
-+ * (basically move the buffer from an unsafe area to a safe one)
-+ */
-+static dma_addr_t
-+dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
-+                 size_t size, enum dma_data_direction dir,
-+                 unsigned long attrs)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+      dma_addr_t dma_addr;
-+
-+      dma_addr = phys_to_dma(dev, page_to_phys(page)) + offset;
-+
-+      swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
-+        if (!is_device_dma_coherent(dev))
-+              __dma_map_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
-+
-+      if (device_info && (dma_addr + size) > device_info->threshold) {
-+              struct safe_buffer *buf;
-+
-+              buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
-+              if (!buf) {
-+                      DO_STATS(device_info->fail_count++);
-+                      return (~(dma_addr_t)0x0);
-+              }
-+
-+              DO_STATS(device_info->map_count++);
-+
-+              dma_addr = map_single(dev, buf, size, dir, attrs);
-+      }
-+      return dma_addr;
-+}
-+
-+/*
-+ * see if a mapped address was really a "safe" buffer and if so, copy
-+ * the data from the safe buffer back to the unsafe buffer and free up
-+ * the safe buffer.  (basically return things back to the way they
-+ * should be)
-+ */
-+static void
-+dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-+                   enum dma_data_direction dir, unsigned long attrs)
-+{
-+      struct safe_buffer *buf;
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->unmap_count++);
-+              dma_addr = unmap_single(dev, buf, size, dir, attrs);
-+              free_safe_buffer(g_dmabounce_device_info, buf);
-+      }
-+
-+        if (!is_device_dma_coherent(dev))
-+              __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
-+      swiotlb_sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+/*
-+ * A version of dmabounce_map_page that assumes the mapping has already
-+ * been created - intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
-+                        enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+
-+        swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
-+        if (!is_device_dma_coherent(dev))
-+                __dma_map_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->sync_dev_count++);
-+              map_single(dev, buf, size, dir, 0);
-+      }
-+}
-+
-+/*
-+ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
-+ * intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
-+                     size_t size, enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
-+              dma_addr = unmap_single(dev, buf, size, dir, 0);
-+      }
-+
-+        if (!is_device_dma_coherent(dev))
-+                __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
-+        swiotlb_sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
-+{
-+      if (g_dmabounce_device_info)
-+              return 0;
-+
-+      return swiotlb_dma_supported(dev, dma_mask);
-+}
-+
-+static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
-+{
-+      return swiotlb_dma_mapping_error(dev, dma_addr);
-+}
-+
-+static const struct dma_map_ops dmabounce_ops = {
-+      .alloc                  = arm64_dma_alloc,
-+      .free                   = arm64_dma_free,
-+      .mmap                   = arm64_dma_mmap,
-+      .get_sgtable            = arm64_dma_get_sgtable,
-+      .map_page               = dmabounce_map_page,
-+      .unmap_page             = dmabounce_unmap_page,
-+      .sync_single_for_cpu    = dmabounce_sync_for_cpu,
-+      .sync_single_for_device = dmabounce_sync_for_device,
-+      .map_sg                 = arm64_dma_map_sg,
-+      .unmap_sg               = arm64_dma_unmap_sg,
-+      .sync_sg_for_cpu        = arm64_dma_sync_sg_for_cpu,
-+      .sync_sg_for_device     = arm64_dma_sync_sg_for_device,
-+      .dma_supported          = dmabounce_dma_supported,
-+      .mapping_error          = dmabounce_mapping_error,
-+};
-+
-+int brcm_pcie_bounce_init(struct device *dev,
-+                        unsigned long buffer_size,
-+                        dma_addr_t threshold)
-+{
-+      struct dmabounce_device_info *device_info;
-+      int ret;
-+
-+      /* Only support a single client */
-+      if (g_dmabounce_device_info)
-+              return -EBUSY;
-+
-+      ret = bcm2838_dma40_memcpy_init();
-+      if (ret)
-+              return ret;
-+
-+      device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
-+      if (!device_info) {
-+              dev_err(dev,
-+                      "Could not allocated dmabounce_device_info\n");
-+              return -ENOMEM;
-+      }
-+
-+      ret = bounce_create(&device_info->pool, dev, buffer_size);
-+      if (ret) {
-+              dev_err(dev,
-+                      "dmabounce: could not allocate %ld byte DMA pool\n",
-+                      buffer_size);
-+              goto err_bounce;
-+      }
-+
-+      device_info->dev = dev;
-+      device_info->threshold = threshold;
-+      INIT_LIST_HEAD(&device_info->safe_buffers);
-+      rwlock_init(&device_info->lock);
-+
-+      DO_STATS(device_info->map_count = 0);
-+      DO_STATS(device_info->unmap_count = 0);
-+      DO_STATS(device_info->sync_dev_count = 0);
-+      DO_STATS(device_info->sync_cpu_count = 0);
-+      DO_STATS(device_info->fail_count = 0);
-+      DO_STATS(device_info->attr_res =
-+               device_create_file(dev, &dev_attr_dmabounce_stats));
-+
-+      g_dmabounce_device_info = device_info;
-+
-+      dev_err(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
-+               buffer_size / 1024, &threshold);
-+
-+      return 0;
-+
-+ err_bounce:
-+      kfree(device_info);
-+      return ret;
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_init);
-+
-+void brcm_pcie_bounce_uninit(struct device *dev)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+
-+      g_dmabounce_device_info = NULL;
-+
-+      if (!device_info) {
-+              dev_warn(dev,
-+                       "Never registered with dmabounce but attempting"
-+                       "to unregister!\n");
-+              return;
-+      }
-+
-+      if (!list_empty(&device_info->safe_buffers)) {
-+              dev_err(dev,
-+                      "Removing from dmabounce with pending buffers!\n");
-+              BUG();
-+      }
-+
-+      bounce_destroy(&device_info->pool);
-+
-+      DO_STATS(if (device_info->attr_res == 0)
-+                       device_remove_file(dev, &dev_attr_dmabounce_stats));
-+
-+      kfree(device_info);
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev)
-+{
-+      set_dma_ops(dev, &dmabounce_ops);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
-+
-+MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
-+MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
-+MODULE_LICENSE("GPL");
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -617,28 +617,6 @@ static const struct dma_map_ops brcm_dma
- static void brcm_set_dma_ops(struct device *dev)
- {
--      int ret;
--
--      if (IS_ENABLED(CONFIG_ARM64)) {
--              /*
--               * We are going to invoke get_dma_ops().  That
--               * function, at this point in time, invokes
--               * get_arch_dma_ops(), and for ARM64 that function
--               * returns a pointer to dummy_dma_ops.  So then we'd
--               * like to call arch_setup_dma_ops(), but that isn't
--               * exported.  Instead, we call of_dma_configure(),
--               * which is exported, and this calls
--               * arch_setup_dma_ops().  Once we do this the call to
--               * get_dma_ops() will work properly because
--               * dev->dma_ops will be set.
--               */
--              ret = of_dma_configure(dev, dev->of_node, true);
--              if (ret) {
--                      dev_err(dev, "of_dma_configure() failed: %d\n", ret);
--                      return;
--              }
--      }
--
-       arch_dma_ops = get_dma_ops(dev);
-       if (!arch_dma_ops) {
-               dev_err(dev, "failed to get arch_dma_ops\n");
-@@ -657,12 +635,12 @@ static int brcmstb_platform_notifier(str
-       extern unsigned long max_pfn;
-       struct device *dev = __dev;
-       const char *rc_name = "0000:00:00.0";
-+      int ret;
-       switch (event) {
-       case BUS_NOTIFY_ADD_DEVICE:
-               if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
-                   strcmp(dev->kobj.name, rc_name)) {
--                      int ret;
-                       ret = brcm_pcie_bounce_register_dev(dev);
-                       if (ret) {
-@@ -671,6 +649,12 @@ static int brcmstb_platform_notifier(str
-                                       ret);
-                               return ret;
-                       }
-+              } else if (IS_ENABLED(CONFIG_ARM64)) {
-+                      ret = of_dma_configure(dev, dev->of_node, true);
-+                      if (ret) {
-+                              dev_err(dev, "of_dma_configure() failed: %d\n", ret);
-+                              return;
-+                      }
-               }
-               brcm_set_dma_ops(dev);
-               return NOTIFY_OK;
diff --git a/target/linux/brcm2708/patches-4.19/950-0670-overlays-sc16ic752-i2c-Fix-xtal-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0670-overlays-sc16ic752-i2c-Fix-xtal-parameter.patch
new file mode 100644 (file)
index 0000000..d148696
--- /dev/null
@@ -0,0 +1,24 @@
+From ee24998ecaed3d03890a7a5e04dddb8c5d073e97 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sat, 17 Aug 2019 19:47:30 +0100
+Subject: [PATCH] overlays: sc16ic752-i2c: Fix xtal parameter
+
+The xtal parameter is targetting the wrong node - fix it.
+
+See: https://github.com/raspberrypi/linux/issues/3156
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
+@@ -35,6 +35,6 @@
+       __overrides__ {
+               int_pin = <&sc16is752>,"interrupts:0";
+               addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name";
+-              xtal = <&sc16is752>,"clock-frequency:0";
++              xtal = <&sc16is752_clk>,"clock-frequency:0";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0671-configs-arm64-vcm2711-Enable-V3D.patch b/target/linux/brcm2708/patches-4.19/950-0671-configs-arm64-vcm2711-Enable-V3D.patch
deleted file mode 100644 (file)
index e09e57b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 709962264bec8f8483df374da5e946c982348e87 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 15 Aug 2019 12:02:34 +0100
-Subject: [PATCH] configs: arm64/vcm2711: Enable V3D
-
-Enable the V3D driver, which depends on BCM2835_POWER.
-
-Originally submitted by GitHub user 'phire' in a slightly different
-form.
-
-See: https://github.com/raspberrypi/linux/pull/3063
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/gpu/drm/v3d/Kconfig          | 2 +-
- 2 files changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/Kconfig
-+++ b/drivers/gpu/drm/v3d/Kconfig
-@@ -1,6 +1,6 @@
- config DRM_V3D
-       tristate "Broadcom V3D 3.x and newer"
--      depends on ARCH_BCM || ARCH_BCMSTB || COMPILE_TEST
-+      depends on ARCH_BCM || ARCH_BCMSTB || ARCH_BCM2835 || COMPILE_TEST
-       depends on DRM
-       depends on COMMON_CLK
-       depends on MMU
diff --git a/target/linux/brcm2708/patches-4.19/950-0671-vc-sm-cma-Fix-compatibility-ioctl.patch b/target/linux/brcm2708/patches-4.19/950-0671-vc-sm-cma-Fix-compatibility-ioctl.patch
new file mode 100644 (file)
index 0000000..af453ec
--- /dev/null
@@ -0,0 +1,64 @@
+From a24a0a621486b36bcdf5c5e0afb05a5d1dd30003 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 19 Aug 2019 15:45:20 +0100
+Subject: [PATCH] vc-sm-cma: Fix compatibility ioctl
+
+This code path hasn't been used previously.
+Fixed up after testing with kodi on 32-bit userland and 64-bit kernel
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1501,11 +1501,10 @@ static long vc_sm_cma_ioctl(struct file
+       return ret;
+ }
+-#ifndef CONFIG_ARM64
+ #ifdef CONFIG_COMPAT
+ struct vc_sm_cma_ioctl_clean_invalid2_32 {
+       u32 op_count;
+-      struct vc_sm_cma_ioctl_clean_invalid_block {
++      struct vc_sm_cma_ioctl_clean_invalid_block_32 {
+               u16 invalidate_mode;
+               u16 block_count;
+               compat_uptr_t start_address;
+@@ -1516,7 +1515,7 @@ struct vc_sm_cma_ioctl_clean_invalid2_32
+ #define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
+       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
+-       struct vc_sm_cma_ioctl_clean_invalid2)
++       struct vc_sm_cma_ioctl_clean_invalid2_32)
+ static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
+                                  unsigned long arg)
+@@ -1524,24 +1523,21 @@ static long vc_sm_cma_compat_ioctl(struc
+       switch (cmd) {
+       case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
+               /* FIXME */
+-              break;
++              return -EINVAL;
+       default:
+-              return vc_sm_cma_compat_ioctl(file, cmd, arg);
++              return vc_sm_cma_ioctl(file, cmd, arg);
+       }
+ }
+ #endif
+-#endif
+ /* Device operations that we managed in this driver. */
+ static const struct file_operations vc_sm_ops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = vc_sm_cma_ioctl,
+-#ifndef CONFIG_ARM64
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl = vc_sm_cma_compat_ioctl,
+ #endif
+-#endif
+       .open = vc_sm_cma_open,
+       .release = vc_sm_cma_release,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0672-overlays-sc16ic752-i2c-Fix-xtal-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0672-overlays-sc16ic752-i2c-Fix-xtal-parameter.patch
deleted file mode 100644 (file)
index d148696..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From ee24998ecaed3d03890a7a5e04dddb8c5d073e97 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Sat, 17 Aug 2019 19:47:30 +0100
-Subject: [PATCH] overlays: sc16ic752-i2c: Fix xtal parameter
-
-The xtal parameter is targetting the wrong node - fix it.
-
-See: https://github.com/raspberrypi/linux/issues/3156
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
-@@ -35,6 +35,6 @@
-       __overrides__ {
-               int_pin = <&sc16is752>,"interrupts:0";
-               addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name";
--              xtal = <&sc16is752>,"clock-frequency:0";
-+              xtal = <&sc16is752_clk>,"clock-frequency:0";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0672-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch b/target/linux/brcm2708/patches-4.19/950-0672-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch
new file mode 100644 (file)
index 0000000..aabb005
--- /dev/null
@@ -0,0 +1,55 @@
+From ae6dba510ac29ef7b0e6c838fb1bcc8b9eb474b7 Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Thu, 22 Aug 2019 22:31:37 +0000
+Subject: [PATCH] staging: bcm2835-codec: add support for
+ V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME
+
+fixes #3171
+
+Signed-off-by: Aman Gupta <aman@tmm1.net>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 19 ++++++++++++++++++-
+ 1 file changed, 18 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
+@@ -1587,6 +1587,20 @@ static int bcm2835_codec_s_ctrl(struct v
+               ret = bcm2835_codec_set_level_profile(ctx, ctrl);
+               break;
++      case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: {
++              u32 mmal_bool = 1;
++
++              if (!ctx->component)
++                      break;
++
++              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++                                                  &ctx->component->output[0],
++                                                  MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
++                                                  &mmal_bool,
++                                                  sizeof(mmal_bool));
++              break;
++      }
++
+       default:
+               v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
+               return -EINVAL;
+@@ -2311,7 +2325,7 @@ static int bcm2835_codec_open(struct fil
+       hdl = &ctx->hdl;
+       if (dev->role == ENCODE) {
+               /* Encode controls */
+-              v4l2_ctrl_handler_init(hdl, 6);
++              v4l2_ctrl_handler_init(hdl, 7);
+               v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
+                                      V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+@@ -2355,6 +2369,9 @@ static int bcm2835_codec_open(struct fil
+                                        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+                                        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
+                                       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
++              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++                                V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
++                                0, 0, 0, 0);
+               if (hdl->error) {
+                       rc = hdl->error;
+                       goto free_ctrl_handler;
diff --git a/target/linux/brcm2708/patches-4.19/950-0673-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch b/target/linux/brcm2708/patches-4.19/950-0673-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch
new file mode 100644 (file)
index 0000000..3bdbb0b
--- /dev/null
@@ -0,0 +1,30 @@
+From 9a2eab654b11d27bcc5a32ebd374f6c9acc38ce4 Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Fri, 23 Aug 2019 16:29:07 -0700
+Subject: [PATCH] staging: bcm2835-codec: remove unnecessary padding on
+ encoder input
+
+The ISP and ENCODE roles have the same underlying hardware. Neither requires vertical alignment.
+
+Signed-off-by: Aman Gupta <aman@tmm1.net>
+---
+ .../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
+@@ -1050,12 +1050,12 @@ static int vidioc_try_fmt(struct bcm2835
+                       f->fmt.pix_mp.height = MIN_H;
+               /*
+-               * For codecs the buffer must have a vertical alignment of 16
++               * For decoders the buffer must have a vertical alignment of 16
+                * lines.
+                * The selection will reflect any cropping rectangle when only
+                * some of the pixels are active.
+                */
+-              if (ctx->dev->role != ISP)
++              if (ctx->dev->role == DECODE)
+                       f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
+       }
+       f->fmt.pix_mp.num_planes = 1;
diff --git a/target/linux/brcm2708/patches-4.19/950-0673-vc-sm-cma-Fix-compatibility-ioctl.patch b/target/linux/brcm2708/patches-4.19/950-0673-vc-sm-cma-Fix-compatibility-ioctl.patch
deleted file mode 100644 (file)
index af453ec..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From a24a0a621486b36bcdf5c5e0afb05a5d1dd30003 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 19 Aug 2019 15:45:20 +0100
-Subject: [PATCH] vc-sm-cma: Fix compatibility ioctl
-
-This code path hasn't been used previously.
-Fixed up after testing with kodi on 32-bit userland and 64-bit kernel
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 12 ++++--------
- 1 file changed, 4 insertions(+), 8 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -1501,11 +1501,10 @@ static long vc_sm_cma_ioctl(struct file
-       return ret;
- }
--#ifndef CONFIG_ARM64
- #ifdef CONFIG_COMPAT
- struct vc_sm_cma_ioctl_clean_invalid2_32 {
-       u32 op_count;
--      struct vc_sm_cma_ioctl_clean_invalid_block {
-+      struct vc_sm_cma_ioctl_clean_invalid_block_32 {
-               u16 invalidate_mode;
-               u16 block_count;
-               compat_uptr_t start_address;
-@@ -1516,7 +1515,7 @@ struct vc_sm_cma_ioctl_clean_invalid2_32
- #define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
-       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
--       struct vc_sm_cma_ioctl_clean_invalid2)
-+       struct vc_sm_cma_ioctl_clean_invalid2_32)
- static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
-                                  unsigned long arg)
-@@ -1524,24 +1523,21 @@ static long vc_sm_cma_compat_ioctl(struc
-       switch (cmd) {
-       case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
-               /* FIXME */
--              break;
-+              return -EINVAL;
-       default:
--              return vc_sm_cma_compat_ioctl(file, cmd, arg);
-+              return vc_sm_cma_ioctl(file, cmd, arg);
-       }
- }
- #endif
--#endif
- /* Device operations that we managed in this driver. */
- static const struct file_operations vc_sm_ops = {
-       .owner = THIS_MODULE,
-       .unlocked_ioctl = vc_sm_cma_ioctl,
--#ifndef CONFIG_ARM64
- #ifdef CONFIG_COMPAT
-       .compat_ioctl = vc_sm_cma_compat_ioctl,
- #endif
--#endif
-       .open = vc_sm_cma_open,
-       .release = vc_sm_cma_release,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0674-arm-dts-add-missing-Raspberry-Pi-model-names.patch b/target/linux/brcm2708/patches-4.19/950-0674-arm-dts-add-missing-Raspberry-Pi-model-names.patch
new file mode 100644 (file)
index 0000000..516e2a5
--- /dev/null
@@ -0,0 +1,58 @@
+From ac6c4a17f6f7aeb977b04dd4dc7e801b7776499f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Thu, 29 Aug 2019 16:26:22 +0200
+Subject: [PATCH] arm: dts: add missing Raspberry Pi model names
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is needed to identify the different models on distributions like OpenWrt.
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-b.dts      | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-cm.dts     | 1 +
+ arch/arm/boot/dts/bcm2710-rpi-cm3.dts    | 1 +
+ 4 files changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
+@@ -6,6 +6,7 @@
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ / {
++      compatible = "raspberrypi,model-b-plus", "brcm,bcm2835";
+       model = "Raspberry Pi Model B+";
+ };
+--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts
+@@ -6,6 +6,7 @@
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ / {
++      compatible = "raspberrypi,model-b", "brcm,bcm2835";
+       model = "Raspberry Pi Model B";
+ };
+--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts
+@@ -5,6 +5,7 @@
+ #include "bcm283x-rpi-csi1-4lane.dtsi"
+ / {
++      compatible = "raspberrypi,compute-module", "brcm,bcm2835";
+       model = "Raspberry Pi Compute Module";
+ };
+--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
+@@ -6,6 +6,7 @@
+ #include "bcm283x-rpi-csi1-4lane.dtsi"
+ / {
++      compatible = "raspberrypi,3-compute-module", "brcm,bcm2837";
+       model = "Raspberry Pi Compute Module 3";
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0674-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch b/target/linux/brcm2708/patches-4.19/950-0674-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch
deleted file mode 100644 (file)
index aabb005..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From ae6dba510ac29ef7b0e6c838fb1bcc8b9eb474b7 Mon Sep 17 00:00:00 2001
-From: Aman Gupta <aman@tmm1.net>
-Date: Thu, 22 Aug 2019 22:31:37 +0000
-Subject: [PATCH] staging: bcm2835-codec: add support for
- V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME
-
-fixes #3171
-
-Signed-off-by: Aman Gupta <aman@tmm1.net>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 19 ++++++++++++++++++-
- 1 file changed, 18 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
-@@ -1587,6 +1587,20 @@ static int bcm2835_codec_s_ctrl(struct v
-               ret = bcm2835_codec_set_level_profile(ctx, ctrl);
-               break;
-+      case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: {
-+              u32 mmal_bool = 1;
-+
-+              if (!ctx->component)
-+                      break;
-+
-+              ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+                                                  &ctx->component->output[0],
-+                                                  MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
-+                                                  &mmal_bool,
-+                                                  sizeof(mmal_bool));
-+              break;
-+      }
-+
-       default:
-               v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
-               return -EINVAL;
-@@ -2311,7 +2325,7 @@ static int bcm2835_codec_open(struct fil
-       hdl = &ctx->hdl;
-       if (dev->role == ENCODE) {
-               /* Encode controls */
--              v4l2_ctrl_handler_init(hdl, 6);
-+              v4l2_ctrl_handler_init(hdl, 7);
-               v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
-                                      V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-@@ -2355,6 +2369,9 @@ static int bcm2835_codec_open(struct fil
-                                        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
-                                        BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
-                                       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
-+              v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+                                V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
-+                                0, 0, 0, 0);
-               if (hdl->error) {
-                       rc = hdl->error;
-                       goto free_ctrl_handler;
diff --git a/target/linux/brcm2708/patches-4.19/950-0675-arch-arm-Add-model-string-to-cpuinfo.patch b/target/linux/brcm2708/patches-4.19/950-0675-arch-arm-Add-model-string-to-cpuinfo.patch
new file mode 100644 (file)
index 0000000..cd33961
--- /dev/null
@@ -0,0 +1,36 @@
+From d9f55647637be79ff42cb85497e43ca8b9a69a7b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 3 Sep 2019 18:16:56 +0100
+Subject: [PATCH] arch/arm: Add model string to cpuinfo
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/kernel/setup.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -1238,6 +1238,8 @@ static int c_show(struct seq_file *m, vo
+ {
+       int i, j;
+       u32 cpuid;
++      struct device_node *np;
++      const char *model;
+       for_each_online_cpu(i) {
+               /*
+@@ -1297,6 +1299,14 @@ static int c_show(struct seq_file *m, vo
+       seq_printf(m, "Revision\t: %04x\n", system_rev);
+       seq_printf(m, "Serial\t\t: %s\n", system_serial);
++      np = of_find_node_by_path("/");
++      if (np) {
++              if (!of_property_read_string(np, "model",
++                                           &model))
++                      seq_printf(m, "Model\t\t: %s\n", model);
++              of_node_put(np);
++      }
++
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0675-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch b/target/linux/brcm2708/patches-4.19/950-0675-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch
deleted file mode 100644 (file)
index 3bdbb0b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 9a2eab654b11d27bcc5a32ebd374f6c9acc38ce4 Mon Sep 17 00:00:00 2001
-From: Aman Gupta <aman@tmm1.net>
-Date: Fri, 23 Aug 2019 16:29:07 -0700
-Subject: [PATCH] staging: bcm2835-codec: remove unnecessary padding on
- encoder input
-
-The ISP and ENCODE roles have the same underlying hardware. Neither requires vertical alignment.
-
-Signed-off-by: Aman Gupta <aman@tmm1.net>
----
- .../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
-@@ -1050,12 +1050,12 @@ static int vidioc_try_fmt(struct bcm2835
-                       f->fmt.pix_mp.height = MIN_H;
-               /*
--               * For codecs the buffer must have a vertical alignment of 16
-+               * For decoders the buffer must have a vertical alignment of 16
-                * lines.
-                * The selection will reflect any cropping rectangle when only
-                * some of the pixels are active.
-                */
--              if (ctx->dev->role != ISP)
-+              if (ctx->dev->role == DECODE)
-                       f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
-       }
-       f->fmt.pix_mp.num_planes = 1;
diff --git a/target/linux/brcm2708/patches-4.19/950-0676-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch b/target/linux/brcm2708/patches-4.19/950-0676-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch
new file mode 100644 (file)
index 0000000..5e29b47
--- /dev/null
@@ -0,0 +1,58 @@
+From aabfcb0abbc34ca5f3c4b4f872123166eca2e100 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 3 Sep 2019 18:17:25 +0100
+Subject: [PATCH] arch/arm64: Add Revision, Serial, Model to cpuinfo
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm64/kernel/cpuinfo.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+--- a/arch/arm64/kernel/cpuinfo.c
++++ b/arch/arm64/kernel/cpuinfo.c
+@@ -27,6 +27,7 @@
+ #include <linux/elf.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
++#include <linux/of_platform.h>
+ #include <linux/personality.h>
+ #include <linux/preempt.h>
+ #include <linux/printk.h>
+@@ -126,6 +127,10 @@ static int c_show(struct seq_file *m, vo
+ {
+       int i, j;
+       bool compat = personality(current->personality) == PER_LINUX32;
++      struct device_node *np;
++      const char *model;
++      const char *serial;
++      u32 revision;
+       for_each_online_cpu(i) {
+               struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
+@@ -177,6 +182,26 @@ static int c_show(struct seq_file *m, vo
+               seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
+       }
++      seq_printf(m, "Hardware\t: BCM2835\n");
++
++      np = of_find_node_by_path("/system");
++      if (np) {
++              if (!of_property_read_u32(np, "linux,revision", &revision))
++                      seq_printf(m, "Revision\t: %04x\n", revision);
++              of_node_put(np);
++      }
++
++      np = of_find_node_by_path("/");
++      if (np) {
++              if (!of_property_read_string(np, "serial-number",
++                                           &serial))
++                      seq_printf(m, "Serial\t\t: %s\n", serial);
++              if (!of_property_read_string(np, "model",
++                                           &model))
++                      seq_printf(m, "Model\t\t: %s\n", model);
++              of_node_put(np);
++      }
++
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0676-arm-dts-add-missing-Raspberry-Pi-model-names.patch b/target/linux/brcm2708/patches-4.19/950-0676-arm-dts-add-missing-Raspberry-Pi-model-names.patch
deleted file mode 100644 (file)
index 516e2a5..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From ac6c4a17f6f7aeb977b04dd4dc7e801b7776499f Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
-Date: Thu, 29 Aug 2019 16:26:22 +0200
-Subject: [PATCH] arm: dts: add missing Raspberry Pi model names
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This is needed to identify the different models on distributions like OpenWrt.
-
-Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
----
- arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 +
- arch/arm/boot/dts/bcm2708-rpi-b.dts      | 1 +
- arch/arm/boot/dts/bcm2708-rpi-cm.dts     | 1 +
- arch/arm/boot/dts/bcm2710-rpi-cm3.dts    | 1 +
- 4 files changed, 4 insertions(+)
-
---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
-@@ -6,6 +6,7 @@
- #include "bcm283x-rpi-csi1-2lane.dtsi"
- / {
-+      compatible = "raspberrypi,model-b-plus", "brcm,bcm2835";
-       model = "Raspberry Pi Model B+";
- };
---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts
-@@ -6,6 +6,7 @@
- #include "bcm283x-rpi-csi1-2lane.dtsi"
- / {
-+      compatible = "raspberrypi,model-b", "brcm,bcm2835";
-       model = "Raspberry Pi Model B";
- };
---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts
-@@ -5,6 +5,7 @@
- #include "bcm283x-rpi-csi1-4lane.dtsi"
- / {
-+      compatible = "raspberrypi,compute-module", "brcm,bcm2835";
-       model = "Raspberry Pi Compute Module";
- };
---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
-@@ -6,6 +6,7 @@
- #include "bcm283x-rpi-csi1-4lane.dtsi"
- / {
-+      compatible = "raspberrypi,3-compute-module", "brcm,bcm2837";
-       model = "Raspberry Pi Compute Module 3";
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0677-arch-arm-Add-model-string-to-cpuinfo.patch b/target/linux/brcm2708/patches-4.19/950-0677-arch-arm-Add-model-string-to-cpuinfo.patch
deleted file mode 100644 (file)
index cd33961..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From d9f55647637be79ff42cb85497e43ca8b9a69a7b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 3 Sep 2019 18:16:56 +0100
-Subject: [PATCH] arch/arm: Add model string to cpuinfo
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/kernel/setup.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/arm/kernel/setup.c
-+++ b/arch/arm/kernel/setup.c
-@@ -1238,6 +1238,8 @@ static int c_show(struct seq_file *m, vo
- {
-       int i, j;
-       u32 cpuid;
-+      struct device_node *np;
-+      const char *model;
-       for_each_online_cpu(i) {
-               /*
-@@ -1297,6 +1299,14 @@ static int c_show(struct seq_file *m, vo
-       seq_printf(m, "Revision\t: %04x\n", system_rev);
-       seq_printf(m, "Serial\t\t: %s\n", system_serial);
-+      np = of_find_node_by_path("/");
-+      if (np) {
-+              if (!of_property_read_string(np, "model",
-+                                           &model))
-+                      seq_printf(m, "Model\t\t: %s\n", model);
-+              of_node_put(np);
-+      }
-+
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0677-media-dt-bindings-Add-binding-for-the-Sony-IMX219-se.patch b/target/linux/brcm2708/patches-4.19/950-0677-media-dt-bindings-Add-binding-for-the-Sony-IMX219-se.patch
new file mode 100644 (file)
index 0000000..30fa9b3
--- /dev/null
@@ -0,0 +1,77 @@
+From 2d8a780a994098f7c532b712abd7298e0bca5a12 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 28 Aug 2019 13:34:30 +0100
+Subject: [PATCH] media: dt-bindings: Add binding for the Sony IMX219
+ sensor
+
+The IMX219 is an 8MPix CSI2 sensor, supporting 2 or 4 data lanes.
+Document the binding for this device.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../devicetree/bindings/media/i2c/imx219.txt  | 59 +++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/media/i2c/imx219.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/media/i2c/imx219.txt
+@@ -0,0 +1,59 @@
++* Sony 1/4.0-Inch 8Mpixel CMOS Digital Image Sensor
++
++The Sony imx219 is a 1/4.0-inch CMOS active pixel digital image sensor with
++an active array size of 3280H x 2464V. It is programmable through I2C
++interface. The I2C address is fixed to 0x10 as per sensor data sheet.
++Image data is sent through MIPI CSI-2, which is configured as either 2 or 4
++data lanes.
++
++Required Properties:
++- compatible: value should be "sony,imx219" for imx219 sensor
++- reg: I2C bus address of the device
++- clocks: reference to the xclk input clock.
++- clock-names: should be "xclk".
++- DOVDD-supply: Digital I/O voltage supply, 1.8 volts
++- AVDD-supply: Analog voltage supply, 2.8 volts
++- DVDD-supply: Digital core voltage supply, 1.2 volts
++
++Optional Properties:
++- xclr-gpios: reference to the GPIO connected to the xclr pin, if any. Must be
++            released after all supplies are applied.
++            This is an active high signal to the imx219.
++
++The imx219 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.
++
++Endpoint node required properties for CSI-2 connection are:
++- remote-endpoint: a phandle to the bus receiver's endpoint node.
++- clock-lanes: should be set to <0> (clock lane on hardware lane 0)
++- data-lanes: should be set to <1 2>, or  <1 2 3 4> (two or four lane CSI-2
++  supported)
++
++Example:
++      sensor@10 {
++              compatible = "sony,imx219";
++              reg = <0x10>;
++              #address-cells = <1>;
++              #size-cells = <0>;
++              clocks = <&imx219_clk>;
++              clock-names = "xclk";
++              xclr-gpios = <&gpio_sensor 0 0>;
++              DOVDD-supply = <&vgen4_reg>; /* 1.8v */
++              AVDD-supply = <&vgen3_reg>;  /* 2.8v */
++              DVDD-supply = <&vgen2_reg>;  /* 1.2v */
++
++              imx219_clk: camera-clk {
++                      compatible = "fixed-clock";
++                      #clock-cells = <0>;
++                      clock-frequency = <24000000>;
++              };
++
++              port {
++                      sensor_out: endpoint {
++                              remote-endpoint = <&csiss_in>;
++                              clock-lanes = <0>;
++                              data-lanes = <1 2>;
++                      };
++              };
++      };
diff --git a/target/linux/brcm2708/patches-4.19/950-0678-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch b/target/linux/brcm2708/patches-4.19/950-0678-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch
deleted file mode 100644 (file)
index 5e29b47..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From aabfcb0abbc34ca5f3c4b4f872123166eca2e100 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 3 Sep 2019 18:17:25 +0100
-Subject: [PATCH] arch/arm64: Add Revision, Serial, Model to cpuinfo
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm64/kernel/cpuinfo.c | 25 +++++++++++++++++++++++++
- 1 file changed, 25 insertions(+)
-
---- a/arch/arm64/kernel/cpuinfo.c
-+++ b/arch/arm64/kernel/cpuinfo.c
-@@ -27,6 +27,7 @@
- #include <linux/elf.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
-+#include <linux/of_platform.h>
- #include <linux/personality.h>
- #include <linux/preempt.h>
- #include <linux/printk.h>
-@@ -126,6 +127,10 @@ static int c_show(struct seq_file *m, vo
- {
-       int i, j;
-       bool compat = personality(current->personality) == PER_LINUX32;
-+      struct device_node *np;
-+      const char *model;
-+      const char *serial;
-+      u32 revision;
-       for_each_online_cpu(i) {
-               struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
-@@ -177,6 +182,26 @@ static int c_show(struct seq_file *m, vo
-               seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
-       }
-+      seq_printf(m, "Hardware\t: BCM2835\n");
-+
-+      np = of_find_node_by_path("/system");
-+      if (np) {
-+              if (!of_property_read_u32(np, "linux,revision", &revision))
-+                      seq_printf(m, "Revision\t: %04x\n", revision);
-+              of_node_put(np);
-+      }
-+
-+      np = of_find_node_by_path("/");
-+      if (np) {
-+              if (!of_property_read_string(np, "serial-number",
-+                                           &serial))
-+                      seq_printf(m, "Serial\t\t: %s\n", serial);
-+              if (!of_property_read_string(np, "model",
-+                                           &model))
-+                      seq_printf(m, "Model\t\t: %s\n", model);
-+              of_node_put(np);
-+      }
-+
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0678-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch b/target/linux/brcm2708/patches-4.19/950-0678-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch
new file mode 100644 (file)
index 0000000..70b9d54
--- /dev/null
@@ -0,0 +1,1146 @@
+From 2186344c6d83ccd169e16c048c8b43aff95545e2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 28 Aug 2019 13:34:49 +0100
+Subject: [PATCH] media: i2c: Add driver for Sony IMX219 sensor
+
+Adds a driver for the 8MPix Sony IMX219 CSI2 sensor.
+Whilst the sensor supports 2 or 4 CSI2 data lanes, this driver
+currently only supports 2 lanes.
+8MPix @ 15fps, 1080P @ 30fps (cropped FOV), and 1640x1232 (2x2 binned)
+@ 30fps are currently supported.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/media/i2c/Kconfig  |   11 +
+ drivers/media/i2c/Makefile |    1 +
+ drivers/media/i2c/imx219.c | 1093 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1105 insertions(+)
+ create mode 100644 drivers/media/i2c/imx219.c
+
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -597,6 +597,17 @@ config VIDEO_APTINA_PLL
+ config VIDEO_SMIAPP_PLL
+       tristate
++config VIDEO_IMX219
++      tristate "Sony IMX219 sensor support"
++      depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
++      depends on MEDIA_CAMERA_SUPPORT
++      help
++        This is a Video4Linux2 sensor driver for the Sony
++        IMX219 camera.
++
++        To compile this driver as a module, choose M here: the
++        module will be called imx219.
++
+ config VIDEO_IMX258
+       tristate "Sony IMX258 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+--- a/drivers/media/i2c/Makefile
++++ b/drivers/media/i2c/Makefile
+@@ -106,6 +106,7 @@ obj-$(CONFIG_VIDEO_I2C)            += video-i2c.o
+ obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
+ obj-$(CONFIG_VIDEO_OV2659)    += ov2659.o
+ obj-$(CONFIG_VIDEO_TC358743)  += tc358743.o
++obj-$(CONFIG_VIDEO_IMX219)    += imx219.o
+ obj-$(CONFIG_VIDEO_IMX258)    += imx258.o
+ obj-$(CONFIG_VIDEO_IMX274)    += imx274.o
+--- /dev/null
++++ b/drivers/media/i2c/imx219.c
+@@ -0,0 +1,1093 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * A V4L2 driver for Sony IMX219 cameras.
++ * Copyright (C) 2019, Raspberry Pi (Trading) Ltd
++ *
++ * Based on Sony imx258 camera driver
++ * Copyright (C) 2018 Intel Corporation
++ *
++ * DT / fwnode changes, and regulator / GPIO control taken from ov5640.c
++ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
++ * Copyright (C) 2014-2017 Mentor Graphics Inc.
++ *
++ */
++
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/clkdev.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 <media/v4l2-ctrls.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-fwnode.h>
++#include <media/v4l2-mediabus.h>
++#include <asm/unaligned.h>
++
++#define IMX219_REG_VALUE_08BIT                1
++#define IMX219_REG_VALUE_16BIT                2
++
++#define IMX219_REG_MODE_SELECT                0x0100
++#define IMX219_MODE_STANDBY           0x00
++#define IMX219_MODE_STREAMING         0x01
++
++/* Chip ID */
++#define IMX219_REG_CHIP_ID            0x0000
++#define IMX219_CHIP_ID                        0x0219
++
++/* V_TIMING internal */
++#define IMX219_REG_VTS                        0x0160
++#define IMX219_VTS_15FPS              0x0dc6
++#define IMX219_VTS_30FPS_1080P                0x06e3
++#define IMX219_VTS_30FPS_BINNED               0x06e3
++#define IMX219_VTS_MAX                        0xffff
++
++/*Frame Length Line*/
++#define IMX219_FLL_MIN                        0x08a6
++#define IMX219_FLL_MAX                        0xffff
++#define IMX219_FLL_STEP                       1
++#define IMX219_FLL_DEFAULT            0x0c98
++
++/* HBLANK control - read only */
++#define IMX219_PPL_DEFAULT            5352
++
++/* Exposure control */
++#define IMX219_REG_EXPOSURE           0x015a
++#define IMX219_EXPOSURE_MIN           4
++#define IMX219_EXPOSURE_STEP          1
++#define IMX219_EXPOSURE_DEFAULT               0x640
++#define IMX219_EXPOSURE_MAX           65535
++
++/* Analog gain control */
++#define IMX219_REG_ANALOG_GAIN                0x0157
++#define IMX219_ANA_GAIN_MIN           0
++#define IMX219_ANA_GAIN_MAX           232
++#define IMX219_ANA_GAIN_STEP          1
++#define IMX219_ANA_GAIN_DEFAULT               0x0
++
++/* Digital gain control */
++#define IMX219_REG_DIGITAL_GAIN               0x0158
++#define IMX219_DGTL_GAIN_MIN          0x0100
++#define IMX219_DGTL_GAIN_MAX          0x0fff
++#define IMX219_DGTL_GAIN_DEFAULT      0x0100
++#define IMX219_DGTL_GAIN_STEP         1
++
++/* Test Pattern Control */
++#define IMX219_REG_TEST_PATTERN               0x0600
++#define IMX219_TEST_PATTERN_DISABLE   0
++#define IMX219_TEST_PATTERN_SOLID_COLOR       1
++#define IMX219_TEST_PATTERN_COLOR_BARS        2
++#define IMX219_TEST_PATTERN_GREY_COLOR        3
++#define IMX219_TEST_PATTERN_PN9               4
++
++struct imx219_reg {
++      u16 address;
++      u8 val;
++};
++
++struct imx219_reg_list {
++      u32 num_of_regs;
++      const struct imx219_reg *regs;
++};
++
++/* Mode : resolution and related config&values */
++struct imx219_mode {
++      /* Frame width */
++      u32 width;
++      /* Frame height */
++      u32 height;
++
++      /* V-timing */
++      u32 vts_def;
++
++      /* Default register values */
++      struct imx219_reg_list reg_list;
++};
++
++/*
++ * Register sets lifted off the i2C interface from the Raspberry Pi firmware
++ * driver.
++ * 3280x2464 = mode 2, 1920x1080 = mode 1, and 1640x1232 = mode 4.
++ */
++static const struct imx219_reg mode_3280x2464_regs[] = {
++      {0x0100, 0x00},
++      {0x30eb, 0x0c},
++      {0x30eb, 0x05},
++      {0x300a, 0xff},
++      {0x300b, 0xff},
++      {0x30eb, 0x05},
++      {0x30eb, 0x09},
++      {0x0114, 0x01},
++      {0x0128, 0x00},
++      {0x012a, 0x18},
++      {0x012b, 0x00},
++      {0x0164, 0x00},
++      {0x0165, 0x00},
++      {0x0166, 0x0c},
++      {0x0167, 0xcf},
++      {0x0168, 0x00},
++      {0x0169, 0x00},
++      {0x016a, 0x09},
++      {0x016b, 0x9f},
++      {0x016c, 0x0c},
++      {0x016d, 0xd0},
++      {0x016e, 0x09},
++      {0x016f, 0xa0},
++      {0x0170, 0x01},
++      {0x0171, 0x01},
++      {0x0174, 0x00},
++      {0x0175, 0x00},
++      {0x018c, 0x0a},
++      {0x018d, 0x0a},
++      {0x0301, 0x05},
++      {0x0303, 0x01},
++      {0x0304, 0x03},
++      {0x0305, 0x03},
++      {0x0306, 0x00},
++      {0x0307, 0x39},
++      {0x0309, 0x0a},
++      {0x030b, 0x01},
++      {0x030c, 0x00},
++      {0x030d, 0x72},
++      {0x0624, 0x0c},
++      {0x0625, 0xd0},
++      {0x0626, 0x09},
++      {0x0627, 0xa0},
++      {0x455e, 0x00},
++      {0x471e, 0x4b},
++      {0x4767, 0x0f},
++      {0x4750, 0x14},
++      {0x4540, 0x00},
++      {0x47b4, 0x14},
++      {0x4713, 0x30},
++      {0x478b, 0x10},
++      {0x478f, 0x10},
++      {0x4793, 0x10},
++      {0x4797, 0x0e},
++      {0x479b, 0x0e},
++
++      {0x0172, 0x03},
++      {0x0162, 0x0d},
++      {0x0163, 0x78},
++};
++
++static const struct imx219_reg mode_1920_1080_regs[] = {
++      {0x0100, 0x00},
++      {0x30eb, 0x05},
++      {0x30eb, 0x0c},
++      {0x300a, 0xff},
++      {0x300b, 0xff},
++      {0x30eb, 0x05},
++      {0x30eb, 0x09},
++      {0x0114, 0x01},
++      {0x0128, 0x00},
++      {0x012a, 0x18},
++      {0x012b, 0x00},
++      {0x0162, 0x0d},
++      {0x0163, 0x78},
++      {0x0164, 0x02},
++      {0x0165, 0xa8},
++      {0x0166, 0x0a},
++      {0x0167, 0x27},
++      {0x0168, 0x02},
++      {0x0169, 0xb4},
++      {0x016a, 0x06},
++      {0x016b, 0xeb},
++      {0x016c, 0x07},
++      {0x016d, 0x80},
++      {0x016e, 0x04},
++      {0x016f, 0x38},
++      {0x0170, 0x01},
++      {0x0171, 0x01},
++      {0x0174, 0x00},
++      {0x0175, 0x00},
++      {0x018c, 0x0a},
++      {0x018d, 0x0a},
++      {0x0301, 0x05},
++      {0x0303, 0x01},
++      {0x0304, 0x03},
++      {0x0305, 0x03},
++      {0x0306, 0x00},
++      {0x0307, 0x39},
++      {0x0309, 0x0a},
++      {0x030b, 0x01},
++      {0x030c, 0x00},
++      {0x030d, 0x72},
++      {0x455e, 0x00},
++      {0x471e, 0x4b},
++      {0x4767, 0x0f},
++      {0x4750, 0x14},
++      {0x4540, 0x00},
++      {0x47b4, 0x14},
++      {0x4713, 0x30},
++      {0x478b, 0x10},
++      {0x478f, 0x10},
++      {0x4793, 0x10},
++      {0x4797, 0x0e},
++      {0x479b, 0x0e},
++
++      {0x0172, 0x03},
++      {0x0162, 0x0d},
++      {0x0163, 0x78},
++};
++
++static const struct imx219_reg mode_1640_1232_regs[] = {
++      {0x30eb, 0x0c},
++      {0x30eb, 0x05},
++      {0x300a, 0xff},
++      {0x300b, 0xff},
++      {0x30eb, 0x05},
++      {0x30eb, 0x09},
++      {0x0114, 0x01},
++      {0x0128, 0x00},
++      {0x012a, 0x18},
++      {0x012b, 0x00},
++      {0x0164, 0x00},
++      {0x0165, 0x00},
++      {0x0166, 0x0c},
++      {0x0167, 0xcf},
++      {0x0168, 0x00},
++      {0x0169, 0x00},
++      {0x016a, 0x09},
++      {0x016b, 0x9f},
++      {0x016c, 0x06},
++      {0x016d, 0x68},
++      {0x016e, 0x04},
++      {0x016f, 0xd0},
++      {0x0170, 0x01},
++      {0x0171, 0x01},
++      {0x0174, 0x01},
++      {0x0175, 0x01},
++      {0x018c, 0x0a},
++      {0x018d, 0x0a},
++      {0x0301, 0x05},
++      {0x0303, 0x01},
++      {0x0304, 0x03},
++      {0x0305, 0x03},
++      {0x0306, 0x00},
++      {0x0307, 0x39},
++      {0x0309, 0x0a},
++      {0x030b, 0x01},
++      {0x030c, 0x00},
++      {0x030d, 0x72},
++      {0x455e, 0x00},
++      {0x471e, 0x4b},
++      {0x4767, 0x0f},
++      {0x4750, 0x14},
++      {0x4540, 0x00},
++      {0x47b4, 0x14},
++      {0x4713, 0x30},
++      {0x478b, 0x10},
++      {0x478f, 0x10},
++      {0x4793, 0x10},
++      {0x4797, 0x0e},
++      {0x479b, 0x0e},
++
++      {0x0172, 0x03},
++      {0x0162, 0x0d},
++      {0x0163, 0x78},
++};
++
++static const char * const imx219_test_pattern_menu[] = {
++      "Disabled",
++      "Color Bars",
++      "Solid Color",
++      "Grey Color Bars",
++      "PN9"
++};
++
++static const int imx219_test_pattern_val[] = {
++      IMX219_TEST_PATTERN_DISABLE,
++      IMX219_TEST_PATTERN_COLOR_BARS,
++      IMX219_TEST_PATTERN_SOLID_COLOR,
++      IMX219_TEST_PATTERN_GREY_COLOR,
++      IMX219_TEST_PATTERN_PN9,
++};
++
++/* regulator supplies */
++static const char * const imx219_supply_name[] = {
++      /* Supplies can be enabled in any order */
++      "VANA",  /* Analog (2.8V) supply */
++      "VDIG",  /* Digital Core (1.8V) supply */
++      "VDDL",  /* IF (1.2V) supply */
++};
++
++#define IMX219_NUM_SUPPLIES ARRAY_SIZE(imx219_supply_name)
++
++#define IMX219_XCLR_DELAY_MS 10       /* Initialisation delay after XCLR low->high */
++
++/* Mode configs */
++static const struct imx219_mode supported_modes[] = {
++      {
++              /* 8MPix 15fps mode */
++              .width = 3280,
++              .height = 2464,
++              .vts_def = IMX219_VTS_15FPS,
++              .reg_list = {
++                      .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
++                      .regs = mode_3280x2464_regs,
++              },
++      },
++      {
++              /* 1080P 30fps cropped */
++              .width = 1920,
++              .height = 1080,
++              .vts_def = IMX219_VTS_30FPS_1080P,
++              .reg_list = {
++                      .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
++                      .regs = mode_1920_1080_regs,
++              },
++      },
++      {
++              /* 2x2 binned 30fps mode */
++              .width = 1640,
++              .height = 1232,
++              .vts_def = IMX219_VTS_30FPS_BINNED,
++              .reg_list = {
++                      .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
++                      .regs = mode_1640_1232_regs,
++              },
++      },
++};
++
++struct imx219 {
++      struct v4l2_subdev sd;
++      struct media_pad pad;
++
++      struct v4l2_fwnode_endpoint ep; /* the parsed DT endpoint info */
++      struct clk *xclk; /* system clock to IMX219 */
++      u32 xclk_freq;
++
++      struct gpio_desc *xclr_gpio;
++      struct regulator_bulk_data supplies[IMX219_NUM_SUPPLIES];
++
++      struct v4l2_ctrl_handler ctrl_handler;
++      /* V4L2 Controls */
++      struct v4l2_ctrl *pixel_rate;
++      struct v4l2_ctrl *exposure;
++
++      /* Current mode */
++      const struct imx219_mode *mode;
++
++      /*
++       * Mutex for serialized access:
++       * Protect sensor module set pad format and start/stop streaming safely.
++       */
++      struct mutex mutex;
++
++      int power_count;
++      /* Streaming on/off */
++      bool streaming;
++};
++
++static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
++{
++      return container_of(_sd, struct imx219, sd);
++}
++
++/* Read registers up to 2 at a time */
++static int imx219_read_reg(struct imx219 *imx219, u16 reg, u32 len, u32 *val)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      struct i2c_msg msgs[2];
++      u8 addr_buf[2] = { reg >> 8, reg & 0xff };
++      u8 data_buf[4] = { 0, };
++      int ret;
++
++      if (len > 4)
++              return -EINVAL;
++
++      /* 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 = len;
++      msgs[1].buf = &data_buf[4 - len];
++
++      ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
++      if (ret != ARRAY_SIZE(msgs))
++              return -EIO;
++
++      *val = get_unaligned_be32(data_buf);
++
++      return 0;
++}
++
++/* Write registers up to 2 at a time */
++static int imx219_write_reg(struct imx219 *imx219, u16 reg, u32 len, u32 val)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      u8 buf[6];
++
++      if (len > 4)
++              return -EINVAL;
++
++      put_unaligned_be16(reg, buf);
++      put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
++      if (i2c_master_send(client, buf, len + 2) != len + 2)
++              return -EIO;
++
++      return 0;
++}
++
++/* Write a list of registers */
++static int imx219_write_regs(struct imx219 *imx219,
++                           const struct imx219_reg *regs, u32 len)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      unsigned int i;
++      int ret;
++
++      for (i = 0; i < len; i++) {
++              ret = imx219_write_reg(imx219, regs[i].address, 1, regs[i].val);
++              if (ret) {
++                      dev_err_ratelimited(&client->dev,
++                                          "Failed to write reg 0x%4.4x. error = %d\n",
++                                          regs[i].address, ret);
++
++                      return ret;
++              }
++      }
++
++      return 0;
++}
++
++/* Power/clock management functions */
++static void imx219_power(struct imx219 *imx219, bool enable)
++{
++      gpiod_set_value_cansleep(imx219->xclr_gpio, enable ? 1 : 0);
++}
++
++static int imx219_set_power_on(struct imx219 *imx219)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      int ret;
++
++      ret = clk_prepare_enable(imx219->xclk);
++      if (ret) {
++              dev_err(&client->dev, "%s: failed to enable clock\n",
++                      __func__);
++              return ret;
++      }
++
++      ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES,
++                                  imx219->supplies);
++      if (ret) {
++              dev_err(&client->dev, "%s: failed to enable regulators\n",
++                      __func__);
++              goto xclk_off;
++      }
++
++      imx219_power(imx219, true);
++      msleep(IMX219_XCLR_DELAY_MS);
++
++      return 0;
++xclk_off:
++      clk_disable_unprepare(imx219->xclk);
++      return ret;
++}
++
++static void imx219_set_power_off(struct imx219 *imx219)
++{
++      imx219_power(imx219, false);
++      regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
++      clk_disable_unprepare(imx219->xclk);
++}
++
++static int imx219_set_power(struct imx219 *imx219, bool on)
++{
++      int ret = 0;
++
++      if (on) {
++              ret = imx219_set_power_on(imx219);
++              if (ret)
++                      return ret;
++      } else {
++              imx219_set_power_off(imx219);
++      }
++
++      return 0;
++}
++
++/* Open sub-device */
++static int imx219_s_power(struct v4l2_subdev *sd, int on)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++      int ret = 0;
++
++      mutex_lock(&imx219->mutex);
++
++      /*
++       * If the power count is modified from 0 to != 0 or from != 0 to 0,
++       * update the power state.
++       */
++      if (imx219->power_count == !on) {
++              ret = imx219_set_power(imx219, !!on);
++              if (ret)
++                      goto out;
++      }
++
++      /* Update the power count. */
++      imx219->power_count += on ? 1 : -1;
++      WARN_ON(imx219->power_count < 0);
++out:
++      mutex_unlock(&imx219->mutex);
++
++      return ret;
++}
++
++static int imx219_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
++{
++      struct v4l2_mbus_framefmt *try_fmt =
++              v4l2_subdev_get_try_format(sd, fh->pad, 0);
++
++      /* Initialize try_fmt */
++      try_fmt->width = supported_modes[0].width;
++      try_fmt->height = supported_modes[0].height;
++      try_fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
++      try_fmt->field = V4L2_FIELD_NONE;
++
++      return 0;
++}
++
++static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
++{
++      struct imx219 *imx219 =
++              container_of(ctrl->handler, struct imx219, ctrl_handler);
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      int ret = 0;
++
++      /*
++       * Applying V4L2 control value only happens
++       * when power is up for streaming
++       */
++      if (pm_runtime_get_if_in_use(&client->dev) == 0)
++              return 0;
++
++      switch (ctrl->id) {
++      case V4L2_CID_ANALOGUE_GAIN:
++              ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN,
++                                     IMX219_REG_VALUE_08BIT, ctrl->val);
++              break;
++      case V4L2_CID_EXPOSURE:
++              ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE,
++                                     IMX219_REG_VALUE_16BIT, ctrl->val);
++              break;
++      case V4L2_CID_DIGITAL_GAIN:
++              ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN,
++                                     IMX219_REG_VALUE_16BIT, ctrl->val);
++              break;
++      case V4L2_CID_TEST_PATTERN:
++              ret = imx219_write_reg(imx219, IMX219_REG_TEST_PATTERN,
++                                     IMX219_REG_VALUE_16BIT,
++                                     imx219_test_pattern_val[ctrl->val]);
++              break;
++      default:
++              dev_info(&client->dev,
++                       "ctrl(id:0x%x,val:0x%x) is not handled\n",
++                       ctrl->id, ctrl->val);
++              ret = -EINVAL;
++              break;
++      }
++
++      pm_runtime_put(&client->dev);
++
++      return ret;
++}
++
++static const struct v4l2_ctrl_ops imx219_ctrl_ops = {
++      .s_ctrl = imx219_set_ctrl,
++};
++
++static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
++                               struct v4l2_subdev_pad_config *cfg,
++                               struct v4l2_subdev_mbus_code_enum *code)
++{
++      /* Only one bayer order(GRBG) is supported */
++      if (code->index > 0)
++              return -EINVAL;
++
++      code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
++
++      return 0;
++}
++
++static int imx219_enum_frame_size(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_SBGGR10_1X10)
++              return -EINVAL;
++
++      fse->min_width = supported_modes[fse->index].width;
++      fse->max_width = fse->min_width;
++      fse->min_height = supported_modes[fse->index].height;
++      fse->max_height = fse->min_height;
++
++      return 0;
++}
++
++static void imx219_update_pad_format(const struct imx219_mode *mode,
++                                   struct v4l2_subdev_format *fmt)
++{
++      fmt->format.width = mode->width;
++      fmt->format.height = mode->height;
++      fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
++      fmt->format.field = V4L2_FIELD_NONE;
++}
++
++static int __imx219_get_pad_format(struct imx219 *imx219,
++                                 struct v4l2_subdev_pad_config *cfg,
++                                 struct v4l2_subdev_format *fmt)
++{
++      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
++              fmt->format = *v4l2_subdev_get_try_format(&imx219->sd, cfg,
++                                                        fmt->pad);
++      else
++              imx219_update_pad_format(imx219->mode, fmt);
++
++      return 0;
++}
++
++static int imx219_get_pad_format(struct v4l2_subdev *sd,
++                               struct v4l2_subdev_pad_config *cfg,
++                               struct v4l2_subdev_format *fmt)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++      int ret;
++
++      mutex_lock(&imx219->mutex);
++      ret = __imx219_get_pad_format(imx219, cfg, fmt);
++      mutex_unlock(&imx219->mutex);
++
++      return ret;
++}
++
++static int imx219_set_pad_format(struct v4l2_subdev *sd,
++                               struct v4l2_subdev_pad_config *cfg,
++                               struct v4l2_subdev_format *fmt)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++      const struct imx219_mode *mode;
++      struct v4l2_mbus_framefmt *framefmt;
++
++      mutex_lock(&imx219->mutex);
++
++      /* Only one raw bayer(BGGR) order is supported */
++      fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
++
++      mode = v4l2_find_nearest_size(supported_modes,
++                                    ARRAY_SIZE(supported_modes),
++                                    width, height,
++                                    fmt->format.width, fmt->format.height);
++      imx219_update_pad_format(mode, fmt);
++      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
++              framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
++              *framefmt = fmt->format;
++      } else {
++              imx219->mode = mode;
++      }
++
++      mutex_unlock(&imx219->mutex);
++
++      return 0;
++}
++
++/* Start streaming */
++static int imx219_start_streaming(struct imx219 *imx219)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      const struct imx219_reg_list *reg_list;
++      int ret;
++
++      /* Apply default values of current mode */
++      reg_list = &imx219->mode->reg_list;
++      ret = imx219_write_regs(imx219, reg_list->regs, reg_list->num_of_regs);
++      if (ret) {
++              dev_err(&client->dev, "%s failed to set mode\n", __func__);
++              return ret;
++      }
++
++      /*
++       * Set VTS appropriately for frame rate control.
++       * Currently fixed per mode.
++       */
++      ret = imx219_write_reg(imx219, IMX219_REG_VTS,
++                             IMX219_REG_VALUE_16BIT, imx219->mode->vts_def);
++      if (ret)
++              return ret;
++
++      /* Apply customized values from user */
++      ret =  __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler);
++      if (ret)
++              return ret;
++
++      /* set stream on register */
++      return imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
++                              IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING);
++}
++
++/* Stop streaming */
++static int imx219_stop_streaming(struct imx219 *imx219)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      int ret;
++
++      /* set stream off register */
++      ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
++                             IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY);
++      if (ret)
++              dev_err(&client->dev, "%s failed to set stream\n", __func__);
++
++      /*
++       * Return success even if it was an error, as there is nothing the
++       * caller can do about it.
++       */
++      return 0;
++}
++
++static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++      int ret = 0;
++
++      mutex_lock(&imx219->mutex);
++      if (imx219->streaming == enable) {
++              mutex_unlock(&imx219->mutex);
++              return 0;
++      }
++
++      if (enable) {
++              ret = pm_runtime_get_sync(&client->dev);
++              if (ret < 0) {
++                      pm_runtime_put_noidle(&client->dev);
++                      goto err_unlock;
++              }
++
++              /*
++               * Apply default & customized values
++               * and then start streaming.
++               */
++              ret = imx219_start_streaming(imx219);
++              if (ret) {
++                      pm_runtime_put(&client->dev);
++                      goto err_unlock;
++              }
++      } else {
++              imx219_stop_streaming(imx219);
++              pm_runtime_put(&client->dev);
++      }
++
++      imx219->streaming = enable;
++      mutex_unlock(&imx219->mutex);
++
++      return ret;
++
++err_unlock:
++      mutex_unlock(&imx219->mutex);
++
++      return ret;
++}
++
++static int __maybe_unused imx219_suspend(struct device *dev)
++{
++      struct i2c_client *client = to_i2c_client(dev);
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct imx219 *imx219 = to_imx219(sd);
++
++      if (imx219->streaming)
++              imx219_stop_streaming(imx219);
++
++      return 0;
++}
++
++static int __maybe_unused imx219_resume(struct device *dev)
++{
++      struct i2c_client *client = to_i2c_client(dev);
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct imx219 *imx219 = to_imx219(sd);
++      int ret;
++
++      if (imx219->streaming) {
++              ret = imx219_start_streaming(imx219);
++              if (ret)
++                      goto error;
++      }
++
++      return 0;
++
++error:
++      imx219_stop_streaming(imx219);
++      imx219->streaming = 0;
++      return ret;
++}
++
++static int imx219_get_regulators(struct imx219 *imx219)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      int i;
++
++      for (i = 0; i < IMX219_NUM_SUPPLIES; i++)
++              imx219->supplies[i].supply = imx219_supply_name[i];
++
++      return devm_regulator_bulk_get(&client->dev,
++                                     IMX219_NUM_SUPPLIES,
++                                     imx219->supplies);
++}
++
++/* Verify chip ID */
++static int imx219_identify_module(struct imx219 *imx219)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      int ret;
++      u32 val;
++
++      ret = imx219_set_power_on(imx219);
++      if (ret)
++              return ret;
++
++      ret = imx219_read_reg(imx219, IMX219_REG_CHIP_ID,
++                            IMX219_REG_VALUE_16BIT, &val);
++      if (ret) {
++              dev_err(&client->dev, "failed to read chip id %x\n",
++                      IMX219_CHIP_ID);
++              goto power_off;
++      }
++
++      if (val != IMX219_CHIP_ID) {
++              dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
++                      IMX219_CHIP_ID, val);
++              ret = -EIO;
++      }
++
++power_off:
++      imx219_set_power_off(imx219);
++      return ret;
++}
++
++static const struct v4l2_subdev_core_ops imx219_core_ops = {
++      .s_power = imx219_s_power,
++};
++
++static const struct v4l2_subdev_video_ops imx219_video_ops = {
++      .s_stream = imx219_set_stream,
++};
++
++static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
++      .enum_mbus_code = imx219_enum_mbus_code,
++      .get_fmt = imx219_get_pad_format,
++      .set_fmt = imx219_set_pad_format,
++      .enum_frame_size = imx219_enum_frame_size,
++};
++
++static const struct v4l2_subdev_ops imx219_subdev_ops = {
++      .core = &imx219_core_ops,
++      .video = &imx219_video_ops,
++      .pad = &imx219_pad_ops,
++};
++
++static const struct v4l2_subdev_internal_ops imx219_internal_ops = {
++      .open = imx219_open,
++};
++
++/* Initialize control handlers */
++static int imx219_init_controls(struct imx219 *imx219)
++{
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      struct v4l2_ctrl_handler *ctrl_hdlr;
++      int ret;
++
++      ctrl_hdlr = &imx219->ctrl_handler;
++      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);
++      if (ret)
++              return ret;
++
++      mutex_init(&imx219->mutex);
++      ctrl_hdlr->lock = &imx219->mutex;
++
++      imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                           V4L2_CID_EXPOSURE,
++                                           IMX219_EXPOSURE_MIN,
++                                           IMX219_EXPOSURE_MAX,
++                                           IMX219_EXPOSURE_STEP,
++                                           IMX219_EXPOSURE_DEFAULT);
++
++      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
++                        IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX,
++                        IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT);
++
++      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
++                        IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX,
++                        IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT);
++
++      v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops,
++                                   V4L2_CID_TEST_PATTERN,
++                                   ARRAY_SIZE(imx219_test_pattern_menu) - 1,
++                                   0, 0, imx219_test_pattern_menu);
++
++      if (ctrl_hdlr->error) {
++              ret = ctrl_hdlr->error;
++              dev_err(&client->dev, "%s control init failed (%d)\n",
++                      __func__, ret);
++              goto error;
++      }
++
++      imx219->sd.ctrl_handler = ctrl_hdlr;
++
++      return 0;
++
++error:
++      v4l2_ctrl_handler_free(ctrl_hdlr);
++      mutex_destroy(&imx219->mutex);
++
++      return ret;
++}
++
++static void imx219_free_controls(struct imx219 *imx219)
++{
++      v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
++      mutex_destroy(&imx219->mutex);
++}
++
++static int imx219_probe(struct i2c_client *client,
++                      const struct i2c_device_id *id)
++{
++      struct device *dev = &client->dev;
++      struct fwnode_handle *endpoint;
++      struct imx219 *imx219;
++      int ret;
++
++      imx219 = devm_kzalloc(&client->dev, sizeof(*imx219), GFP_KERNEL);
++      if (!imx219)
++              return -ENOMEM;
++
++      /* Initialize subdev */
++      v4l2_i2c_subdev_init(&imx219->sd, client, &imx219_subdev_ops);
++
++      /* Get CSI2 bus config */
++      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
++                                                NULL);
++      if (!endpoint) {
++              dev_err(dev, "endpoint node not found\n");
++              return -EINVAL;
++      }
++
++      ret = v4l2_fwnode_endpoint_parse(endpoint, &imx219->ep);
++      fwnode_handle_put(endpoint);
++      if (ret) {
++              dev_err(dev, "Could not parse endpoint\n");
++              return ret;
++      }
++
++      /* Get system clock (xclk) */
++      imx219->xclk = devm_clk_get(dev, "xclk");
++      if (IS_ERR(imx219->xclk)) {
++              dev_err(dev, "failed to get xclk\n");
++              return PTR_ERR(imx219->xclk);
++      }
++
++      imx219->xclk_freq = clk_get_rate(imx219->xclk);
++      if (imx219->xclk_freq != 24000000) {
++              dev_err(dev, "xclk frequency not supported: %d Hz\n",
++                      imx219->xclk_freq);
++              return -EINVAL;
++      }
++
++      ret = imx219_get_regulators(imx219);
++      if (ret)
++              return ret;
++
++      /* request optional power down pin */
++      imx219->xclr_gpio = devm_gpiod_get_optional(dev, "xclr",
++                                                  GPIOD_OUT_HIGH);
++
++      /* Check module identity */
++      ret = imx219_identify_module(imx219);
++      if (ret)
++              return ret;
++
++      /* Set default mode to max resolution */
++      imx219->mode = &supported_modes[0];
++
++      ret = imx219_init_controls(imx219);
++      if (ret)
++              return ret;
++
++      /* Initialize subdev */
++      imx219->sd.internal_ops = &imx219_internal_ops;
++      imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
++      imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
++
++      /* Initialize source pad */
++      imx219->pad.flags = MEDIA_PAD_FL_SOURCE;
++
++      ret = media_entity_pads_init(&imx219->sd.entity, 1, &imx219->pad);
++      if (ret)
++              goto error_handler_free;
++
++      ret = v4l2_async_register_subdev_sensor_common(&imx219->sd);
++      if (ret < 0)
++              goto error_media_entity;
++
++      pm_runtime_set_active(&client->dev);
++      pm_runtime_enable(&client->dev);
++      pm_runtime_idle(&client->dev);
++
++      return 0;
++
++error_media_entity:
++      media_entity_cleanup(&imx219->sd.entity);
++
++error_handler_free:
++      imx219_free_controls(imx219);
++
++      return ret;
++}
++
++static int imx219_remove(struct i2c_client *client)
++{
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct imx219 *imx219 = to_imx219(sd);
++
++      v4l2_async_unregister_subdev(sd);
++      media_entity_cleanup(&sd->entity);
++      imx219_free_controls(imx219);
++
++      pm_runtime_disable(&client->dev);
++      pm_runtime_set_suspended(&client->dev);
++
++      return 0;
++}
++
++static const struct of_device_id imx219_dt_ids[] = {
++      { .compatible = "sony,imx219" },
++      { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, imx219_dt_ids);
++
++static struct i2c_driver imx219_i2c_driver = {
++      .driver = {
++              .name = "imx219",
++              .of_match_table = imx219_dt_ids,
++      },
++      .probe = imx219_probe,
++      .remove = imx219_remove,
++};
++
++module_i2c_driver(imx219_i2c_driver);
++
++MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.org");
++MODULE_DESCRIPTION("Sony IMX219 sensor driver");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0679-dtoverlays-Add-overlay-for-the-Sony-IMX219-image-sen.patch b/target/linux/brcm2708/patches-4.19/950-0679-dtoverlays-Add-overlay-for-the-Sony-IMX219-image-sen.patch
new file mode 100644 (file)
index 0000000..9be42a6
--- /dev/null
@@ -0,0 +1,180 @@
+From 7a4d12054b24c8cb980be4c6466b50c14beb78d3 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 28 Aug 2019 13:35:19 +0100
+Subject: [PATCH] dtoverlays: Add overlay for the Sony IMX219 image
+ sensor.
+
+Adds an overlay for the IMX219 image sensor, connected to the
+Unicam CSI2 receiver peripheral.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  12 ++
+ arch/arm/boot/dts/overlays/imx219-overlay.dts | 129 ++++++++++++++++++
+ 3 files changed, 142 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/imx219-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -77,6 +77,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       i2c6.dtbo \
+       i2s-gpio28-31.dtbo \
+       ilitek251x.dtbo \
++      imx219.dtbo \
+       iqaudio-codec.dtbo \
+       iqaudio-dac.dtbo \
+       iqaudio-dacplus.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1269,6 +1269,18 @@ Params: interrupt               GPIO use
+                                 touchscreen (in pixels)
++Name:   imx219
++Info:   Sony IMX219 camera module.
++        Uses Unicam 1, which is the standard camera connector on most Pi
++        variants.
++Load:   dtoverlay=imx219,<param>=<val>
++Params: i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
++                                Useful on Compute Modules.
++
++        i2c_pins_28_29          Use pins 28&29 for the I2C instead of 44&45.
++                                This is required for Pi B+, 2, 0, and 0W.
++
++
+ Name:   iqaudio-codec
+ Info:   Configures the IQaudio Codec audio card
+ Load:   dtoverlay=iqaudio-codec
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/imx219-overlay.dts
+@@ -0,0 +1,129 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Definitions for IMX219 camera module on VC I2C bus
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c_vc>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      imx219: imx219@10 {
++                              compatible = "sony,imx219";
++                              reg = <0x10>;
++                              status = "okay";
++
++                              clocks = <&imx219_clk>;
++                              clock-names = "xclk";
++
++                              VANA-supply = <&imx219_vana>;   /* 2.8v */
++                              VDIG-supply = <&imx219_vdig>;   /* 1.8v */
++                              VDDL-supply = <&imx219_vddl>;   /* 1.2v */
++
++                              imx219_clk: camera-clk {
++                                      compatible = "fixed-clock";
++                                      #clock-cells = <0>;
++                                      clock-frequency = <24000000>;
++                              };
++
++                              port {
++                                      imx219_0: endpoint {
++                                              remote-endpoint = <&csi1_ep>;
++                                              clock-lanes = <0>;
++                                              data-lanes = <1 2>;
++                                              clock-noncontinuous;
++                                              link-frequencies =
++                                                      /bits/ 64 <297000000>;
++                                      };
++                              };
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&csi1>;
++              __overlay__ {
++                      status = "okay";
++
++                      port {
++                              csi1_ep: endpoint {
++                                      remote-endpoint = <&imx219_0>;
++                              };
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c0_pins>;
++              __dormant__ {
++                      brcm,pins = <28 29>;
++                      brcm,function = <4>; /* alt0 */
++              };
++      };
++      fragment@3 {
++              target = <&i2c0_pins>;
++              __overlay__ {
++                      brcm,pins = <44 45>;
++                      brcm,function = <5>; /* alt1 */
++              };
++      };
++      fragment@4 {
++              target = <&i2c0_pins>;
++              __dormant__ {
++                      brcm,pins = <0 1>;
++                      brcm,function = <4>; /* alt0 */
++              };
++      };
++      fragment@5 {
++              target = <&i2c_vc>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@6 {
++              target-path="/";
++              __overlay__ {
++                      imx219_vana: fixedregulator@0 {
++                              compatible = "regulator-fixed";
++                              regulator-name = "imx219_vana";
++                              regulator-min-microvolt = <2800000>;
++                              regulator-max-microvolt = <2800000>;
++                              gpio = <&gpio 41 GPIO_ACTIVE_HIGH>;
++                              enable-active-high;
++                      };
++                      imx219_vdig: fixedregulator@1 {
++                              compatible = "regulator-fixed";
++                              regulator-name = "imx219_vdig";
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                      };
++                      imx219_vddl: fixedregulator@2 {
++                              compatible = "regulator-fixed";
++                              regulator-name = "imx219_vddl";
++                              regulator-min-microvolt = <1200000>;
++                              regulator-max-microvolt = <1200000>;
++                      };
++              };
++      };
++
++      fragment@7 {
++              target-path="/__overrides__";
++              __overlay__ {
++                      cam0-pwdn-ctrl = <&imx219_vana>,"gpio:0";
++                      cam0-pwdn      = <&imx219_vana>,"gpio:4";
++              };
++      };
++
++      __overrides__ {
++              i2c_pins_0_1 = <0>,"-2-3+4";
++              i2c_pins_28_29 = <0>,"+2-3-4";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0679-media-dt-bindings-Add-binding-for-the-Sony-IMX219-se.patch b/target/linux/brcm2708/patches-4.19/950-0679-media-dt-bindings-Add-binding-for-the-Sony-IMX219-se.patch
deleted file mode 100644 (file)
index 30fa9b3..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-From 2d8a780a994098f7c532b712abd7298e0bca5a12 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 28 Aug 2019 13:34:30 +0100
-Subject: [PATCH] media: dt-bindings: Add binding for the Sony IMX219
- sensor
-
-The IMX219 is an 8MPix CSI2 sensor, supporting 2 or 4 data lanes.
-Document the binding for this device.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../devicetree/bindings/media/i2c/imx219.txt  | 59 +++++++++++++++++++
- 1 file changed, 59 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/media/i2c/imx219.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/media/i2c/imx219.txt
-@@ -0,0 +1,59 @@
-+* Sony 1/4.0-Inch 8Mpixel CMOS Digital Image Sensor
-+
-+The Sony imx219 is a 1/4.0-inch CMOS active pixel digital image sensor with
-+an active array size of 3280H x 2464V. It is programmable through I2C
-+interface. The I2C address is fixed to 0x10 as per sensor data sheet.
-+Image data is sent through MIPI CSI-2, which is configured as either 2 or 4
-+data lanes.
-+
-+Required Properties:
-+- compatible: value should be "sony,imx219" for imx219 sensor
-+- reg: I2C bus address of the device
-+- clocks: reference to the xclk input clock.
-+- clock-names: should be "xclk".
-+- DOVDD-supply: Digital I/O voltage supply, 1.8 volts
-+- AVDD-supply: Analog voltage supply, 2.8 volts
-+- DVDD-supply: Digital core voltage supply, 1.2 volts
-+
-+Optional Properties:
-+- xclr-gpios: reference to the GPIO connected to the xclr pin, if any. Must be
-+            released after all supplies are applied.
-+            This is an active high signal to the imx219.
-+
-+The imx219 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.
-+
-+Endpoint node required properties for CSI-2 connection are:
-+- remote-endpoint: a phandle to the bus receiver's endpoint node.
-+- clock-lanes: should be set to <0> (clock lane on hardware lane 0)
-+- data-lanes: should be set to <1 2>, or  <1 2 3 4> (two or four lane CSI-2
-+  supported)
-+
-+Example:
-+      sensor@10 {
-+              compatible = "sony,imx219";
-+              reg = <0x10>;
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              clocks = <&imx219_clk>;
-+              clock-names = "xclk";
-+              xclr-gpios = <&gpio_sensor 0 0>;
-+              DOVDD-supply = <&vgen4_reg>; /* 1.8v */
-+              AVDD-supply = <&vgen3_reg>;  /* 2.8v */
-+              DVDD-supply = <&vgen2_reg>;  /* 1.2v */
-+
-+              imx219_clk: camera-clk {
-+                      compatible = "fixed-clock";
-+                      #clock-cells = <0>;
-+                      clock-frequency = <24000000>;
-+              };
-+
-+              port {
-+                      sensor_out: endpoint {
-+                              remote-endpoint = <&csiss_in>;
-+                              clock-lanes = <0>;
-+                              data-lanes = <1 2>;
-+                      };
-+              };
-+      };
diff --git a/target/linux/brcm2708/patches-4.19/950-0680-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch b/target/linux/brcm2708/patches-4.19/950-0680-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch
deleted file mode 100644 (file)
index 70b9d54..0000000
+++ /dev/null
@@ -1,1146 +0,0 @@
-From 2186344c6d83ccd169e16c048c8b43aff95545e2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 28 Aug 2019 13:34:49 +0100
-Subject: [PATCH] media: i2c: Add driver for Sony IMX219 sensor
-
-Adds a driver for the 8MPix Sony IMX219 CSI2 sensor.
-Whilst the sensor supports 2 or 4 CSI2 data lanes, this driver
-currently only supports 2 lanes.
-8MPix @ 15fps, 1080P @ 30fps (cropped FOV), and 1640x1232 (2x2 binned)
-@ 30fps are currently supported.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/media/i2c/Kconfig  |   11 +
- drivers/media/i2c/Makefile |    1 +
- drivers/media/i2c/imx219.c | 1093 ++++++++++++++++++++++++++++++++++++
- 3 files changed, 1105 insertions(+)
- create mode 100644 drivers/media/i2c/imx219.c
-
---- a/drivers/media/i2c/Kconfig
-+++ b/drivers/media/i2c/Kconfig
-@@ -597,6 +597,17 @@ config VIDEO_APTINA_PLL
- config VIDEO_SMIAPP_PLL
-       tristate
-+config VIDEO_IMX219
-+      tristate "Sony IMX219 sensor support"
-+      depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-+      depends on MEDIA_CAMERA_SUPPORT
-+      help
-+        This is a Video4Linux2 sensor driver for the Sony
-+        IMX219 camera.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called imx219.
-+
- config VIDEO_IMX258
-       tristate "Sony IMX258 sensor support"
-       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
---- a/drivers/media/i2c/Makefile
-+++ b/drivers/media/i2c/Makefile
-@@ -106,6 +106,7 @@ obj-$(CONFIG_VIDEO_I2C)            += video-i2c.o
- obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
- obj-$(CONFIG_VIDEO_OV2659)    += ov2659.o
- obj-$(CONFIG_VIDEO_TC358743)  += tc358743.o
-+obj-$(CONFIG_VIDEO_IMX219)    += imx219.o
- obj-$(CONFIG_VIDEO_IMX258)    += imx258.o
- obj-$(CONFIG_VIDEO_IMX274)    += imx274.o
---- /dev/null
-+++ b/drivers/media/i2c/imx219.c
-@@ -0,0 +1,1093 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * A V4L2 driver for Sony IMX219 cameras.
-+ * Copyright (C) 2019, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on Sony imx258 camera driver
-+ * Copyright (C) 2018 Intel Corporation
-+ *
-+ * DT / fwnode changes, and regulator / GPIO control taken from ov5640.c
-+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
-+ * Copyright (C) 2014-2017 Mentor Graphics Inc.
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.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 <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-mediabus.h>
-+#include <asm/unaligned.h>
-+
-+#define IMX219_REG_VALUE_08BIT                1
-+#define IMX219_REG_VALUE_16BIT                2
-+
-+#define IMX219_REG_MODE_SELECT                0x0100
-+#define IMX219_MODE_STANDBY           0x00
-+#define IMX219_MODE_STREAMING         0x01
-+
-+/* Chip ID */
-+#define IMX219_REG_CHIP_ID            0x0000
-+#define IMX219_CHIP_ID                        0x0219
-+
-+/* V_TIMING internal */
-+#define IMX219_REG_VTS                        0x0160
-+#define IMX219_VTS_15FPS              0x0dc6
-+#define IMX219_VTS_30FPS_1080P                0x06e3
-+#define IMX219_VTS_30FPS_BINNED               0x06e3
-+#define IMX219_VTS_MAX                        0xffff
-+
-+/*Frame Length Line*/
-+#define IMX219_FLL_MIN                        0x08a6
-+#define IMX219_FLL_MAX                        0xffff
-+#define IMX219_FLL_STEP                       1
-+#define IMX219_FLL_DEFAULT            0x0c98
-+
-+/* HBLANK control - read only */
-+#define IMX219_PPL_DEFAULT            5352
-+
-+/* Exposure control */
-+#define IMX219_REG_EXPOSURE           0x015a
-+#define IMX219_EXPOSURE_MIN           4
-+#define IMX219_EXPOSURE_STEP          1
-+#define IMX219_EXPOSURE_DEFAULT               0x640
-+#define IMX219_EXPOSURE_MAX           65535
-+
-+/* Analog gain control */
-+#define IMX219_REG_ANALOG_GAIN                0x0157
-+#define IMX219_ANA_GAIN_MIN           0
-+#define IMX219_ANA_GAIN_MAX           232
-+#define IMX219_ANA_GAIN_STEP          1
-+#define IMX219_ANA_GAIN_DEFAULT               0x0
-+
-+/* Digital gain control */
-+#define IMX219_REG_DIGITAL_GAIN               0x0158
-+#define IMX219_DGTL_GAIN_MIN          0x0100
-+#define IMX219_DGTL_GAIN_MAX          0x0fff
-+#define IMX219_DGTL_GAIN_DEFAULT      0x0100
-+#define IMX219_DGTL_GAIN_STEP         1
-+
-+/* Test Pattern Control */
-+#define IMX219_REG_TEST_PATTERN               0x0600
-+#define IMX219_TEST_PATTERN_DISABLE   0
-+#define IMX219_TEST_PATTERN_SOLID_COLOR       1
-+#define IMX219_TEST_PATTERN_COLOR_BARS        2
-+#define IMX219_TEST_PATTERN_GREY_COLOR        3
-+#define IMX219_TEST_PATTERN_PN9               4
-+
-+struct imx219_reg {
-+      u16 address;
-+      u8 val;
-+};
-+
-+struct imx219_reg_list {
-+      u32 num_of_regs;
-+      const struct imx219_reg *regs;
-+};
-+
-+/* Mode : resolution and related config&values */
-+struct imx219_mode {
-+      /* Frame width */
-+      u32 width;
-+      /* Frame height */
-+      u32 height;
-+
-+      /* V-timing */
-+      u32 vts_def;
-+
-+      /* Default register values */
-+      struct imx219_reg_list reg_list;
-+};
-+
-+/*
-+ * Register sets lifted off the i2C interface from the Raspberry Pi firmware
-+ * driver.
-+ * 3280x2464 = mode 2, 1920x1080 = mode 1, and 1640x1232 = mode 4.
-+ */
-+static const struct imx219_reg mode_3280x2464_regs[] = {
-+      {0x0100, 0x00},
-+      {0x30eb, 0x0c},
-+      {0x30eb, 0x05},
-+      {0x300a, 0xff},
-+      {0x300b, 0xff},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x09},
-+      {0x0114, 0x01},
-+      {0x0128, 0x00},
-+      {0x012a, 0x18},
-+      {0x012b, 0x00},
-+      {0x0164, 0x00},
-+      {0x0165, 0x00},
-+      {0x0166, 0x0c},
-+      {0x0167, 0xcf},
-+      {0x0168, 0x00},
-+      {0x0169, 0x00},
-+      {0x016a, 0x09},
-+      {0x016b, 0x9f},
-+      {0x016c, 0x0c},
-+      {0x016d, 0xd0},
-+      {0x016e, 0x09},
-+      {0x016f, 0xa0},
-+      {0x0170, 0x01},
-+      {0x0171, 0x01},
-+      {0x0174, 0x00},
-+      {0x0175, 0x00},
-+      {0x018c, 0x0a},
-+      {0x018d, 0x0a},
-+      {0x0301, 0x05},
-+      {0x0303, 0x01},
-+      {0x0304, 0x03},
-+      {0x0305, 0x03},
-+      {0x0306, 0x00},
-+      {0x0307, 0x39},
-+      {0x0309, 0x0a},
-+      {0x030b, 0x01},
-+      {0x030c, 0x00},
-+      {0x030d, 0x72},
-+      {0x0624, 0x0c},
-+      {0x0625, 0xd0},
-+      {0x0626, 0x09},
-+      {0x0627, 0xa0},
-+      {0x455e, 0x00},
-+      {0x471e, 0x4b},
-+      {0x4767, 0x0f},
-+      {0x4750, 0x14},
-+      {0x4540, 0x00},
-+      {0x47b4, 0x14},
-+      {0x4713, 0x30},
-+      {0x478b, 0x10},
-+      {0x478f, 0x10},
-+      {0x4793, 0x10},
-+      {0x4797, 0x0e},
-+      {0x479b, 0x0e},
-+
-+      {0x0172, 0x03},
-+      {0x0162, 0x0d},
-+      {0x0163, 0x78},
-+};
-+
-+static const struct imx219_reg mode_1920_1080_regs[] = {
-+      {0x0100, 0x00},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x0c},
-+      {0x300a, 0xff},
-+      {0x300b, 0xff},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x09},
-+      {0x0114, 0x01},
-+      {0x0128, 0x00},
-+      {0x012a, 0x18},
-+      {0x012b, 0x00},
-+      {0x0162, 0x0d},
-+      {0x0163, 0x78},
-+      {0x0164, 0x02},
-+      {0x0165, 0xa8},
-+      {0x0166, 0x0a},
-+      {0x0167, 0x27},
-+      {0x0168, 0x02},
-+      {0x0169, 0xb4},
-+      {0x016a, 0x06},
-+      {0x016b, 0xeb},
-+      {0x016c, 0x07},
-+      {0x016d, 0x80},
-+      {0x016e, 0x04},
-+      {0x016f, 0x38},
-+      {0x0170, 0x01},
-+      {0x0171, 0x01},
-+      {0x0174, 0x00},
-+      {0x0175, 0x00},
-+      {0x018c, 0x0a},
-+      {0x018d, 0x0a},
-+      {0x0301, 0x05},
-+      {0x0303, 0x01},
-+      {0x0304, 0x03},
-+      {0x0305, 0x03},
-+      {0x0306, 0x00},
-+      {0x0307, 0x39},
-+      {0x0309, 0x0a},
-+      {0x030b, 0x01},
-+      {0x030c, 0x00},
-+      {0x030d, 0x72},
-+      {0x455e, 0x00},
-+      {0x471e, 0x4b},
-+      {0x4767, 0x0f},
-+      {0x4750, 0x14},
-+      {0x4540, 0x00},
-+      {0x47b4, 0x14},
-+      {0x4713, 0x30},
-+      {0x478b, 0x10},
-+      {0x478f, 0x10},
-+      {0x4793, 0x10},
-+      {0x4797, 0x0e},
-+      {0x479b, 0x0e},
-+
-+      {0x0172, 0x03},
-+      {0x0162, 0x0d},
-+      {0x0163, 0x78},
-+};
-+
-+static const struct imx219_reg mode_1640_1232_regs[] = {
-+      {0x30eb, 0x0c},
-+      {0x30eb, 0x05},
-+      {0x300a, 0xff},
-+      {0x300b, 0xff},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x09},
-+      {0x0114, 0x01},
-+      {0x0128, 0x00},
-+      {0x012a, 0x18},
-+      {0x012b, 0x00},
-+      {0x0164, 0x00},
-+      {0x0165, 0x00},
-+      {0x0166, 0x0c},
-+      {0x0167, 0xcf},
-+      {0x0168, 0x00},
-+      {0x0169, 0x00},
-+      {0x016a, 0x09},
-+      {0x016b, 0x9f},
-+      {0x016c, 0x06},
-+      {0x016d, 0x68},
-+      {0x016e, 0x04},
-+      {0x016f, 0xd0},
-+      {0x0170, 0x01},
-+      {0x0171, 0x01},
-+      {0x0174, 0x01},
-+      {0x0175, 0x01},
-+      {0x018c, 0x0a},
-+      {0x018d, 0x0a},
-+      {0x0301, 0x05},
-+      {0x0303, 0x01},
-+      {0x0304, 0x03},
-+      {0x0305, 0x03},
-+      {0x0306, 0x00},
-+      {0x0307, 0x39},
-+      {0x0309, 0x0a},
-+      {0x030b, 0x01},
-+      {0x030c, 0x00},
-+      {0x030d, 0x72},
-+      {0x455e, 0x00},
-+      {0x471e, 0x4b},
-+      {0x4767, 0x0f},
-+      {0x4750, 0x14},
-+      {0x4540, 0x00},
-+      {0x47b4, 0x14},
-+      {0x4713, 0x30},
-+      {0x478b, 0x10},
-+      {0x478f, 0x10},
-+      {0x4793, 0x10},
-+      {0x4797, 0x0e},
-+      {0x479b, 0x0e},
-+
-+      {0x0172, 0x03},
-+      {0x0162, 0x0d},
-+      {0x0163, 0x78},
-+};
-+
-+static const char * const imx219_test_pattern_menu[] = {
-+      "Disabled",
-+      "Color Bars",
-+      "Solid Color",
-+      "Grey Color Bars",
-+      "PN9"
-+};
-+
-+static const int imx219_test_pattern_val[] = {
-+      IMX219_TEST_PATTERN_DISABLE,
-+      IMX219_TEST_PATTERN_COLOR_BARS,
-+      IMX219_TEST_PATTERN_SOLID_COLOR,
-+      IMX219_TEST_PATTERN_GREY_COLOR,
-+      IMX219_TEST_PATTERN_PN9,
-+};
-+
-+/* regulator supplies */
-+static const char * const imx219_supply_name[] = {
-+      /* Supplies can be enabled in any order */
-+      "VANA",  /* Analog (2.8V) supply */
-+      "VDIG",  /* Digital Core (1.8V) supply */
-+      "VDDL",  /* IF (1.2V) supply */
-+};
-+
-+#define IMX219_NUM_SUPPLIES ARRAY_SIZE(imx219_supply_name)
-+
-+#define IMX219_XCLR_DELAY_MS 10       /* Initialisation delay after XCLR low->high */
-+
-+/* Mode configs */
-+static const struct imx219_mode supported_modes[] = {
-+      {
-+              /* 8MPix 15fps mode */
-+              .width = 3280,
-+              .height = 2464,
-+              .vts_def = IMX219_VTS_15FPS,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
-+                      .regs = mode_3280x2464_regs,
-+              },
-+      },
-+      {
-+              /* 1080P 30fps cropped */
-+              .width = 1920,
-+              .height = 1080,
-+              .vts_def = IMX219_VTS_30FPS_1080P,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
-+                      .regs = mode_1920_1080_regs,
-+              },
-+      },
-+      {
-+              /* 2x2 binned 30fps mode */
-+              .width = 1640,
-+              .height = 1232,
-+              .vts_def = IMX219_VTS_30FPS_BINNED,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
-+                      .regs = mode_1640_1232_regs,
-+              },
-+      },
-+};
-+
-+struct imx219 {
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+
-+      struct v4l2_fwnode_endpoint ep; /* the parsed DT endpoint info */
-+      struct clk *xclk; /* system clock to IMX219 */
-+      u32 xclk_freq;
-+
-+      struct gpio_desc *xclr_gpio;
-+      struct regulator_bulk_data supplies[IMX219_NUM_SUPPLIES];
-+
-+      struct v4l2_ctrl_handler ctrl_handler;
-+      /* V4L2 Controls */
-+      struct v4l2_ctrl *pixel_rate;
-+      struct v4l2_ctrl *exposure;
-+
-+      /* Current mode */
-+      const struct imx219_mode *mode;
-+
-+      /*
-+       * Mutex for serialized access:
-+       * Protect sensor module set pad format and start/stop streaming safely.
-+       */
-+      struct mutex mutex;
-+
-+      int power_count;
-+      /* Streaming on/off */
-+      bool streaming;
-+};
-+
-+static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
-+{
-+      return container_of(_sd, struct imx219, sd);
-+}
-+
-+/* Read registers up to 2 at a time */
-+static int imx219_read_reg(struct imx219 *imx219, u16 reg, u32 len, u32 *val)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      struct i2c_msg msgs[2];
-+      u8 addr_buf[2] = { reg >> 8, reg & 0xff };
-+      u8 data_buf[4] = { 0, };
-+      int ret;
-+
-+      if (len > 4)
-+              return -EINVAL;
-+
-+      /* 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 = len;
-+      msgs[1].buf = &data_buf[4 - len];
-+
-+      ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-+      if (ret != ARRAY_SIZE(msgs))
-+              return -EIO;
-+
-+      *val = get_unaligned_be32(data_buf);
-+
-+      return 0;
-+}
-+
-+/* Write registers up to 2 at a time */
-+static int imx219_write_reg(struct imx219 *imx219, u16 reg, u32 len, u32 val)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      u8 buf[6];
-+
-+      if (len > 4)
-+              return -EINVAL;
-+
-+      put_unaligned_be16(reg, buf);
-+      put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
-+      if (i2c_master_send(client, buf, len + 2) != len + 2)
-+              return -EIO;
-+
-+      return 0;
-+}
-+
-+/* Write a list of registers */
-+static int imx219_write_regs(struct imx219 *imx219,
-+                           const struct imx219_reg *regs, u32 len)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      unsigned int i;
-+      int ret;
-+
-+      for (i = 0; i < len; i++) {
-+              ret = imx219_write_reg(imx219, regs[i].address, 1, regs[i].val);
-+              if (ret) {
-+                      dev_err_ratelimited(&client->dev,
-+                                          "Failed to write reg 0x%4.4x. error = %d\n",
-+                                          regs[i].address, ret);
-+
-+                      return ret;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+/* Power/clock management functions */
-+static void imx219_power(struct imx219 *imx219, bool enable)
-+{
-+      gpiod_set_value_cansleep(imx219->xclr_gpio, enable ? 1 : 0);
-+}
-+
-+static int imx219_set_power_on(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int ret;
-+
-+      ret = clk_prepare_enable(imx219->xclk);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable clock\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES,
-+                                  imx219->supplies);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable regulators\n",
-+                      __func__);
-+              goto xclk_off;
-+      }
-+
-+      imx219_power(imx219, true);
-+      msleep(IMX219_XCLR_DELAY_MS);
-+
-+      return 0;
-+xclk_off:
-+      clk_disable_unprepare(imx219->xclk);
-+      return ret;
-+}
-+
-+static void imx219_set_power_off(struct imx219 *imx219)
-+{
-+      imx219_power(imx219, false);
-+      regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
-+      clk_disable_unprepare(imx219->xclk);
-+}
-+
-+static int imx219_set_power(struct imx219 *imx219, bool on)
-+{
-+      int ret = 0;
-+
-+      if (on) {
-+              ret = imx219_set_power_on(imx219);
-+              if (ret)
-+                      return ret;
-+      } else {
-+              imx219_set_power_off(imx219);
-+      }
-+
-+      return 0;
-+}
-+
-+/* Open sub-device */
-+static int imx219_s_power(struct v4l2_subdev *sd, int on)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&imx219->mutex);
-+
-+      /*
-+       * If the power count is modified from 0 to != 0 or from != 0 to 0,
-+       * update the power state.
-+       */
-+      if (imx219->power_count == !on) {
-+              ret = imx219_set_power(imx219, !!on);
-+              if (ret)
-+                      goto out;
-+      }
-+
-+      /* Update the power count. */
-+      imx219->power_count += on ? 1 : -1;
-+      WARN_ON(imx219->power_count < 0);
-+out:
-+      mutex_unlock(&imx219->mutex);
-+
-+      return ret;
-+}
-+
-+static int imx219_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-+{
-+      struct v4l2_mbus_framefmt *try_fmt =
-+              v4l2_subdev_get_try_format(sd, fh->pad, 0);
-+
-+      /* Initialize try_fmt */
-+      try_fmt->width = supported_modes[0].width;
-+      try_fmt->height = supported_modes[0].height;
-+      try_fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+      try_fmt->field = V4L2_FIELD_NONE;
-+
-+      return 0;
-+}
-+
-+static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct imx219 *imx219 =
-+              container_of(ctrl->handler, struct imx219, ctrl_handler);
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int ret = 0;
-+
-+      /*
-+       * Applying V4L2 control value only happens
-+       * when power is up for streaming
-+       */
-+      if (pm_runtime_get_if_in_use(&client->dev) == 0)
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_ANALOGUE_GAIN:
-+              ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN,
-+                                     IMX219_REG_VALUE_08BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE:
-+              ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE,
-+                                     IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_DIGITAL_GAIN:
-+              ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN,
-+                                     IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = imx219_write_reg(imx219, IMX219_REG_TEST_PATTERN,
-+                                     IMX219_REG_VALUE_16BIT,
-+                                     imx219_test_pattern_val[ctrl->val]);
-+              break;
-+      default:
-+              dev_info(&client->dev,
-+                       "ctrl(id:0x%x,val:0x%x) is not handled\n",
-+                       ctrl->id, ctrl->val);
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      pm_runtime_put(&client->dev);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops imx219_ctrl_ops = {
-+      .s_ctrl = imx219_set_ctrl,
-+};
-+
-+static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_pad_config *cfg,
-+                               struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      /* Only one bayer order(GRBG) is supported */
-+      if (code->index > 0)
-+              return -EINVAL;
-+
-+      code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+
-+      return 0;
-+}
-+
-+static int imx219_enum_frame_size(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_SBGGR10_1X10)
-+              return -EINVAL;
-+
-+      fse->min_width = supported_modes[fse->index].width;
-+      fse->max_width = fse->min_width;
-+      fse->min_height = supported_modes[fse->index].height;
-+      fse->max_height = fse->min_height;
-+
-+      return 0;
-+}
-+
-+static void imx219_update_pad_format(const struct imx219_mode *mode,
-+                                   struct v4l2_subdev_format *fmt)
-+{
-+      fmt->format.width = mode->width;
-+      fmt->format.height = mode->height;
-+      fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+      fmt->format.field = V4L2_FIELD_NONE;
-+}
-+
-+static int __imx219_get_pad_format(struct imx219 *imx219,
-+                                 struct v4l2_subdev_pad_config *cfg,
-+                                 struct v4l2_subdev_format *fmt)
-+{
-+      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt->format = *v4l2_subdev_get_try_format(&imx219->sd, cfg,
-+                                                        fmt->pad);
-+      else
-+              imx219_update_pad_format(imx219->mode, fmt);
-+
-+      return 0;
-+}
-+
-+static int imx219_get_pad_format(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_pad_config *cfg,
-+                               struct v4l2_subdev_format *fmt)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      int ret;
-+
-+      mutex_lock(&imx219->mutex);
-+      ret = __imx219_get_pad_format(imx219, cfg, fmt);
-+      mutex_unlock(&imx219->mutex);
-+
-+      return ret;
-+}
-+
-+static int imx219_set_pad_format(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_pad_config *cfg,
-+                               struct v4l2_subdev_format *fmt)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      const struct imx219_mode *mode;
-+      struct v4l2_mbus_framefmt *framefmt;
-+
-+      mutex_lock(&imx219->mutex);
-+
-+      /* Only one raw bayer(BGGR) order is supported */
-+      fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+
-+      mode = v4l2_find_nearest_size(supported_modes,
-+                                    ARRAY_SIZE(supported_modes),
-+                                    width, height,
-+                                    fmt->format.width, fmt->format.height);
-+      imx219_update_pad_format(mode, fmt);
-+      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-+              framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
-+              *framefmt = fmt->format;
-+      } else {
-+              imx219->mode = mode;
-+      }
-+
-+      mutex_unlock(&imx219->mutex);
-+
-+      return 0;
-+}
-+
-+/* Start streaming */
-+static int imx219_start_streaming(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      const struct imx219_reg_list *reg_list;
-+      int ret;
-+
-+      /* Apply default values of current mode */
-+      reg_list = &imx219->mode->reg_list;
-+      ret = imx219_write_regs(imx219, reg_list->regs, reg_list->num_of_regs);
-+      if (ret) {
-+              dev_err(&client->dev, "%s failed to set mode\n", __func__);
-+              return ret;
-+      }
-+
-+      /*
-+       * Set VTS appropriately for frame rate control.
-+       * Currently fixed per mode.
-+       */
-+      ret = imx219_write_reg(imx219, IMX219_REG_VTS,
-+                             IMX219_REG_VALUE_16BIT, imx219->mode->vts_def);
-+      if (ret)
-+              return ret;
-+
-+      /* Apply customized values from user */
-+      ret =  __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler);
-+      if (ret)
-+              return ret;
-+
-+      /* set stream on register */
-+      return imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-+                              IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING);
-+}
-+
-+/* Stop streaming */
-+static int imx219_stop_streaming(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int ret;
-+
-+      /* set stream off register */
-+      ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-+                             IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY);
-+      if (ret)
-+              dev_err(&client->dev, "%s failed to set stream\n", __func__);
-+
-+      /*
-+       * Return success even if it was an error, as there is nothing the
-+       * caller can do about it.
-+       */
-+      return 0;
-+}
-+
-+static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&imx219->mutex);
-+      if (imx219->streaming == enable) {
-+              mutex_unlock(&imx219->mutex);
-+              return 0;
-+      }
-+
-+      if (enable) {
-+              ret = pm_runtime_get_sync(&client->dev);
-+              if (ret < 0) {
-+                      pm_runtime_put_noidle(&client->dev);
-+                      goto err_unlock;
-+              }
-+
-+              /*
-+               * Apply default & customized values
-+               * and then start streaming.
-+               */
-+              ret = imx219_start_streaming(imx219);
-+              if (ret) {
-+                      pm_runtime_put(&client->dev);
-+                      goto err_unlock;
-+              }
-+      } else {
-+              imx219_stop_streaming(imx219);
-+              pm_runtime_put(&client->dev);
-+      }
-+
-+      imx219->streaming = enable;
-+      mutex_unlock(&imx219->mutex);
-+
-+      return ret;
-+
-+err_unlock:
-+      mutex_unlock(&imx219->mutex);
-+
-+      return ret;
-+}
-+
-+static int __maybe_unused imx219_suspend(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx219 *imx219 = to_imx219(sd);
-+
-+      if (imx219->streaming)
-+              imx219_stop_streaming(imx219);
-+
-+      return 0;
-+}
-+
-+static int __maybe_unused imx219_resume(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx219 *imx219 = to_imx219(sd);
-+      int ret;
-+
-+      if (imx219->streaming) {
-+              ret = imx219_start_streaming(imx219);
-+              if (ret)
-+                      goto error;
-+      }
-+
-+      return 0;
-+
-+error:
-+      imx219_stop_streaming(imx219);
-+      imx219->streaming = 0;
-+      return ret;
-+}
-+
-+static int imx219_get_regulators(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int i;
-+
-+      for (i = 0; i < IMX219_NUM_SUPPLIES; i++)
-+              imx219->supplies[i].supply = imx219_supply_name[i];
-+
-+      return devm_regulator_bulk_get(&client->dev,
-+                                     IMX219_NUM_SUPPLIES,
-+                                     imx219->supplies);
-+}
-+
-+/* Verify chip ID */
-+static int imx219_identify_module(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int ret;
-+      u32 val;
-+
-+      ret = imx219_set_power_on(imx219);
-+      if (ret)
-+              return ret;
-+
-+      ret = imx219_read_reg(imx219, IMX219_REG_CHIP_ID,
-+                            IMX219_REG_VALUE_16BIT, &val);
-+      if (ret) {
-+              dev_err(&client->dev, "failed to read chip id %x\n",
-+                      IMX219_CHIP_ID);
-+              goto power_off;
-+      }
-+
-+      if (val != IMX219_CHIP_ID) {
-+              dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
-+                      IMX219_CHIP_ID, val);
-+              ret = -EIO;
-+      }
-+
-+power_off:
-+      imx219_set_power_off(imx219);
-+      return ret;
-+}
-+
-+static const struct v4l2_subdev_core_ops imx219_core_ops = {
-+      .s_power = imx219_s_power,
-+};
-+
-+static const struct v4l2_subdev_video_ops imx219_video_ops = {
-+      .s_stream = imx219_set_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
-+      .enum_mbus_code = imx219_enum_mbus_code,
-+      .get_fmt = imx219_get_pad_format,
-+      .set_fmt = imx219_set_pad_format,
-+      .enum_frame_size = imx219_enum_frame_size,
-+};
-+
-+static const struct v4l2_subdev_ops imx219_subdev_ops = {
-+      .core = &imx219_core_ops,
-+      .video = &imx219_video_ops,
-+      .pad = &imx219_pad_ops,
-+};
-+
-+static const struct v4l2_subdev_internal_ops imx219_internal_ops = {
-+      .open = imx219_open,
-+};
-+
-+/* Initialize control handlers */
-+static int imx219_init_controls(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      struct v4l2_ctrl_handler *ctrl_hdlr;
-+      int ret;
-+
-+      ctrl_hdlr = &imx219->ctrl_handler;
-+      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);
-+      if (ret)
-+              return ret;
-+
-+      mutex_init(&imx219->mutex);
-+      ctrl_hdlr->lock = &imx219->mutex;
-+
-+      imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                                           V4L2_CID_EXPOSURE,
-+                                           IMX219_EXPOSURE_MIN,
-+                                           IMX219_EXPOSURE_MAX,
-+                                           IMX219_EXPOSURE_STEP,
-+                                           IMX219_EXPOSURE_DEFAULT);
-+
-+      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
-+                        IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX,
-+                        IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT);
-+
-+      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
-+                        IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX,
-+                        IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT);
-+
-+      v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops,
-+                                   V4L2_CID_TEST_PATTERN,
-+                                   ARRAY_SIZE(imx219_test_pattern_menu) - 1,
-+                                   0, 0, imx219_test_pattern_menu);
-+
-+      if (ctrl_hdlr->error) {
-+              ret = ctrl_hdlr->error;
-+              dev_err(&client->dev, "%s control init failed (%d)\n",
-+                      __func__, ret);
-+              goto error;
-+      }
-+
-+      imx219->sd.ctrl_handler = ctrl_hdlr;
-+
-+      return 0;
-+
-+error:
-+      v4l2_ctrl_handler_free(ctrl_hdlr);
-+      mutex_destroy(&imx219->mutex);
-+
-+      return ret;
-+}
-+
-+static void imx219_free_controls(struct imx219 *imx219)
-+{
-+      v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
-+      mutex_destroy(&imx219->mutex);
-+}
-+
-+static int imx219_probe(struct i2c_client *client,
-+                      const struct i2c_device_id *id)
-+{
-+      struct device *dev = &client->dev;
-+      struct fwnode_handle *endpoint;
-+      struct imx219 *imx219;
-+      int ret;
-+
-+      imx219 = devm_kzalloc(&client->dev, sizeof(*imx219), GFP_KERNEL);
-+      if (!imx219)
-+              return -ENOMEM;
-+
-+      /* Initialize subdev */
-+      v4l2_i2c_subdev_init(&imx219->sd, client, &imx219_subdev_ops);
-+
-+      /* Get CSI2 bus config */
-+      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
-+                                                NULL);
-+      if (!endpoint) {
-+              dev_err(dev, "endpoint node not found\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = v4l2_fwnode_endpoint_parse(endpoint, &imx219->ep);
-+      fwnode_handle_put(endpoint);
-+      if (ret) {
-+              dev_err(dev, "Could not parse endpoint\n");
-+              return ret;
-+      }
-+
-+      /* Get system clock (xclk) */
-+      imx219->xclk = devm_clk_get(dev, "xclk");
-+      if (IS_ERR(imx219->xclk)) {
-+              dev_err(dev, "failed to get xclk\n");
-+              return PTR_ERR(imx219->xclk);
-+      }
-+
-+      imx219->xclk_freq = clk_get_rate(imx219->xclk);
-+      if (imx219->xclk_freq != 24000000) {
-+              dev_err(dev, "xclk frequency not supported: %d Hz\n",
-+                      imx219->xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      ret = imx219_get_regulators(imx219);
-+      if (ret)
-+              return ret;
-+
-+      /* request optional power down pin */
-+      imx219->xclr_gpio = devm_gpiod_get_optional(dev, "xclr",
-+                                                  GPIOD_OUT_HIGH);
-+
-+      /* Check module identity */
-+      ret = imx219_identify_module(imx219);
-+      if (ret)
-+              return ret;
-+
-+      /* Set default mode to max resolution */
-+      imx219->mode = &supported_modes[0];
-+
-+      ret = imx219_init_controls(imx219);
-+      if (ret)
-+              return ret;
-+
-+      /* Initialize subdev */
-+      imx219->sd.internal_ops = &imx219_internal_ops;
-+      imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-+      imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+
-+      /* Initialize source pad */
-+      imx219->pad.flags = MEDIA_PAD_FL_SOURCE;
-+
-+      ret = media_entity_pads_init(&imx219->sd.entity, 1, &imx219->pad);
-+      if (ret)
-+              goto error_handler_free;
-+
-+      ret = v4l2_async_register_subdev_sensor_common(&imx219->sd);
-+      if (ret < 0)
-+              goto error_media_entity;
-+
-+      pm_runtime_set_active(&client->dev);
-+      pm_runtime_enable(&client->dev);
-+      pm_runtime_idle(&client->dev);
-+
-+      return 0;
-+
-+error_media_entity:
-+      media_entity_cleanup(&imx219->sd.entity);
-+
-+error_handler_free:
-+      imx219_free_controls(imx219);
-+
-+      return ret;
-+}
-+
-+static int imx219_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx219 *imx219 = to_imx219(sd);
-+
-+      v4l2_async_unregister_subdev(sd);
-+      media_entity_cleanup(&sd->entity);
-+      imx219_free_controls(imx219);
-+
-+      pm_runtime_disable(&client->dev);
-+      pm_runtime_set_suspended(&client->dev);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id imx219_dt_ids[] = {
-+      { .compatible = "sony,imx219" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, imx219_dt_ids);
-+
-+static struct i2c_driver imx219_i2c_driver = {
-+      .driver = {
-+              .name = "imx219",
-+              .of_match_table = imx219_dt_ids,
-+      },
-+      .probe = imx219_probe,
-+      .remove = imx219_remove,
-+};
-+
-+module_i2c_driver(imx219_i2c_driver);
-+
-+MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.org");
-+MODULE_DESCRIPTION("Sony IMX219 sensor driver");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0680-staging-bcm2835-codec-Fix-non-documentation-comment-.patch b/target/linux/brcm2708/patches-4.19/950-0680-staging-bcm2835-codec-Fix-non-documentation-comment-.patch
new file mode 100644 (file)
index 0000000..116d168
--- /dev/null
@@ -0,0 +1,27 @@
+From d4fc8b1d50522b416baeb1d1f5e5498000af5a7f Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Sun, 28 Apr 2019 12:15:35 +0200
+Subject: [PATCH] staging: bcm2835-codec: Fix non-documentation comment
+ block
+
+The job_ready comment is incorrectly using the documentation prefix
+(/**) which causes a warning at build time.
+
+Simplify it.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.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
+@@ -557,7 +557,7 @@ static struct vchiq_mmal_port *get_port_
+  * mem2mem callbacks
+  */
+-/**
++/*
+  * job_ready() - check whether an instance is ready to be scheduled to run
+  */
+ static int job_ready(void *priv)
diff --git a/target/linux/brcm2708/patches-4.19/950-0681-dtoverlays-Add-overlay-for-the-Sony-IMX219-image-sen.patch b/target/linux/brcm2708/patches-4.19/950-0681-dtoverlays-Add-overlay-for-the-Sony-IMX219-image-sen.patch
deleted file mode 100644 (file)
index 9be42a6..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-From 7a4d12054b24c8cb980be4c6466b50c14beb78d3 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 28 Aug 2019 13:35:19 +0100
-Subject: [PATCH] dtoverlays: Add overlay for the Sony IMX219 image
- sensor.
-
-Adds an overlay for the IMX219 image sensor, connected to the
-Unicam CSI2 receiver peripheral.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |  12 ++
- arch/arm/boot/dts/overlays/imx219-overlay.dts | 129 ++++++++++++++++++
- 3 files changed, 142 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/imx219-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -77,6 +77,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       i2c6.dtbo \
-       i2s-gpio28-31.dtbo \
-       ilitek251x.dtbo \
-+      imx219.dtbo \
-       iqaudio-codec.dtbo \
-       iqaudio-dac.dtbo \
-       iqaudio-dacplus.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1269,6 +1269,18 @@ Params: interrupt               GPIO use
-                                 touchscreen (in pixels)
-+Name:   imx219
-+Info:   Sony IMX219 camera module.
-+        Uses Unicam 1, which is the standard camera connector on most Pi
-+        variants.
-+Load:   dtoverlay=imx219,<param>=<val>
-+Params: i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
-+                                Useful on Compute Modules.
-+
-+        i2c_pins_28_29          Use pins 28&29 for the I2C instead of 44&45.
-+                                This is required for Pi B+, 2, 0, and 0W.
-+
-+
- Name:   iqaudio-codec
- Info:   Configures the IQaudio Codec audio card
- Load:   dtoverlay=iqaudio-codec
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/imx219-overlay.dts
-@@ -0,0 +1,129 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+// Definitions for IMX219 camera module on VC I2C bus
-+/dts-v1/;
-+/plugin/;
-+
-+#include <dt-bindings/gpio/gpio.h>
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&i2c_vc>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      imx219: imx219@10 {
-+                              compatible = "sony,imx219";
-+                              reg = <0x10>;
-+                              status = "okay";
-+
-+                              clocks = <&imx219_clk>;
-+                              clock-names = "xclk";
-+
-+                              VANA-supply = <&imx219_vana>;   /* 2.8v */
-+                              VDIG-supply = <&imx219_vdig>;   /* 1.8v */
-+                              VDDL-supply = <&imx219_vddl>;   /* 1.2v */
-+
-+                              imx219_clk: camera-clk {
-+                                      compatible = "fixed-clock";
-+                                      #clock-cells = <0>;
-+                                      clock-frequency = <24000000>;
-+                              };
-+
-+                              port {
-+                                      imx219_0: endpoint {
-+                                              remote-endpoint = <&csi1_ep>;
-+                                              clock-lanes = <0>;
-+                                              data-lanes = <1 2>;
-+                                              clock-noncontinuous;
-+                                              link-frequencies =
-+                                                      /bits/ 64 <297000000>;
-+                                      };
-+                              };
-+                      };
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&csi1>;
-+              __overlay__ {
-+                      status = "okay";
-+
-+                      port {
-+                              csi1_ep: endpoint {
-+                                      remote-endpoint = <&imx219_0>;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&i2c0_pins>;
-+              __dormant__ {
-+                      brcm,pins = <28 29>;
-+                      brcm,function = <4>; /* alt0 */
-+              };
-+      };
-+      fragment@3 {
-+              target = <&i2c0_pins>;
-+              __overlay__ {
-+                      brcm,pins = <44 45>;
-+                      brcm,function = <5>; /* alt1 */
-+              };
-+      };
-+      fragment@4 {
-+              target = <&i2c0_pins>;
-+              __dormant__ {
-+                      brcm,pins = <0 1>;
-+                      brcm,function = <4>; /* alt0 */
-+              };
-+      };
-+      fragment@5 {
-+              target = <&i2c_vc>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@6 {
-+              target-path="/";
-+              __overlay__ {
-+                      imx219_vana: fixedregulator@0 {
-+                              compatible = "regulator-fixed";
-+                              regulator-name = "imx219_vana";
-+                              regulator-min-microvolt = <2800000>;
-+                              regulator-max-microvolt = <2800000>;
-+                              gpio = <&gpio 41 GPIO_ACTIVE_HIGH>;
-+                              enable-active-high;
-+                      };
-+                      imx219_vdig: fixedregulator@1 {
-+                              compatible = "regulator-fixed";
-+                              regulator-name = "imx219_vdig";
-+                              regulator-min-microvolt = <1800000>;
-+                              regulator-max-microvolt = <1800000>;
-+                      };
-+                      imx219_vddl: fixedregulator@2 {
-+                              compatible = "regulator-fixed";
-+                              regulator-name = "imx219_vddl";
-+                              regulator-min-microvolt = <1200000>;
-+                              regulator-max-microvolt = <1200000>;
-+                      };
-+              };
-+      };
-+
-+      fragment@7 {
-+              target-path="/__overrides__";
-+              __overlay__ {
-+                      cam0-pwdn-ctrl = <&imx219_vana>,"gpio:0";
-+                      cam0-pwdn      = <&imx219_vana>,"gpio:4";
-+              };
-+      };
-+
-+      __overrides__ {
-+              i2c_pins_0_1 = <0>,"-2-3+4";
-+              i2c_pins_28_29 = <0>,"+2-3-4";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0681-staging-bcm2835-codec-Fix-declaration-of-roles.patch b/target/linux/brcm2708/patches-4.19/950-0681-staging-bcm2835-codec-Fix-declaration-of-roles.patch
new file mode 100644 (file)
index 0000000..05ea839
--- /dev/null
@@ -0,0 +1,26 @@
+From 2d17824e8e5b2b6a6b830b8fe26c71a7d396f760 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Wed, 20 Mar 2019 11:42:39 +0000
+Subject: [PATCH] staging: bcm2835-codec: Fix declaration of roles
+
+The static role text is declared incorrectly. The static should be
+first, and the roles should also be constified.
+
+Convert from "const static char *" to "static const char * const".
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.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
+@@ -77,7 +77,7 @@ enum bcm2835_codec_role {
+       ISP,
+ };
+-const static char *roles[] = {
++static const char * const roles[] = {
+       "decode",
+       "encode",
+       "isp"
diff --git a/target/linux/brcm2708/patches-4.19/950-0682-staging-bcm2835-codec-Add-role-to-device-name.patch b/target/linux/brcm2708/patches-4.19/950-0682-staging-bcm2835-codec-Add-role-to-device-name.patch
new file mode 100644 (file)
index 0000000..4afdf8c
--- /dev/null
@@ -0,0 +1,45 @@
+From ca613ed735fc52e68189d2ad0880f1007b931d78 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Wed, 20 Mar 2019 11:55:43 +0000
+Subject: [PATCH] staging: bcm2835-codec: Add role to device name
+
+Three entities are created, Decode, Encode and ISP but all of the video
+nodes use the same video name string "bcm2835-codec" which makes it
+difficult to identify each role.
+
+Append the role-name to the video name to facilitate identifying a
+specific instance from userspace.
+
+The Card-Type is also extended with the role name to support identifying
+the device context from within QUERY_CAP operations.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c      | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -947,8 +947,10 @@ static void device_run(void *priv)
+ static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+ {
++      struct bcm2835_codec_dev *dev = video_drvdata(file);
++
+       strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
+-      strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
++      strncpy(cap->card, dev->vfd.name, sizeof(cap->card) - 1);
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                MEM2MEM_NAME);
+       return 0;
+@@ -2657,8 +2659,8 @@ static int bcm2835_codec_create(struct p
+       }
+       video_set_drvdata(vfd, dev);
+-      snprintf(vfd->name, sizeof(vfd->name), "%s",
+-               bcm2835_codec_videodev.name);
++      snprintf(vfd->name, sizeof(vfd->name), "%s-%s",
++               bcm2835_codec_videodev.name, roles[role]);
+       v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
+                 vfd->num);
diff --git a/target/linux/brcm2708/patches-4.19/950-0682-staging-bcm2835-codec-Fix-non-documentation-comment-.patch b/target/linux/brcm2708/patches-4.19/950-0682-staging-bcm2835-codec-Fix-non-documentation-comment-.patch
deleted file mode 100644 (file)
index 116d168..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From d4fc8b1d50522b416baeb1d1f5e5498000af5a7f Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Sun, 28 Apr 2019 12:15:35 +0200
-Subject: [PATCH] staging: bcm2835-codec: Fix non-documentation comment
- block
-
-The job_ready comment is incorrectly using the documentation prefix
-(/**) which causes a warning at build time.
-
-Simplify it.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.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
-@@ -557,7 +557,7 @@ static struct vchiq_mmal_port *get_port_
-  * mem2mem callbacks
-  */
--/**
-+/*
-  * job_ready() - check whether an instance is ready to be scheduled to run
-  */
- static int job_ready(void *priv)
diff --git a/target/linux/brcm2708/patches-4.19/950-0683-staging-bcm2835-codec-Fix-declaration-of-roles.patch b/target/linux/brcm2708/patches-4.19/950-0683-staging-bcm2835-codec-Fix-declaration-of-roles.patch
deleted file mode 100644 (file)
index 05ea839..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 2d17824e8e5b2b6a6b830b8fe26c71a7d396f760 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Wed, 20 Mar 2019 11:42:39 +0000
-Subject: [PATCH] staging: bcm2835-codec: Fix declaration of roles
-
-The static role text is declared incorrectly. The static should be
-first, and the roles should also be constified.
-
-Convert from "const static char *" to "static const char * const".
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.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
-@@ -77,7 +77,7 @@ enum bcm2835_codec_role {
-       ISP,
- };
--const static char *roles[] = {
-+static const char * const roles[] = {
-       "decode",
-       "encode",
-       "isp"
diff --git a/target/linux/brcm2708/patches-4.19/950-0683-staging-bcm2835-codec-Pass-driver-context-to-create-.patch b/target/linux/brcm2708/patches-4.19/950-0683-staging-bcm2835-codec-Pass-driver-context-to-create-.patch
new file mode 100644 (file)
index 0000000..083e75b
--- /dev/null
@@ -0,0 +1,61 @@
+From 9243f7de67345adfcac52198f78bd12cfebb6867 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Wed, 20 Mar 2019 11:35:26 +0000
+Subject: [PATCH] staging: bcm2835-codec: Pass driver context to create
+ entities
+
+Pass the bcm2835_codec_driver driver context directly into the
+bcm2835_codec_create() so that it can be used to store driver global
+state. Pass the struct platform_device *pdev by adding it to the driver
+global state.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c              | 13 +++++++++----
+ 1 file changed, 9 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
+@@ -457,6 +457,8 @@ struct bcm2835_codec_ctx {
+ };
+ struct bcm2835_codec_driver {
++      struct platform_device *pdev;
++
+       struct bcm2835_codec_dev *encode;
+       struct bcm2835_codec_dev *decode;
+       struct bcm2835_codec_dev *isp;
+@@ -2587,10 +2589,11 @@ destroy_component:
+       return ret;
+ }
+-static int bcm2835_codec_create(struct platform_device *pdev,
++static int bcm2835_codec_create(struct bcm2835_codec_driver *drv,
+                               struct bcm2835_codec_dev **new_dev,
+                               enum bcm2835_codec_role role)
+ {
++      struct platform_device *pdev = drv->pdev;
+       struct bcm2835_codec_dev *dev;
+       struct video_device *vfd;
+       int video_nr;
+@@ -2711,15 +2714,17 @@ static int bcm2835_codec_probe(struct pl
+       if (!drv)
+               return -ENOMEM;
+-      ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
++      drv->pdev = pdev;
++
++      ret = bcm2835_codec_create(drv, &drv->decode, DECODE);
+       if (ret)
+               goto out;
+-      ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
++      ret = bcm2835_codec_create(drv, &drv->encode, ENCODE);
+       if (ret)
+               goto out;
+-      ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
++      ret = bcm2835_codec_create(drv, &drv->isp, ISP);
+       if (ret)
+               goto out;
diff --git a/target/linux/brcm2708/patches-4.19/950-0684-staging-bcm2835-codec-Add-role-to-device-name.patch b/target/linux/brcm2708/patches-4.19/950-0684-staging-bcm2835-codec-Add-role-to-device-name.patch
deleted file mode 100644 (file)
index 4afdf8c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From ca613ed735fc52e68189d2ad0880f1007b931d78 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Wed, 20 Mar 2019 11:55:43 +0000
-Subject: [PATCH] staging: bcm2835-codec: Add role to device name
-
-Three entities are created, Decode, Encode and ISP but all of the video
-nodes use the same video name string "bcm2835-codec" which makes it
-difficult to identify each role.
-
-Append the role-name to the video name to facilitate identifying a
-specific instance from userspace.
-
-The Card-Type is also extended with the role name to support identifying
-the device context from within QUERY_CAP operations.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c      | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -947,8 +947,10 @@ static void device_run(void *priv)
- static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
- {
-+      struct bcm2835_codec_dev *dev = video_drvdata(file);
-+
-       strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
--      strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-+      strncpy(cap->card, dev->vfd.name, sizeof(cap->card) - 1);
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                MEM2MEM_NAME);
-       return 0;
-@@ -2657,8 +2659,8 @@ static int bcm2835_codec_create(struct p
-       }
-       video_set_drvdata(vfd, dev);
--      snprintf(vfd->name, sizeof(vfd->name), "%s",
--               bcm2835_codec_videodev.name);
-+      snprintf(vfd->name, sizeof(vfd->name), "%s-%s",
-+               bcm2835_codec_videodev.name, roles[role]);
-       v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
-                 vfd->num);
diff --git a/target/linux/brcm2708/patches-4.19/950-0684-staging-bcm2835-codec-add-media-controller-support.patch b/target/linux/brcm2708/patches-4.19/950-0684-staging-bcm2835-codec-add-media-controller-support.patch
new file mode 100644 (file)
index 0000000..a42fa7d
--- /dev/null
@@ -0,0 +1,163 @@
+From d1ceb85b7c6c7c3eec8b424e0172c29e93a570f2 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Wed, 20 Mar 2019 12:54:15 +0000
+Subject: [PATCH] staging: bcm2835-codec: add media controller support
+
+Provide a single media device to contain all of the bcm2835_codec
+devices created.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ .../vc04_services/bcm2835-codec/Kconfig       |  2 +-
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 41 +++++++++++++++++--
+ 2 files changed, 38 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/Kconfig
++++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
+@@ -1,6 +1,6 @@
+ config VIDEO_CODEC_BCM2835
+       tristate "BCM2835 Video codec support"
+-      depends on MEDIA_SUPPORT
++      depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
+       depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
+       select BCM2835_VCHIQ_MMAL
+       select VIDEOBUF2_DMA_CONTIG
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -458,6 +458,7 @@ struct bcm2835_codec_ctx {
+ struct bcm2835_codec_driver {
+       struct platform_device *pdev;
++      struct media_device     mdev;
+       struct bcm2835_codec_dev *encode;
+       struct bcm2835_codec_dev *decode;
+@@ -2596,6 +2597,7 @@ static int bcm2835_codec_create(struct b
+       struct platform_device *pdev = drv->pdev;
+       struct bcm2835_codec_dev *dev;
+       struct video_device *vfd;
++      int function;
+       int video_nr;
+       int ret;
+@@ -2615,18 +2617,21 @@ static int bcm2835_codec_create(struct b
+       if (ret)
+               goto vchiq_finalise;
+-      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+-      if (ret)
+-              goto vchiq_finalise;
+-
+       atomic_set(&dev->num_inst, 0);
+       mutex_init(&dev->dev_mutex);
++      /* Initialise the video device */
+       dev->vfd = bcm2835_codec_videodev;
++
+       vfd = &dev->vfd;
+       vfd->lock = &dev->dev_mutex;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+       vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
++      vfd->v4l2_dev->mdev = &drv->mdev;
++
++      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++      if (ret)
++              goto vchiq_finalise;
+       switch (role) {
+       case DECODE:
+@@ -2634,11 +2639,13 @@ static int bcm2835_codec_create(struct b
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
+               v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
++              function = MEDIA_ENT_F_PROC_VIDEO_DECODER;
+               video_nr = decode_video_nr;
+               break;
+       case ENCODE:
+               v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
++              function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
+               video_nr = encode_video_nr;
+               break;
+       case ISP:
+@@ -2648,6 +2655,7 @@ static int bcm2835_codec_create(struct b
+               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
+               v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
+               v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
++              function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
+               video_nr = isp_video_nr;
+               break;
+       default:
+@@ -2676,6 +2684,10 @@ static int bcm2835_codec_create(struct b
+               goto err_m2m;
+       }
++      ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, function);
++      if (ret)
++              goto err_m2m;
++
+       v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
+                 roles[role]);
+       return 0;
+@@ -2697,6 +2709,7 @@ static int bcm2835_codec_destroy(struct
+       v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
+                 roles[dev->role]);
++      v4l2_m2m_unregister_media_controller(dev->m2m_dev);
+       v4l2_m2m_release(dev->m2m_dev);
+       video_unregister_device(&dev->vfd);
+       v4l2_device_unregister(&dev->v4l2_dev);
+@@ -2708,6 +2721,7 @@ static int bcm2835_codec_destroy(struct
+ static int bcm2835_codec_probe(struct platform_device *pdev)
+ {
+       struct bcm2835_codec_driver *drv;
++      struct media_device *mdev;
+       int ret = 0;
+       drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+@@ -2715,6 +2729,17 @@ static int bcm2835_codec_probe(struct pl
+               return -ENOMEM;
+       drv->pdev = pdev;
++      mdev = &drv->mdev;
++      mdev->dev = &pdev->dev;
++
++      strscpy(mdev->model, bcm2835_codec_videodev.name, sizeof(mdev->model));
++      strscpy(mdev->serial, "0000", sizeof(mdev->serial));
++      snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
++               pdev->name);
++
++      /* This should return the vgencmd version information or such .. */
++      mdev->hw_revision = 1;
++      media_device_init(mdev);
+       ret = bcm2835_codec_create(drv, &drv->decode, DECODE);
+       if (ret)
+@@ -2728,6 +2753,10 @@ static int bcm2835_codec_probe(struct pl
+       if (ret)
+               goto out;
++      /* Register the media device node */
++      if (media_device_register(mdev) < 0)
++              goto out;
++
+       platform_set_drvdata(pdev, drv);
+       return 0;
+@@ -2748,12 +2777,16 @@ static int bcm2835_codec_remove(struct p
+ {
+       struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
++      media_device_unregister(&drv->mdev);
++
+       bcm2835_codec_destroy(drv->isp);
+       bcm2835_codec_destroy(drv->encode);
+       bcm2835_codec_destroy(drv->decode);
++      media_device_cleanup(&drv->mdev);
++
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0685-media-bcm2835-unicam-Reduce-scope-of-local-function.patch b/target/linux/brcm2708/patches-4.19/950-0685-media-bcm2835-unicam-Reduce-scope-of-local-function.patch
new file mode 100644 (file)
index 0000000..1e9d4b4
--- /dev/null
@@ -0,0 +1,29 @@
+From 4924b7b5517c9c334cf5faa3c7a29adf9a0c0ba1 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Wed, 28 Aug 2019 15:54:19 +0100
+Subject: [PATCH] media: bcm2835: unicam: Reduce scope of local
+ function
+
+unicam_start_rx() is not used outside of the unicam module.  Its current
+definition produces a compiler warning, that no function prototype
+exists.
+
+As the function is only used within the local scope of the module,
+convert it to a static function.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.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
+@@ -963,7 +963,7 @@ static void unicam_cfg_image_id(struct u
+       }
+ }
+-void unicam_start_rx(struct unicam_device *dev, unsigned long addr)
++static void unicam_start_rx(struct unicam_device *dev, unsigned long addr)
+ {
+       struct unicam_cfg *cfg = &dev->cfg;
+       int line_int_freq = dev->v_fmt.fmt.pix.height >> 2;
diff --git a/target/linux/brcm2708/patches-4.19/950-0685-staging-bcm2835-codec-Pass-driver-context-to-create-.patch b/target/linux/brcm2708/patches-4.19/950-0685-staging-bcm2835-codec-Pass-driver-context-to-create-.patch
deleted file mode 100644 (file)
index 083e75b..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From 9243f7de67345adfcac52198f78bd12cfebb6867 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Wed, 20 Mar 2019 11:35:26 +0000
-Subject: [PATCH] staging: bcm2835-codec: Pass driver context to create
- entities
-
-Pass the bcm2835_codec_driver driver context directly into the
-bcm2835_codec_create() so that it can be used to store driver global
-state. Pass the struct platform_device *pdev by adding it to the driver
-global state.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c              | 13 +++++++++----
- 1 file changed, 9 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
-@@ -457,6 +457,8 @@ struct bcm2835_codec_ctx {
- };
- struct bcm2835_codec_driver {
-+      struct platform_device *pdev;
-+
-       struct bcm2835_codec_dev *encode;
-       struct bcm2835_codec_dev *decode;
-       struct bcm2835_codec_dev *isp;
-@@ -2587,10 +2589,11 @@ destroy_component:
-       return ret;
- }
--static int bcm2835_codec_create(struct platform_device *pdev,
-+static int bcm2835_codec_create(struct bcm2835_codec_driver *drv,
-                               struct bcm2835_codec_dev **new_dev,
-                               enum bcm2835_codec_role role)
- {
-+      struct platform_device *pdev = drv->pdev;
-       struct bcm2835_codec_dev *dev;
-       struct video_device *vfd;
-       int video_nr;
-@@ -2711,15 +2714,17 @@ static int bcm2835_codec_probe(struct pl
-       if (!drv)
-               return -ENOMEM;
--      ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
-+      drv->pdev = pdev;
-+
-+      ret = bcm2835_codec_create(drv, &drv->decode, DECODE);
-       if (ret)
-               goto out;
--      ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
-+      ret = bcm2835_codec_create(drv, &drv->encode, ENCODE);
-       if (ret)
-               goto out;
--      ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
-+      ret = bcm2835_codec_create(drv, &drv->isp, ISP);
-       if (ret)
-               goto out;
diff --git a/target/linux/brcm2708/patches-4.19/950-0686-media-bcm2835-unicam-add-media-controller-support.patch b/target/linux/brcm2708/patches-4.19/950-0686-media-bcm2835-unicam-add-media-controller-support.patch
new file mode 100644 (file)
index 0000000..e847212
--- /dev/null
@@ -0,0 +1,128 @@
+From 06cd9857f8faa63321506a75988c475906a32970 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Wed, 20 Mar 2019 12:54:47 +0000
+Subject: [PATCH] media: bcm2835: unicam: add media controller support
+
+Add a media controller device node to represent the Unicam device.
+The attached sensor will be automatically added to the media graph by
+V4L2 core.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/media/platform/bcm2835/Kconfig        |  2 +-
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 46 ++++++++++++++++++-
+ 2 files changed, 45 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/Kconfig
++++ b/drivers/media/platform/bcm2835/Kconfig
+@@ -2,7 +2,7 @@
+ config VIDEO_BCM2835_UNICAM
+       tristate "Broadcom BCM2835 Unicam video capture driver"
+-      depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
++      depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+       depends on ARCH_BCM2835 || COMPILE_TEST
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_FWNODE
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -314,6 +314,9 @@ struct unicam_device {
+       struct clk *clock;
+       /* V4l2 device */
+       struct v4l2_device v4l2_dev;
++      struct media_device mdev;
++      struct media_pad pad;
++
+       /* parent device */
+       struct platform_device *pdev;
+       /* subdevice async Notifier */
+@@ -1912,6 +1915,8 @@ static int unicam_probe_complete(struct
+               unicam->v4l2_dev.ctrl_handler = NULL;
+       video_set_drvdata(vdev, unicam);
++      vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
++
+       ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+       if (ret) {
+               unicam_err(unicam, "Unable to register video device.\n");
+@@ -1953,6 +1958,16 @@ static int unicam_probe_complete(struct
+               return ret;
+       }
++      ret = media_create_pad_link(&unicam->sensor->entity, 0,
++                                  &unicam->video_dev.entity, 0,
++                                  MEDIA_LNK_FL_ENABLED |
++                                  MEDIA_LNK_FL_IMMUTABLE);
++      if (ret) {
++              unicam_err(unicam, "Unable to create pad links.\n");
++              video_unregister_device(&unicam->video_dev);
++              return ret;
++      }
++
+       return 0;
+ }
+@@ -2155,18 +2170,38 @@ static int unicam_probe(struct platform_
+               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", pdev->name);
++      unicam->mdev.hw_revision = 1;
++
++      media_entity_pads_init(&unicam->video_dev.entity, 1, &unicam->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");
+-              return ret;
++              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->ctrl_handler;
+       ret = v4l2_ctrl_handler_init(hdl, 16);
+       if (ret < 0)
+-              goto probe_out_v4l2_unregister;
++              goto media_unregister;
+       unicam->v4l2_dev.ctrl_handler = hdl;
+       /* set the driver data in platform device */
+@@ -2185,8 +2220,13 @@ static int unicam_probe(struct platform_
+ 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;
+ }
+@@ -2204,6 +2244,8 @@ static int unicam_remove(struct platform
+       video_unregister_device(&unicam->video_dev);
+       if (unicam->sensor_config)
+               v4l2_subdev_free_pad_config(unicam->sensor_config);
++      media_device_unregister(&unicam->mdev);
++      media_device_cleanup(&unicam->mdev);
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0686-staging-bcm2835-codec-add-media-controller-support.patch b/target/linux/brcm2708/patches-4.19/950-0686-staging-bcm2835-codec-add-media-controller-support.patch
deleted file mode 100644 (file)
index a42fa7d..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-From d1ceb85b7c6c7c3eec8b424e0172c29e93a570f2 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Wed, 20 Mar 2019 12:54:15 +0000
-Subject: [PATCH] staging: bcm2835-codec: add media controller support
-
-Provide a single media device to contain all of the bcm2835_codec
-devices created.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- .../vc04_services/bcm2835-codec/Kconfig       |  2 +-
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 41 +++++++++++++++++--
- 2 files changed, 38 insertions(+), 5 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/Kconfig
-+++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
-@@ -1,6 +1,6 @@
- config VIDEO_CODEC_BCM2835
-       tristate "BCM2835 Video codec support"
--      depends on MEDIA_SUPPORT
-+      depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
-       depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
-       select BCM2835_VCHIQ_MMAL
-       select VIDEOBUF2_DMA_CONTIG
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -458,6 +458,7 @@ struct bcm2835_codec_ctx {
- struct bcm2835_codec_driver {
-       struct platform_device *pdev;
-+      struct media_device     mdev;
-       struct bcm2835_codec_dev *encode;
-       struct bcm2835_codec_dev *decode;
-@@ -2596,6 +2597,7 @@ static int bcm2835_codec_create(struct b
-       struct platform_device *pdev = drv->pdev;
-       struct bcm2835_codec_dev *dev;
-       struct video_device *vfd;
-+      int function;
-       int video_nr;
-       int ret;
-@@ -2615,18 +2617,21 @@ static int bcm2835_codec_create(struct b
-       if (ret)
-               goto vchiq_finalise;
--      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
--      if (ret)
--              goto vchiq_finalise;
--
-       atomic_set(&dev->num_inst, 0);
-       mutex_init(&dev->dev_mutex);
-+      /* Initialise the video device */
-       dev->vfd = bcm2835_codec_videodev;
-+
-       vfd = &dev->vfd;
-       vfd->lock = &dev->dev_mutex;
-       vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-+      vfd->v4l2_dev->mdev = &drv->mdev;
-+
-+      ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-+      if (ret)
-+              goto vchiq_finalise;
-       switch (role) {
-       case DECODE:
-@@ -2634,11 +2639,13 @@ static int bcm2835_codec_create(struct b
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-               v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
-+              function = MEDIA_ENT_F_PROC_VIDEO_DECODER;
-               video_nr = decode_video_nr;
-               break;
-       case ENCODE:
-               v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-+              function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
-               video_nr = encode_video_nr;
-               break;
-       case ISP:
-@@ -2648,6 +2655,7 @@ static int bcm2835_codec_create(struct b
-               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-               v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-               v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
-+              function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
-               video_nr = isp_video_nr;
-               break;
-       default:
-@@ -2676,6 +2684,10 @@ static int bcm2835_codec_create(struct b
-               goto err_m2m;
-       }
-+      ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, function);
-+      if (ret)
-+              goto err_m2m;
-+
-       v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
-                 roles[role]);
-       return 0;
-@@ -2697,6 +2709,7 @@ static int bcm2835_codec_destroy(struct
-       v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
-                 roles[dev->role]);
-+      v4l2_m2m_unregister_media_controller(dev->m2m_dev);
-       v4l2_m2m_release(dev->m2m_dev);
-       video_unregister_device(&dev->vfd);
-       v4l2_device_unregister(&dev->v4l2_dev);
-@@ -2708,6 +2721,7 @@ static int bcm2835_codec_destroy(struct
- static int bcm2835_codec_probe(struct platform_device *pdev)
- {
-       struct bcm2835_codec_driver *drv;
-+      struct media_device *mdev;
-       int ret = 0;
-       drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
-@@ -2715,6 +2729,17 @@ static int bcm2835_codec_probe(struct pl
-               return -ENOMEM;
-       drv->pdev = pdev;
-+      mdev = &drv->mdev;
-+      mdev->dev = &pdev->dev;
-+
-+      strscpy(mdev->model, bcm2835_codec_videodev.name, sizeof(mdev->model));
-+      strscpy(mdev->serial, "0000", sizeof(mdev->serial));
-+      snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
-+               pdev->name);
-+
-+      /* This should return the vgencmd version information or such .. */
-+      mdev->hw_revision = 1;
-+      media_device_init(mdev);
-       ret = bcm2835_codec_create(drv, &drv->decode, DECODE);
-       if (ret)
-@@ -2728,6 +2753,10 @@ static int bcm2835_codec_probe(struct pl
-       if (ret)
-               goto out;
-+      /* Register the media device node */
-+      if (media_device_register(mdev) < 0)
-+              goto out;
-+
-       platform_set_drvdata(pdev, drv);
-       return 0;
-@@ -2748,12 +2777,16 @@ static int bcm2835_codec_remove(struct p
- {
-       struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
-+      media_device_unregister(&drv->mdev);
-+
-       bcm2835_codec_destroy(drv->isp);
-       bcm2835_codec_destroy(drv->encode);
-       bcm2835_codec_destroy(drv->decode);
-+      media_device_cleanup(&drv->mdev);
-+
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0687-Limit-max_req_size-under-arm64-or-any-other-platform.patch b/target/linux/brcm2708/patches-4.19/950-0687-Limit-max_req_size-under-arm64-or-any-other-platform.patch
new file mode 100644 (file)
index 0000000..87b4e9b
--- /dev/null
@@ -0,0 +1,33 @@
+From 7bfcb31431f06efc233e4cc4d7ab65e10a6522cd Mon Sep 17 00:00:00 2001
+From: Yaroslav Rosomakho <yaroslavros@gmail.com>
+Date: Fri, 23 Aug 2019 11:02:22 +0200
+Subject: [PATCH] Limit max_req_size under arm64 (or any other platform
+ that uses swiotlb) to prevent potential buffer overflow due to bouncing.
+
+Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -38,6 +38,7 @@
+ #include <linux/dmaengine.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/of_dma.h>
++#include <linux/swiotlb.h>
+ #include "sdhci.h"
+@@ -1374,7 +1375,10 @@ static int bcm2835_mmc_add_host(struct b
+       }
+ #endif
+       mmc->max_segs = 128;
+-      mmc->max_req_size = 524288;
++      if (swiotlb_max_segment())
++              mmc->max_req_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE;
++      else
++              mmc->max_req_size = 524288;
+       mmc->max_seg_size = mmc->max_req_size;
+       mmc->max_blk_size = 512;
+       mmc->max_blk_count =  65535;
diff --git a/target/linux/brcm2708/patches-4.19/950-0687-media-bcm2835-unicam-Reduce-scope-of-local-function.patch b/target/linux/brcm2708/patches-4.19/950-0687-media-bcm2835-unicam-Reduce-scope-of-local-function.patch
deleted file mode 100644 (file)
index 1e9d4b4..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 4924b7b5517c9c334cf5faa3c7a29adf9a0c0ba1 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Wed, 28 Aug 2019 15:54:19 +0100
-Subject: [PATCH] media: bcm2835: unicam: Reduce scope of local
- function
-
-unicam_start_rx() is not used outside of the unicam module.  Its current
-definition produces a compiler warning, that no function prototype
-exists.
-
-As the function is only used within the local scope of the module,
-convert it to a static function.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.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
-@@ -963,7 +963,7 @@ static void unicam_cfg_image_id(struct u
-       }
- }
--void unicam_start_rx(struct unicam_device *dev, unsigned long addr)
-+static void unicam_start_rx(struct unicam_device *dev, unsigned long addr)
- {
-       struct unicam_cfg *cfg = &dev->cfg;
-       int line_int_freq = dev->v_fmt.fmt.pix.height >> 2;
diff --git a/target/linux/brcm2708/patches-4.19/950-0688-Add-missing-dma_unmap_sg-calls-to-free-relevant-swio.patch b/target/linux/brcm2708/patches-4.19/950-0688-Add-missing-dma_unmap_sg-calls-to-free-relevant-swio.patch
new file mode 100644 (file)
index 0000000..0a14126
--- /dev/null
@@ -0,0 +1,46 @@
+From f8554985b77df2dac55f2d7c85e0f0cc3497a1fd Mon Sep 17 00:00:00 2001
+From: Yaroslav Rosomakho <yaroslavros@gmail.com>
+Date: Fri, 23 Aug 2019 11:05:51 +0200
+Subject: [PATCH] Add missing dma_unmap_sg calls to free relevant
+ swiotlb bounce buffers. This prevents DMA leaks.
+
+Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -345,16 +345,17 @@ static void bcm2835_mmc_dma_complete(voi
+       host->use_dma = false;
+-      if (host->data && !(host->data->flags & MMC_DATA_WRITE)) {
+-              /* otherwise handled in SDHCI IRQ */
++      if (host->data) {
+               dma_chan = host->dma_chan_rxtx;
+-              dir_data = DMA_FROM_DEVICE;
+-
++              if (host->data->flags & MMC_DATA_WRITE)
++                      dir_data = DMA_TO_DEVICE;
++              else
++                      dir_data = DMA_FROM_DEVICE;
+               dma_unmap_sg(dma_chan->device->dev,
+                    host->data->sg, host->data->sg_len,
+                    dir_data);
+-
+-              bcm2835_mmc_finish_data(host);
++              if (! (host->data->flags & MMC_DATA_WRITE))
++                      bcm2835_mmc_finish_data(host);
+       } else if (host->wait_for_dma) {
+               host->wait_for_dma = false;
+               tasklet_schedule(&host->finish_tasklet);
+@@ -540,6 +541,8 @@ static void bcm2835_mmc_transfer_dma(str
+               spin_unlock_irqrestore(&host->lock, flags);
+               dmaengine_submit(desc);
+               dma_async_issue_pending(dma_chan);
++      } else {
++              dma_unmap_sg(dma_chan->device->dev, host->data->sg, len, dir_data);
+       }
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0688-media-bcm2835-unicam-add-media-controller-support.patch b/target/linux/brcm2708/patches-4.19/950-0688-media-bcm2835-unicam-add-media-controller-support.patch
deleted file mode 100644 (file)
index e847212..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-From 06cd9857f8faa63321506a75988c475906a32970 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Wed, 20 Mar 2019 12:54:47 +0000
-Subject: [PATCH] media: bcm2835: unicam: add media controller support
-
-Add a media controller device node to represent the Unicam device.
-The attached sensor will be automatically added to the media graph by
-V4L2 core.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/media/platform/bcm2835/Kconfig        |  2 +-
- .../media/platform/bcm2835/bcm2835-unicam.c   | 46 ++++++++++++++++++-
- 2 files changed, 45 insertions(+), 3 deletions(-)
-
---- a/drivers/media/platform/bcm2835/Kconfig
-+++ b/drivers/media/platform/bcm2835/Kconfig
-@@ -2,7 +2,7 @@
- config VIDEO_BCM2835_UNICAM
-       tristate "Broadcom BCM2835 Unicam video capture driver"
--      depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-+      depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
-       depends on ARCH_BCM2835 || COMPILE_TEST
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_FWNODE
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -314,6 +314,9 @@ struct unicam_device {
-       struct clk *clock;
-       /* V4l2 device */
-       struct v4l2_device v4l2_dev;
-+      struct media_device mdev;
-+      struct media_pad pad;
-+
-       /* parent device */
-       struct platform_device *pdev;
-       /* subdevice async Notifier */
-@@ -1912,6 +1915,8 @@ static int unicam_probe_complete(struct
-               unicam->v4l2_dev.ctrl_handler = NULL;
-       video_set_drvdata(vdev, unicam);
-+      vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
-+
-       ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
-       if (ret) {
-               unicam_err(unicam, "Unable to register video device.\n");
-@@ -1953,6 +1958,16 @@ static int unicam_probe_complete(struct
-               return ret;
-       }
-+      ret = media_create_pad_link(&unicam->sensor->entity, 0,
-+                                  &unicam->video_dev.entity, 0,
-+                                  MEDIA_LNK_FL_ENABLED |
-+                                  MEDIA_LNK_FL_IMMUTABLE);
-+      if (ret) {
-+              unicam_err(unicam, "Unable to create pad links.\n");
-+              video_unregister_device(&unicam->video_dev);
-+              return ret;
-+      }
-+
-       return 0;
- }
-@@ -2155,18 +2170,38 @@ static int unicam_probe(struct platform_
-               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", pdev->name);
-+      unicam->mdev.hw_revision = 1;
-+
-+      media_entity_pads_init(&unicam->video_dev.entity, 1, &unicam->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");
--              return ret;
-+              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->ctrl_handler;
-       ret = v4l2_ctrl_handler_init(hdl, 16);
-       if (ret < 0)
--              goto probe_out_v4l2_unregister;
-+              goto media_unregister;
-       unicam->v4l2_dev.ctrl_handler = hdl;
-       /* set the driver data in platform device */
-@@ -2185,8 +2220,13 @@ static int unicam_probe(struct platform_
- 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;
- }
-@@ -2204,6 +2244,8 @@ static int unicam_remove(struct platform
-       video_unregister_device(&unicam->video_dev);
-       if (unicam->sensor_config)
-               v4l2_subdev_free_pad_config(unicam->sensor_config);
-+      media_device_unregister(&unicam->mdev);
-+      media_device_cleanup(&unicam->mdev);
-       return 0;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0689-Limit-max_req_size-under-arm64-or-any-other-platform.patch b/target/linux/brcm2708/patches-4.19/950-0689-Limit-max_req_size-under-arm64-or-any-other-platform.patch
deleted file mode 100644 (file)
index 87b4e9b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 7bfcb31431f06efc233e4cc4d7ab65e10a6522cd Mon Sep 17 00:00:00 2001
-From: Yaroslav Rosomakho <yaroslavros@gmail.com>
-Date: Fri, 23 Aug 2019 11:02:22 +0200
-Subject: [PATCH] Limit max_req_size under arm64 (or any other platform
- that uses swiotlb) to prevent potential buffer overflow due to bouncing.
-
-Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
----
- drivers/mmc/host/bcm2835-mmc.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -38,6 +38,7 @@
- #include <linux/dmaengine.h>
- #include <linux/dma-mapping.h>
- #include <linux/of_dma.h>
-+#include <linux/swiotlb.h>
- #include "sdhci.h"
-@@ -1374,7 +1375,10 @@ static int bcm2835_mmc_add_host(struct b
-       }
- #endif
-       mmc->max_segs = 128;
--      mmc->max_req_size = 524288;
-+      if (swiotlb_max_segment())
-+              mmc->max_req_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE;
-+      else
-+              mmc->max_req_size = 524288;
-       mmc->max_seg_size = mmc->max_req_size;
-       mmc->max_blk_size = 512;
-       mmc->max_blk_count =  65535;
diff --git a/target/linux/brcm2708/patches-4.19/950-0689-overlays-mcp23017-rename-the-GPIO-pins-node-with-the.patch b/target/linux/brcm2708/patches-4.19/950-0689-overlays-mcp23017-rename-the-GPIO-pins-node-with-the.patch
new file mode 100644 (file)
index 0000000..09dbf4a
--- /dev/null
@@ -0,0 +1,37 @@
+From 9802671acf4250d6541d175ba599da03cee8acc1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 5 Sep 2019 17:36:38 +0100
+Subject: [PATCH] overlays: mcp23017: rename the GPIO pins node with
+ the device
+
+In order to allow the overlay to be loaded multiple times the
+GPIO node for the interrupt line needs to be unique.
+Rename it based on the MCP23017 I2C address
+
+https://github.com/raspberrypi/linux/issues/3207
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
+@@ -16,7 +16,7 @@
+       fragment@1 {
+               target = <&gpio>;
+               __overlay__ {
+-                      mcp23017_pins: mcp23017_pins {
++                      mcp23017_pins: mcp23017_pins@20 {
+                               brcm,pins = <4>;
+                               brcm,function = <0>;
+                       };
+@@ -55,7 +55,7 @@
+       __overrides__ {
+               gpiopin = <&mcp23017_pins>,"brcm,pins:0",
+                               <&mcp23017>,"interrupts:0";
+-              addr = <&mcp23017>,"reg:0";
++              addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0";
+               mcp23008 = <0>,"=3";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0690-Add-missing-dma_unmap_sg-calls-to-free-relevant-swio.patch b/target/linux/brcm2708/patches-4.19/950-0690-Add-missing-dma_unmap_sg-calls-to-free-relevant-swio.patch
deleted file mode 100644 (file)
index 0a14126..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From f8554985b77df2dac55f2d7c85e0f0cc3497a1fd Mon Sep 17 00:00:00 2001
-From: Yaroslav Rosomakho <yaroslavros@gmail.com>
-Date: Fri, 23 Aug 2019 11:05:51 +0200
-Subject: [PATCH] Add missing dma_unmap_sg calls to free relevant
- swiotlb bounce buffers. This prevents DMA leaks.
-
-Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
----
- drivers/mmc/host/bcm2835-mmc.c | 15 +++++++++------
- 1 file changed, 9 insertions(+), 6 deletions(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -345,16 +345,17 @@ static void bcm2835_mmc_dma_complete(voi
-       host->use_dma = false;
--      if (host->data && !(host->data->flags & MMC_DATA_WRITE)) {
--              /* otherwise handled in SDHCI IRQ */
-+      if (host->data) {
-               dma_chan = host->dma_chan_rxtx;
--              dir_data = DMA_FROM_DEVICE;
--
-+              if (host->data->flags & MMC_DATA_WRITE)
-+                      dir_data = DMA_TO_DEVICE;
-+              else
-+                      dir_data = DMA_FROM_DEVICE;
-               dma_unmap_sg(dma_chan->device->dev,
-                    host->data->sg, host->data->sg_len,
-                    dir_data);
--
--              bcm2835_mmc_finish_data(host);
-+              if (! (host->data->flags & MMC_DATA_WRITE))
-+                      bcm2835_mmc_finish_data(host);
-       } else if (host->wait_for_dma) {
-               host->wait_for_dma = false;
-               tasklet_schedule(&host->finish_tasklet);
-@@ -540,6 +541,8 @@ static void bcm2835_mmc_transfer_dma(str
-               spin_unlock_irqrestore(&host->lock, flags);
-               dmaengine_submit(desc);
-               dma_async_issue_pending(dma_chan);
-+      } else {
-+              dma_unmap_sg(dma_chan->device->dev, host->data->sg, len, dir_data);
-       }
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0690-overlays-mcp23017-Add-option-for-not-connecting-the-.patch b/target/linux/brcm2708/patches-4.19/950-0690-overlays-mcp23017-Add-option-for-not-connecting-the-.patch
new file mode 100644 (file)
index 0000000..e6376d7
--- /dev/null
@@ -0,0 +1,66 @@
+From b37ac8c50684c3517fb9c6f737e7ea444a7d7405 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 5 Sep 2019 17:41:46 +0100
+Subject: [PATCH] overlays: mcp23017: Add option for not connecting the
+ int GPIO
+
+The interrupt GPIO is optional to the driver, therefore add an
+option to not configure it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README             |  1 +
+ .../boot/dts/overlays/mcp23017-overlay.dts    | 21 +++++++++++++------
+ 2 files changed, 16 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1427,6 +1427,7 @@ Params: gpiopin                 Gpio pin
+         addr                    I2C address of the MCP23017 (default: 0x20)
+         mcp23008                Configure an MCP23008 instead.
++        noints                  Disable the interrupt GPIO line.
+ Name:   mcp23s17
+--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
+@@ -34,11 +34,6 @@
+                               reg = <0x20>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+-                              #interrupt-cells=<2>;
+-                              interrupt-parent = <&gpio>;
+-                              interrupts = <4 2>;
+-                              interrupt-controller;
+-                              microchip,irq-mirror;
+                               status = "okay";
+                       };
+@@ -52,11 +47,25 @@
+               };
+       };
++      fragment@4 {
++              target = <&i2c1>;
++              __overlay__ {
++                      mcp23017_irq: mcp@20 {
++                              #interrupt-cells=<2>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <4 2>;
++                              interrupt-controller;
++                              microchip,irq-mirror;
++                      };
++              };
++      };
++
+       __overrides__ {
+               gpiopin = <&mcp23017_pins>,"brcm,pins:0",
+-                              <&mcp23017>,"interrupts:0";
++                              <&mcp23017_irq>,"interrupts:0";
+               addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0";
+               mcp23008 = <0>,"=3";
++              noints = <0>,"!1!4";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0691-overlays-mcp23017-rename-the-GPIO-pins-node-with-the.patch b/target/linux/brcm2708/patches-4.19/950-0691-overlays-mcp23017-rename-the-GPIO-pins-node-with-the.patch
deleted file mode 100644 (file)
index 09dbf4a..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 9802671acf4250d6541d175ba599da03cee8acc1 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 5 Sep 2019 17:36:38 +0100
-Subject: [PATCH] overlays: mcp23017: rename the GPIO pins node with
- the device
-
-In order to allow the overlay to be loaded multiple times the
-GPIO node for the interrupt line needs to be unique.
-Rename it based on the MCP23017 I2C address
-
-https://github.com/raspberrypi/linux/issues/3207
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-@@ -16,7 +16,7 @@
-       fragment@1 {
-               target = <&gpio>;
-               __overlay__ {
--                      mcp23017_pins: mcp23017_pins {
-+                      mcp23017_pins: mcp23017_pins@20 {
-                               brcm,pins = <4>;
-                               brcm,function = <0>;
-                       };
-@@ -55,7 +55,7 @@
-       __overrides__ {
-               gpiopin = <&mcp23017_pins>,"brcm,pins:0",
-                               <&mcp23017>,"interrupts:0";
--              addr = <&mcp23017>,"reg:0";
-+              addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0";
-               mcp23008 = <0>,"=3";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0691-v4l2-Add-a-Greyworld-AWB-mode.patch b/target/linux/brcm2708/patches-4.19/950-0691-v4l2-Add-a-Greyworld-AWB-mode.patch
new file mode 100644 (file)
index 0000000..aca9837
--- /dev/null
@@ -0,0 +1,34 @@
+From c8f63d006ff5f84ad629f4c06cdc9fee34fdfe3d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 6 Sep 2019 15:04:51 +0100
+Subject: [PATCH] v4l2: Add a Greyworld AWB mode.
+
+Adds a simple greyworld white balance preset, mainly for use
+with cameras without an IR filter (eg Raspberry Pi NoIR)
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/media/v4l2-core/v4l2-ctrls.c | 1 +
+ include/uapi/linux/v4l2-controls.h   | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/media/v4l2-core/v4l2-ctrls.c
++++ b/drivers/media/v4l2-core/v4l2-ctrls.c
+@@ -275,6 +275,7 @@ const char * const *v4l2_ctrl_get_menu(u
+               "Flash",
+               "Cloudy",
+               "Shade",
++              "Greyworld",
+               NULL,
+       };
+       static const char * const camera_iso_sensitivity_auto[] = {
+--- a/include/uapi/linux/v4l2-controls.h
++++ b/include/uapi/linux/v4l2-controls.h
+@@ -815,6 +815,7 @@ enum v4l2_auto_n_preset_white_balance {
+       V4L2_WHITE_BALANCE_FLASH                = 7,
+       V4L2_WHITE_BALANCE_CLOUDY               = 8,
+       V4L2_WHITE_BALANCE_SHADE                = 9,
++      V4L2_WHITE_BALANCE_GREYWORLD            = 10,
+ };
+ #define V4L2_CID_WIDE_DYNAMIC_RANGE           (V4L2_CID_CAMERA_CLASS_BASE+21)
diff --git a/target/linux/brcm2708/patches-4.19/950-0692-overlays-mcp23017-Add-option-for-not-connecting-the-.patch b/target/linux/brcm2708/patches-4.19/950-0692-overlays-mcp23017-Add-option-for-not-connecting-the-.patch
deleted file mode 100644 (file)
index e6376d7..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-From b37ac8c50684c3517fb9c6f737e7ea444a7d7405 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 5 Sep 2019 17:41:46 +0100
-Subject: [PATCH] overlays: mcp23017: Add option for not connecting the
- int GPIO
-
-The interrupt GPIO is optional to the driver, therefore add an
-option to not configure it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README             |  1 +
- .../boot/dts/overlays/mcp23017-overlay.dts    | 21 +++++++++++++------
- 2 files changed, 16 insertions(+), 6 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1427,6 +1427,7 @@ Params: gpiopin                 Gpio pin
-         addr                    I2C address of the MCP23017 (default: 0x20)
-         mcp23008                Configure an MCP23008 instead.
-+        noints                  Disable the interrupt GPIO line.
- Name:   mcp23s17
---- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-@@ -34,11 +34,6 @@
-                               reg = <0x20>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
--                              #interrupt-cells=<2>;
--                              interrupt-parent = <&gpio>;
--                              interrupts = <4 2>;
--                              interrupt-controller;
--                              microchip,irq-mirror;
-                               status = "okay";
-                       };
-@@ -52,11 +47,25 @@
-               };
-       };
-+      fragment@4 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      mcp23017_irq: mcp@20 {
-+                              #interrupt-cells=<2>;
-+                              interrupt-parent = <&gpio>;
-+                              interrupts = <4 2>;
-+                              interrupt-controller;
-+                              microchip,irq-mirror;
-+                      };
-+              };
-+      };
-+
-       __overrides__ {
-               gpiopin = <&mcp23017_pins>,"brcm,pins:0",
--                              <&mcp23017>,"interrupts:0";
-+                              <&mcp23017_irq>,"interrupts:0";
-               addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0";
-               mcp23008 = <0>,"=3";
-+              noints = <0>,"!1!4";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0692-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch b/target/linux/brcm2708/patches-4.19/950-0692-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch
new file mode 100644 (file)
index 0000000..a1e4149
--- /dev/null
@@ -0,0 +1,48 @@
+From b5ec436637af67f37efad1550945b750101527d4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 6 Sep 2019 15:13:06 +0100
+Subject: [PATCH] staging: bcm2835-camera: Add greyworld AWB mode
+
+This is mainly used for the NoIR camera which has no IR
+filter and can completely confuse normal AWB presets.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/controls.c   | 8 ++++++--
+ .../staging/vc04_services/vchiq-mmal/mmal-parameters.h    | 1 +
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -481,6 +481,10 @@ static int ctrl_set_awb_mode(struct bm28
+       case V4L2_WHITE_BALANCE_SHADE:
+               u32_value = MMAL_PARAM_AWBMODE_SHADE;
+               break;
++
++      case V4L2_WHITE_BALANCE_GREYWORLD:
++              u32_value = MMAL_PARAM_AWBMODE_GREYWORLD;
++              break;
+       }
+       return vchiq_mmal_port_parameter_set(dev->instance, control,
+@@ -1008,8 +1012,8 @@ static const struct bm2835_mmal_v4l2_ctr
+       {
+               V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+               MMAL_CONTROL_TYPE_STD_MENU,
+-              ~0x3ff, V4L2_WHITE_BALANCE_SHADE, V4L2_WHITE_BALANCE_AUTO, 0,
+-              NULL,
++              ~0x7ff, V4L2_WHITE_BALANCE_GREYWORLD, V4L2_WHITE_BALANCE_AUTO,
++              0, NULL,
+               MMAL_PARAMETER_AWB_MODE,
+               &ctrl_set_awb_mode,
+               false
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
+@@ -313,6 +313,7 @@ enum mmal_parameter_awbmode {
+       MMAL_PARAM_AWBMODE_INCANDESCENT,
+       MMAL_PARAM_AWBMODE_FLASH,
+       MMAL_PARAM_AWBMODE_HORIZON,
++      MMAL_PARAM_AWBMODE_GREYWORLD,
+ };
+ enum mmal_parameter_imagefx {
diff --git a/target/linux/brcm2708/patches-4.19/950-0693-PCI-brcmstb-Fix-compilation-warning.patch b/target/linux/brcm2708/patches-4.19/950-0693-PCI-brcmstb-Fix-compilation-warning.patch
new file mode 100644 (file)
index 0000000..978a656
--- /dev/null
@@ -0,0 +1,24 @@
+From 2245d8c6d0feaa94ca55fa8ecfe3ca9c0c05c566 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 9 Sep 2019 10:16:08 +0100
+Subject: [PATCH] PCI: brcmstb: Fix compilation warning
+
+Fixes: ea2c11a187c0e248343452846457b94715e04969
+Fixes: https://github.com/raspberrypi/linux/issues/3216
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -653,7 +653,7 @@ static int brcmstb_platform_notifier(str
+                       ret = of_dma_configure(dev, dev->of_node, true);
+                       if (ret) {
+                               dev_err(dev, "of_dma_configure() failed: %d\n", ret);
+-                              return;
++                              return ret;
+                       }
+               }
+               brcm_set_dma_ops(dev);
diff --git a/target/linux/brcm2708/patches-4.19/950-0693-v4l2-Add-a-Greyworld-AWB-mode.patch b/target/linux/brcm2708/patches-4.19/950-0693-v4l2-Add-a-Greyworld-AWB-mode.patch
deleted file mode 100644 (file)
index aca9837..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From c8f63d006ff5f84ad629f4c06cdc9fee34fdfe3d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 6 Sep 2019 15:04:51 +0100
-Subject: [PATCH] v4l2: Add a Greyworld AWB mode.
-
-Adds a simple greyworld white balance preset, mainly for use
-with cameras without an IR filter (eg Raspberry Pi NoIR)
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/media/v4l2-core/v4l2-ctrls.c | 1 +
- include/uapi/linux/v4l2-controls.h   | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/media/v4l2-core/v4l2-ctrls.c
-+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
-@@ -275,6 +275,7 @@ const char * const *v4l2_ctrl_get_menu(u
-               "Flash",
-               "Cloudy",
-               "Shade",
-+              "Greyworld",
-               NULL,
-       };
-       static const char * const camera_iso_sensitivity_auto[] = {
---- a/include/uapi/linux/v4l2-controls.h
-+++ b/include/uapi/linux/v4l2-controls.h
-@@ -815,6 +815,7 @@ enum v4l2_auto_n_preset_white_balance {
-       V4L2_WHITE_BALANCE_FLASH                = 7,
-       V4L2_WHITE_BALANCE_CLOUDY               = 8,
-       V4L2_WHITE_BALANCE_SHADE                = 9,
-+      V4L2_WHITE_BALANCE_GREYWORLD            = 10,
- };
- #define V4L2_CID_WIDE_DYNAMIC_RANGE           (V4L2_CID_CAMERA_CLASS_BASE+21)
diff --git a/target/linux/brcm2708/patches-4.19/950-0694-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch b/target/linux/brcm2708/patches-4.19/950-0694-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch
new file mode 100644 (file)
index 0000000..203804d
--- /dev/null
@@ -0,0 +1,34 @@
+From 1e37bc9f0ea83fa4b3f1714b4382edb7b256a251 Mon Sep 17 00:00:00 2001
+From: James Hughes <JamesH65@users.noreply.github.com>
+Date: Wed, 11 Sep 2019 14:57:18 +0100
+Subject: [PATCH] drm/vc4: Fix for margins in composite/SDTV mode
+ (#3223)
+
+Margins were incorrectly assumed to be setup in SDTV mode, but were
+not actually done, so this make the setup non-conditional on mode.
+
+Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1588,14 +1588,9 @@ vc4_fkms_connector_init(struct drm_devic
+               connector->interlace_allowed = 0;
+       }
+-      /* Create and attach TV margin props to this connector.
+-       * Already done for SDTV outputs.
+-       */
+-      if (fkms_connector->display_type != DRM_MODE_ENCODER_TVDAC) {
+-              ret = drm_mode_create_tv_margin_properties(dev);
+-              if (ret)
+-                      goto fail;
+-      }
++      ret = drm_mode_create_tv_margin_properties(dev);
++      if (ret)
++              goto fail;
+       drm_connector_attach_tv_margin_properties(connector);
diff --git a/target/linux/brcm2708/patches-4.19/950-0694-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch b/target/linux/brcm2708/patches-4.19/950-0694-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch
deleted file mode 100644 (file)
index a1e4149..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From b5ec436637af67f37efad1550945b750101527d4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 6 Sep 2019 15:13:06 +0100
-Subject: [PATCH] staging: bcm2835-camera: Add greyworld AWB mode
-
-This is mainly used for the NoIR camera which has no IR
-filter and can completely confuse normal AWB presets.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/controls.c   | 8 ++++++--
- .../staging/vc04_services/vchiq-mmal/mmal-parameters.h    | 1 +
- 2 files changed, 7 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -481,6 +481,10 @@ static int ctrl_set_awb_mode(struct bm28
-       case V4L2_WHITE_BALANCE_SHADE:
-               u32_value = MMAL_PARAM_AWBMODE_SHADE;
-               break;
-+
-+      case V4L2_WHITE_BALANCE_GREYWORLD:
-+              u32_value = MMAL_PARAM_AWBMODE_GREYWORLD;
-+              break;
-       }
-       return vchiq_mmal_port_parameter_set(dev->instance, control,
-@@ -1008,8 +1012,8 @@ static const struct bm2835_mmal_v4l2_ctr
-       {
-               V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
-               MMAL_CONTROL_TYPE_STD_MENU,
--              ~0x3ff, V4L2_WHITE_BALANCE_SHADE, V4L2_WHITE_BALANCE_AUTO, 0,
--              NULL,
-+              ~0x7ff, V4L2_WHITE_BALANCE_GREYWORLD, V4L2_WHITE_BALANCE_AUTO,
-+              0, NULL,
-               MMAL_PARAMETER_AWB_MODE,
-               &ctrl_set_awb_mode,
-               false
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-@@ -313,6 +313,7 @@ enum mmal_parameter_awbmode {
-       MMAL_PARAM_AWBMODE_INCANDESCENT,
-       MMAL_PARAM_AWBMODE_FLASH,
-       MMAL_PARAM_AWBMODE_HORIZON,
-+      MMAL_PARAM_AWBMODE_GREYWORLD,
- };
- enum mmal_parameter_imagefx {
diff --git a/target/linux/brcm2708/patches-4.19/950-0695-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch b/target/linux/brcm2708/patches-4.19/950-0695-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch
new file mode 100644 (file)
index 0000000..0ff9775
--- /dev/null
@@ -0,0 +1,246 @@
+From f0715f5e178f2f7c0afb719a3a35c8ac250b7586 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=B6rg=20Schambacher?=
+ <j-schambacher@users.noreply.github.com>
+Date: Thu, 12 Sep 2019 14:57:32 +0200
+Subject: [PATCH] Add Hifiberry DAC+DSP soundcard driver (#3224)
+
+Adds the driver for the Hifiberry DAC+DSP. It supports capture and
+playback depending on the DSP firmware.
+
+Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  6 ++
+ .../overlays/hifiberry-dacplusdsp-overlay.dts | 34 +++++++
+ sound/soc/bcm/Kconfig                         |  7 ++
+ sound/soc/bcm/Makefile                        |  2 +
+ sound/soc/bcm/hifiberry_dacplusdsp.c          | 90 +++++++++++++++++++
+ sound/soc/bcm/rpi-simple-soundcard.c          | 19 ++++
+ 10 files changed, 162 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts
+ create mode 100644 sound/soc/bcm/hifiberry_dacplusdsp.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -54,6 +54,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       hifiberry-dacplus.dtbo \
+       hifiberry-dacplusadc.dtbo \
+       hifiberry-dacplusadcpro.dtbo \
++      hifiberry-dacplusdsp.dtbo \
+       hifiberry-digi.dtbo \
+       hifiberry-digi-pro.dtbo \
+       hy28a.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -904,6 +904,12 @@ Params: 24db_digital_gain       Allow ga
+                                 master for bit clock and frame clock.
++Name:   hifiberry-dacplusdsp
++Info:   Configures the HifiBerry DAC+DSP audio card
++Load:   dtoverlay=hifiberry-dacplusdsp
++Params: <None>
++
++
+ Name:   hifiberry-digi
+ Info:   Configures the HifiBerry Digi and Digi+ audio card
+ Load:   dtoverlay=hifiberry-digi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts
+@@ -0,0 +1,34 @@
++// Definitions for hifiberry DAC+DSP soundcard overlay
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target-path = "/";
++              __overlay__ {
++                      dacplusdsp-codec {
++                              #sound-dai-cells = <0>;
++                              compatible = "hifiberry,dacplusdsp";
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&sound>;
++              __overlay__ {
++                      compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++};
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -56,6 +56,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
+         help
+          Say Y or M if you want to add support for HifiBerry DAC+ADC PRO.
++config SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP
++        tristate "Support for HifiBerry DAC+DSP"
++        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++      select SND_RPI_SIMPLE_SOUNDCARD
++        help
++         Say Y or M if you want to add support for HifiBerry DSP-DAC.
++
+ config SND_BCM2708_SOC_HIFIBERRY_DIGI
+         tristate "Support for HifiBerry Digi"
+         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -15,6 +15,7 @@ snd-soc-googlevoicehat-codec-objs := goo
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
++snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+@@ -40,6 +41,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICE
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+--- /dev/null
++++ b/sound/soc/bcm/hifiberry_dacplusdsp.c
+@@ -0,0 +1,90 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * ASoC Driver for HiFiBerry DAC + DSP
++ *
++ * Author:    Joerg Schambacher <joscha@schambacher.com>
++ *            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/init.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <sound/soc.h>
++
++static struct snd_soc_component_driver dacplusdsp_component_driver;
++
++static struct snd_soc_dai_driver dacplusdsp_dai = {
++      .name = "dacplusdsp-hifi",
++      .capture = {
++              .stream_name = "DAC+DSP Capture",
++              .channels_min = 2,
++              .channels_max = 2,
++              .rates = SNDRV_PCM_RATE_CONTINUOUS,
++              .formats = SNDRV_PCM_FMTBIT_S16_LE |
++                         SNDRV_PCM_FMTBIT_S24_LE |
++                         SNDRV_PCM_FMTBIT_S32_LE,
++      },
++      .playback = {
++              .stream_name = "DACP+DSP Playback",
++              .channels_min = 2,
++              .channels_max = 2,
++              .rates = SNDRV_PCM_RATE_CONTINUOUS,
++              .formats = SNDRV_PCM_FMTBIT_S16_LE |
++                         SNDRV_PCM_FMTBIT_S24_LE |
++                         SNDRV_PCM_FMTBIT_S32_LE,
++      },
++      .symmetric_rates = 1};
++
++#ifdef CONFIG_OF
++static const struct of_device_id dacplusdsp_ids[] = {
++      {
++              .compatible = "hifiberry,dacplusdsp",
++      },
++      {} };
++MODULE_DEVICE_TABLE(of, dacplusdsp_ids);
++#endif
++
++static int dacplusdsp_platform_probe(struct platform_device *pdev)
++{
++      int ret;
++
++      ret = snd_soc_register_component(&pdev->dev,
++                      &dacplusdsp_component_driver, &dacplusdsp_dai, 1);
++      if (ret) {
++              pr_alert("snd_soc_register_component failed\n");
++              return ret;
++      }
++
++      return 0;
++}
++
++static int dacplusdsp_platform_remove(struct platform_device *pdev)
++{
++      snd_soc_unregister_component(&pdev->dev);
++      return 0;
++}
++
++static struct platform_driver dacplusdsp_driver = {
++      .driver = {
++              .name = "hifiberry-dacplusdsp-codec",
++              .of_match_table = of_match_ptr(dacplusdsp_ids),
++              },
++              .probe = dacplusdsp_platform_probe,
++              .remove = dacplusdsp_platform_remove,
++};
++
++module_platform_driver(dacplusdsp_driver);
++
++MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+DSP");
++MODULE_LICENSE("GPL v2");
+--- a/sound/soc/bcm/rpi-simple-soundcard.c
++++ b/sound/soc/bcm/rpi-simple-soundcard.c
+@@ -136,6 +136,23 @@ static struct snd_rpi_simple_drvdata drv
+       .dai       = snd_googlevoicehat_soundcard_dai,
+ };
++static struct snd_soc_dai_link snd_hifiberrydacplusdsp_soundcard_dai[] = {
++{
++      .name           = "Hifiberry DAC+DSP SoundCard",
++      .stream_name    = "Hifiberry DAC+DSP SoundCard HiFi",
++      .codec_dai_name = "dacplusdsp-hifi",
++      .codec_name     = "dacplusdsp-codec",
++      .dai_fmt        =  SND_SOC_DAIFMT_I2S |
++                         SND_SOC_DAIFMT_NB_NF |
++                         SND_SOC_DAIFMT_CBS_CFS,
++},
++};
++
++static struct snd_rpi_simple_drvdata drvdata_hifiberrydacplusdsp = {
++      .card_name = "snd_rpi_hifiberrydacplusdsp_soundcard",
++      .dai       = snd_hifiberrydacplusdsp_soundcard_dai,
++};
++
+ static struct snd_soc_dai_link snd_hifiberry_amp_dai[] = {
+       {
+               .name           = "HifiBerry AMP",
+@@ -193,6 +210,8 @@ static const struct of_device_id snd_rpi
+               .data = (void *) &drvdata_adau1977 },
+       { .compatible = "googlevoicehat,googlevoicehat-soundcard",
+               .data = (void *) &drvdata_googlevoicehat },
++      { .compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard",
++              .data = (void *) &drvdata_hifiberrydacplusdsp },
+       { .compatible = "hifiberry,hifiberry-amp",
+               .data = (void *) &drvdata_hifiberry_amp },
+       { .compatible = "hifiberry,hifiberry-dac",
diff --git a/target/linux/brcm2708/patches-4.19/950-0695-PCI-brcmstb-Fix-compilation-warning.patch b/target/linux/brcm2708/patches-4.19/950-0695-PCI-brcmstb-Fix-compilation-warning.patch
deleted file mode 100644 (file)
index 978a656..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 2245d8c6d0feaa94ca55fa8ecfe3ca9c0c05c566 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 9 Sep 2019 10:16:08 +0100
-Subject: [PATCH] PCI: brcmstb: Fix compilation warning
-
-Fixes: ea2c11a187c0e248343452846457b94715e04969
-Fixes: https://github.com/raspberrypi/linux/issues/3216
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/pci/controller/pcie-brcmstb.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -653,7 +653,7 @@ static int brcmstb_platform_notifier(str
-                       ret = of_dma_configure(dev, dev->of_node, true);
-                       if (ret) {
-                               dev_err(dev, "of_dma_configure() failed: %d\n", ret);
--                              return;
-+                              return ret;
-                       }
-               }
-               brcm_set_dma_ops(dev);
diff --git a/target/linux/brcm2708/patches-4.19/950-0696-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch b/target/linux/brcm2708/patches-4.19/950-0696-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch
deleted file mode 100644 (file)
index 203804d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 1e37bc9f0ea83fa4b3f1714b4382edb7b256a251 Mon Sep 17 00:00:00 2001
-From: James Hughes <JamesH65@users.noreply.github.com>
-Date: Wed, 11 Sep 2019 14:57:18 +0100
-Subject: [PATCH] drm/vc4: Fix for margins in composite/SDTV mode
- (#3223)
-
-Margins were incorrectly assumed to be setup in SDTV mode, but were
-not actually done, so this make the setup non-conditional on mode.
-
-Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 11 +++--------
- 1 file changed, 3 insertions(+), 8 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1588,14 +1588,9 @@ vc4_fkms_connector_init(struct drm_devic
-               connector->interlace_allowed = 0;
-       }
--      /* Create and attach TV margin props to this connector.
--       * Already done for SDTV outputs.
--       */
--      if (fkms_connector->display_type != DRM_MODE_ENCODER_TVDAC) {
--              ret = drm_mode_create_tv_margin_properties(dev);
--              if (ret)
--                      goto fail;
--      }
-+      ret = drm_mode_create_tv_margin_properties(dev);
-+      if (ret)
-+              goto fail;
-       drm_connector_attach_tv_margin_properties(connector);
diff --git a/target/linux/brcm2708/patches-4.19/950-0696-staging-bcm2835-codec-Allow-height-of-1920.patch b/target/linux/brcm2708/patches-4.19/950-0696-staging-bcm2835-codec-Allow-height-of-1920.patch
new file mode 100644 (file)
index 0000000..3004f89
--- /dev/null
@@ -0,0 +1,27 @@
+From b25d17959484972a6585d6e1f7cb2cfb93d1540e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 6 Sep 2019 17:24:55 +0100
+Subject: [PATCH] staging: bcm2835-codec: Allow height of 1920.
+
+The codec is happy with video up to 1920 high if the width
+is suitably reduced to stay within level limits. eg 1080x1920
+is OK to decode.
+
+Increase the height limit accordingly.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../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
+@@ -92,7 +92,7 @@ static const char * const components[] =
+ #define MIN_W         32
+ #define MIN_H         32
+ #define MAX_W         1920
+-#define MAX_H         1088
++#define MAX_H         1920
+ #define BPL_ALIGN     32
+ #define DEFAULT_WIDTH 640
+ #define DEFAULT_HEIGHT        480
diff --git a/target/linux/brcm2708/patches-4.19/950-0697-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch b/target/linux/brcm2708/patches-4.19/950-0697-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch
deleted file mode 100644 (file)
index 0ff9775..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-From f0715f5e178f2f7c0afb719a3a35c8ac250b7586 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?J=C3=B6rg=20Schambacher?=
- <j-schambacher@users.noreply.github.com>
-Date: Thu, 12 Sep 2019 14:57:32 +0200
-Subject: [PATCH] Add Hifiberry DAC+DSP soundcard driver (#3224)
-
-Adds the driver for the Hifiberry DAC+DSP. It supports capture and
-playback depending on the DSP firmware.
-
-Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             |  6 ++
- .../overlays/hifiberry-dacplusdsp-overlay.dts | 34 +++++++
- sound/soc/bcm/Kconfig                         |  7 ++
- sound/soc/bcm/Makefile                        |  2 +
- sound/soc/bcm/hifiberry_dacplusdsp.c          | 90 +++++++++++++++++++
- sound/soc/bcm/rpi-simple-soundcard.c          | 19 ++++
- 10 files changed, 162 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts
- create mode 100644 sound/soc/bcm/hifiberry_dacplusdsp.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -54,6 +54,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       hifiberry-dacplus.dtbo \
-       hifiberry-dacplusadc.dtbo \
-       hifiberry-dacplusadcpro.dtbo \
-+      hifiberry-dacplusdsp.dtbo \
-       hifiberry-digi.dtbo \
-       hifiberry-digi-pro.dtbo \
-       hy28a.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -904,6 +904,12 @@ Params: 24db_digital_gain       Allow ga
-                                 master for bit clock and frame clock.
-+Name:   hifiberry-dacplusdsp
-+Info:   Configures the HifiBerry DAC+DSP audio card
-+Load:   dtoverlay=hifiberry-dacplusdsp
-+Params: <None>
-+
-+
- Name:   hifiberry-digi
- Info:   Configures the HifiBerry Digi and Digi+ audio card
- Load:   dtoverlay=hifiberry-digi
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts
-@@ -0,0 +1,34 @@
-+// Definitions for hifiberry DAC+DSP soundcard overlay
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target-path = "/";
-+              __overlay__ {
-+                      dacplusdsp-codec {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "hifiberry,dacplusdsp";
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&sound>;
-+              __overlay__ {
-+                      compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard";
-+                      i2s-controller = <&i2s>;
-+                      status = "okay";
-+              };
-+      };
-+};
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -56,6 +56,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
-         help
-          Say Y or M if you want to add support for HifiBerry DAC+ADC PRO.
-+config SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP
-+        tristate "Support for HifiBerry DAC+DSP"
-+        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+      select SND_RPI_SIMPLE_SOUNDCARD
-+        help
-+         Say Y or M if you want to add support for HifiBerry DSP-DAC.
-+
- config SND_BCM2708_SOC_HIFIBERRY_DIGI
-         tristate "Support for HifiBerry Digi"
-         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -15,6 +15,7 @@ snd-soc-googlevoicehat-codec-objs := goo
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
- snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
-+snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
-@@ -40,6 +41,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICE
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
-+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
---- /dev/null
-+++ b/sound/soc/bcm/hifiberry_dacplusdsp.c
-@@ -0,0 +1,90 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * ASoC Driver for HiFiBerry DAC + DSP
-+ *
-+ * Author:    Joerg Schambacher <joscha@schambacher.com>
-+ *            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/init.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <sound/soc.h>
-+
-+static struct snd_soc_component_driver dacplusdsp_component_driver;
-+
-+static struct snd_soc_dai_driver dacplusdsp_dai = {
-+      .name = "dacplusdsp-hifi",
-+      .capture = {
-+              .stream_name = "DAC+DSP Capture",
-+              .channels_min = 2,
-+              .channels_max = 2,
-+              .rates = SNDRV_PCM_RATE_CONTINUOUS,
-+              .formats = SNDRV_PCM_FMTBIT_S16_LE |
-+                         SNDRV_PCM_FMTBIT_S24_LE |
-+                         SNDRV_PCM_FMTBIT_S32_LE,
-+      },
-+      .playback = {
-+              .stream_name = "DACP+DSP Playback",
-+              .channels_min = 2,
-+              .channels_max = 2,
-+              .rates = SNDRV_PCM_RATE_CONTINUOUS,
-+              .formats = SNDRV_PCM_FMTBIT_S16_LE |
-+                         SNDRV_PCM_FMTBIT_S24_LE |
-+                         SNDRV_PCM_FMTBIT_S32_LE,
-+      },
-+      .symmetric_rates = 1};
-+
-+#ifdef CONFIG_OF
-+static const struct of_device_id dacplusdsp_ids[] = {
-+      {
-+              .compatible = "hifiberry,dacplusdsp",
-+      },
-+      {} };
-+MODULE_DEVICE_TABLE(of, dacplusdsp_ids);
-+#endif
-+
-+static int dacplusdsp_platform_probe(struct platform_device *pdev)
-+{
-+      int ret;
-+
-+      ret = snd_soc_register_component(&pdev->dev,
-+                      &dacplusdsp_component_driver, &dacplusdsp_dai, 1);
-+      if (ret) {
-+              pr_alert("snd_soc_register_component failed\n");
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int dacplusdsp_platform_remove(struct platform_device *pdev)
-+{
-+      snd_soc_unregister_component(&pdev->dev);
-+      return 0;
-+}
-+
-+static struct platform_driver dacplusdsp_driver = {
-+      .driver = {
-+              .name = "hifiberry-dacplusdsp-codec",
-+              .of_match_table = of_match_ptr(dacplusdsp_ids),
-+              },
-+              .probe = dacplusdsp_platform_probe,
-+              .remove = dacplusdsp_platform_remove,
-+};
-+
-+module_platform_driver(dacplusdsp_driver);
-+
-+MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
-+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+DSP");
-+MODULE_LICENSE("GPL v2");
---- a/sound/soc/bcm/rpi-simple-soundcard.c
-+++ b/sound/soc/bcm/rpi-simple-soundcard.c
-@@ -136,6 +136,23 @@ static struct snd_rpi_simple_drvdata drv
-       .dai       = snd_googlevoicehat_soundcard_dai,
- };
-+static struct snd_soc_dai_link snd_hifiberrydacplusdsp_soundcard_dai[] = {
-+{
-+      .name           = "Hifiberry DAC+DSP SoundCard",
-+      .stream_name    = "Hifiberry DAC+DSP SoundCard HiFi",
-+      .codec_dai_name = "dacplusdsp-hifi",
-+      .codec_name     = "dacplusdsp-codec",
-+      .dai_fmt        =  SND_SOC_DAIFMT_I2S |
-+                         SND_SOC_DAIFMT_NB_NF |
-+                         SND_SOC_DAIFMT_CBS_CFS,
-+},
-+};
-+
-+static struct snd_rpi_simple_drvdata drvdata_hifiberrydacplusdsp = {
-+      .card_name = "snd_rpi_hifiberrydacplusdsp_soundcard",
-+      .dai       = snd_hifiberrydacplusdsp_soundcard_dai,
-+};
-+
- static struct snd_soc_dai_link snd_hifiberry_amp_dai[] = {
-       {
-               .name           = "HifiBerry AMP",
-@@ -193,6 +210,8 @@ static const struct of_device_id snd_rpi
-               .data = (void *) &drvdata_adau1977 },
-       { .compatible = "googlevoicehat,googlevoicehat-soundcard",
-               .data = (void *) &drvdata_googlevoicehat },
-+      { .compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard",
-+              .data = (void *) &drvdata_hifiberrydacplusdsp },
-       { .compatible = "hifiberry,hifiberry-amp",
-               .data = (void *) &drvdata_hifiberry_amp },
-       { .compatible = "hifiberry,hifiberry-dac",
diff --git a/target/linux/brcm2708/patches-4.19/950-0697-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch b/target/linux/brcm2708/patches-4.19/950-0697-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch
new file mode 100644 (file)
index 0000000..36c5d1c
--- /dev/null
@@ -0,0 +1,107 @@
+From 956fd55c1071c48f00285d82507698c501633e7a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 13 Sep 2019 15:11:47 +0100
+Subject: [PATCH] staging: bcm2835-codec: Correct g/s_selection API
+ MPLANE support
+
+The g_selection and s_selection API is messed up and requires
+the driver to expect the non-MPLANE buffer types, not the MPLANE
+ones even if they are supported. The V4L2 core will convert the
+MPLANE ones to non-MPLANE should they be passed in
+
+Fixes: 5e484a3 staging: bcm2835-codec: switch to multi-planar API
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 67 +++++++++++++------
+ 1 file changed, 47 insertions(+), 20 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1260,17 +1260,30 @@ static int vidioc_g_selection(struct fil
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+       struct bcm2835_codec_q_data *q_data;
+-      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
+-                                                              true : false;
+-      if ((ctx->dev->role == DECODE && !capture_queue) ||
+-          (ctx->dev->role == ENCODE && capture_queue))
+-              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
+-              return -EINVAL;
+-
+-      q_data = get_q_data(ctx, s->type);
+-      if (!q_data)
++      /*
++       * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
++       * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
++       * API. The V4L2 core will have converted the MPLANE variants to
++       * non-MPLANE.
++       * Open code this instead of using get_q_data in this case.
++       */
++      switch (s->type) {
++      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++              /* CAPTURE on encoder is not valid. */
++              if (ctx->dev->role == ENCODE)
++                      return -EINVAL;
++              q_data = &ctx->q_data[V4L2_M2M_DST];
++              break;
++      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++              /* OUTPUT on deoder is not valid. */
++              if (ctx->dev->role == DECODE)
++                      return -EINVAL;
++              q_data = &ctx->q_data[V4L2_M2M_SRC];
++              break;
++      default:
+               return -EINVAL;
++      }
+       switch (ctx->dev->role) {
+       case DECODE:
+@@ -1323,22 +1336,36 @@ static int vidioc_s_selection(struct fil
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+       struct bcm2835_codec_q_data *q_data = NULL;
+-      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
+-                                                              true : false;
++
++      /*
++       * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
++       * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
++       * API. The V4L2 core will have converted the MPLANE variants to
++       * non-MPLANE.
++       *
++       * Open code this instead of using get_q_data in this case.
++       */
++      switch (s->type) {
++      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++              /* CAPTURE on encoder is not valid. */
++              if (ctx->dev->role == ENCODE)
++                      return -EINVAL;
++              q_data = &ctx->q_data[V4L2_M2M_DST];
++              break;
++      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++              /* OUTPUT on deoder is not valid. */
++              if (ctx->dev->role == DECODE)
++                      return -EINVAL;
++              q_data = &ctx->q_data[V4L2_M2M_SRC];
++              break;
++      default:
++              return -EINVAL;
++      }
+       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
+                __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
+                s->r.width, s->r.height);
+-      if ((ctx->dev->role == DECODE && !capture_queue) ||
+-          (ctx->dev->role == ENCODE && capture_queue))
+-              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
+-              return -EINVAL;
+-
+-      q_data = get_q_data(ctx, s->type);
+-      if (!q_data)
+-              return -EINVAL;
+-
+       switch (ctx->dev->role) {
+       case DECODE:
+               switch (s->target) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0698-regulator-gpio-Allow-nonexclusive-GPIO-access.patch b/target/linux/brcm2708/patches-4.19/950-0698-regulator-gpio-Allow-nonexclusive-GPIO-access.patch
new file mode 100644 (file)
index 0000000..a940736
--- /dev/null
@@ -0,0 +1,79 @@
+From f6d983b7bc9ae79d0eb4dea7bc30a1ad5ff428a7 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Fri, 12 Oct 2018 14:54:12 +0200
+Subject: [PATCH] regulator/gpio: Allow nonexclusive GPIO access
+
+commit b0ce7b29bfcd090ddba476f45a75ec0a797b048a upstream.
+
+[ This is a partial cherry-pick, omitting the regulator
+change which isn't required ]
+
+This allows nonexclusive (simultaneous) access to a single
+GPIO line for the fixed regulator enable line. This happens
+when several regulators use the same GPIO for enabling and
+disabling a regulator, and all need a handle on their GPIO
+descriptor.
+
+This solution with a special flag is not entirely elegant
+and should ideally be replaced by something more careful as
+this makes it possible for several consumers to
+enable/disable the same GPIO line to the left and right
+without any consistency. The current use inside the regulator
+core should however be fine as it takes special care to
+handle this.
+
+For the state of the GPIO backend, this is still the
+lesser evil compared to going back to global GPIO
+numbers.
+
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Fixes: efdfeb079cc3 ("regulator: fixed: Convert to use GPIO descriptor only")
+Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Jon Hunter <jonathanh@nvidia.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ drivers/gpio/gpiolib.c        | 19 +++++++++++++++++--
+ include/linux/gpio/consumer.h |  1 +
+ 2 files changed, 18 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -3988,8 +3988,23 @@ struct gpio_desc *__must_check gpiod_get
+        * the device name as label
+        */
+       status = gpiod_request(desc, con_id ? con_id : devname);
+-      if (status < 0)
+-              return ERR_PTR(status);
++      if (status < 0) {
++              if (status == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
++                      /*
++                       * This happens when there are several consumers for
++                       * the same GPIO line: we just return here without
++                       * further initialization. It is a bit if a hack.
++                       * This is necessary to support fixed regulators.
++                       *
++                       * FIXME: Make this more sane and safe.
++                       */
++                      dev_info(dev, "nonexclusive access to GPIO for %s\n",
++                               con_id ? con_id : devname);
++                      return desc;
++              } else {
++                      return ERR_PTR(status);
++              }
++      }
+       status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
+       if (status < 0) {
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -30,6 +30,7 @@ struct gpio_descs {
+ #define GPIOD_FLAGS_BIT_DIR_OUT               BIT(1)
+ #define GPIOD_FLAGS_BIT_DIR_VAL               BIT(2)
+ #define GPIOD_FLAGS_BIT_OPEN_DRAIN    BIT(3)
++#define GPIOD_FLAGS_BIT_NONEXCLUSIVE  BIT(4)
+ /**
+  * Optional flags that can be passed to one of gpiod_* to configure direction
diff --git a/target/linux/brcm2708/patches-4.19/950-0698-staging-bcm2835-codec-Allow-height-of-1920.patch b/target/linux/brcm2708/patches-4.19/950-0698-staging-bcm2835-codec-Allow-height-of-1920.patch
deleted file mode 100644 (file)
index 3004f89..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From b25d17959484972a6585d6e1f7cb2cfb93d1540e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 6 Sep 2019 17:24:55 +0100
-Subject: [PATCH] staging: bcm2835-codec: Allow height of 1920.
-
-The codec is happy with video up to 1920 high if the width
-is suitably reduced to stay within level limits. eg 1080x1920
-is OK to decode.
-
-Increase the height limit accordingly.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../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
-@@ -92,7 +92,7 @@ static const char * const components[] =
- #define MIN_W         32
- #define MIN_H         32
- #define MAX_W         1920
--#define MAX_H         1088
-+#define MAX_H         1920
- #define BPL_ALIGN     32
- #define DEFAULT_WIDTH 640
- #define DEFAULT_HEIGHT        480
diff --git a/target/linux/brcm2708/patches-4.19/950-0699-gpio-Enable-nonexclusive-gpiods-from-DT-nodes.patch b/target/linux/brcm2708/patches-4.19/950-0699-gpio-Enable-nonexclusive-gpiods-from-DT-nodes.patch
new file mode 100644 (file)
index 0000000..a4139e6
--- /dev/null
@@ -0,0 +1,34 @@
+From 76870d237adff4c8e419064e7d4f5a8ef87c1085 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Thu, 6 Dec 2018 13:43:44 +0100
+Subject: [PATCH] gpio: Enable nonexclusive gpiods from DT nodes
+
+commit ec757001c818c175e6b610e8ef80c2a25d1ed1a5 upstream.
+
+This makes gpiod_get_from_of_node() respect the
+GPIOD_FLAGS_BIT_NONEXCLUSIVE flag which is especially
+nice when getting regulator GPIOs right out of device
+tree nodes.
+
+Suggested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Fixes: b0ce7b29bfcd ("regulator/gpio: Allow nonexclusive GPIO access")
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ drivers/gpio/gpiolib.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -4062,6 +4062,8 @@ struct gpio_desc *gpiod_get_from_of_node
+       transitory = flags & OF_GPIO_TRANSITORY;
+       ret = gpiod_request(desc, label);
++      if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
++              return desc;
+       if (ret)
+               return ERR_PTR(ret);
diff --git a/target/linux/brcm2708/patches-4.19/950-0699-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch b/target/linux/brcm2708/patches-4.19/950-0699-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch
deleted file mode 100644 (file)
index 36c5d1c..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-From 956fd55c1071c48f00285d82507698c501633e7a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 13 Sep 2019 15:11:47 +0100
-Subject: [PATCH] staging: bcm2835-codec: Correct g/s_selection API
- MPLANE support
-
-The g_selection and s_selection API is messed up and requires
-the driver to expect the non-MPLANE buffer types, not the MPLANE
-ones even if they are supported. The V4L2 core will convert the
-MPLANE ones to non-MPLANE should they be passed in
-
-Fixes: 5e484a3 staging: bcm2835-codec: switch to multi-planar API
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 67 +++++++++++++------
- 1 file changed, 47 insertions(+), 20 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1260,17 +1260,30 @@ static int vidioc_g_selection(struct fil
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
-       struct bcm2835_codec_q_data *q_data;
--      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
--                                                              true : false;
--      if ((ctx->dev->role == DECODE && !capture_queue) ||
--          (ctx->dev->role == ENCODE && capture_queue))
--              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
--              return -EINVAL;
--
--      q_data = get_q_data(ctx, s->type);
--      if (!q_data)
-+      /*
-+       * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
-+       * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
-+       * API. The V4L2 core will have converted the MPLANE variants to
-+       * non-MPLANE.
-+       * Open code this instead of using get_q_data in this case.
-+       */
-+      switch (s->type) {
-+      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+              /* CAPTURE on encoder is not valid. */
-+              if (ctx->dev->role == ENCODE)
-+                      return -EINVAL;
-+              q_data = &ctx->q_data[V4L2_M2M_DST];
-+              break;
-+      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+              /* OUTPUT on deoder is not valid. */
-+              if (ctx->dev->role == DECODE)
-+                      return -EINVAL;
-+              q_data = &ctx->q_data[V4L2_M2M_SRC];
-+              break;
-+      default:
-               return -EINVAL;
-+      }
-       switch (ctx->dev->role) {
-       case DECODE:
-@@ -1323,22 +1336,36 @@ static int vidioc_s_selection(struct fil
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
-       struct bcm2835_codec_q_data *q_data = NULL;
--      bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
--                                                              true : false;
-+
-+      /*
-+       * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
-+       * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
-+       * API. The V4L2 core will have converted the MPLANE variants to
-+       * non-MPLANE.
-+       *
-+       * Open code this instead of using get_q_data in this case.
-+       */
-+      switch (s->type) {
-+      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+              /* CAPTURE on encoder is not valid. */
-+              if (ctx->dev->role == ENCODE)
-+                      return -EINVAL;
-+              q_data = &ctx->q_data[V4L2_M2M_DST];
-+              break;
-+      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+              /* OUTPUT on deoder is not valid. */
-+              if (ctx->dev->role == DECODE)
-+                      return -EINVAL;
-+              q_data = &ctx->q_data[V4L2_M2M_SRC];
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
-                __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
-                s->r.width, s->r.height);
--      if ((ctx->dev->role == DECODE && !capture_queue) ||
--          (ctx->dev->role == ENCODE && capture_queue))
--              /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
--              return -EINVAL;
--
--      q_data = get_q_data(ctx, s->type);
--      if (!q_data)
--              return -EINVAL;
--
-       switch (ctx->dev->role) {
-       case DECODE:
-               switch (s->target) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0700-Fix-poll-rate-on-touchscreen-3238.patch b/target/linux/brcm2708/patches-4.19/950-0700-Fix-poll-rate-on-touchscreen-3238.patch
new file mode 100644 (file)
index 0000000..b47c819
--- /dev/null
@@ -0,0 +1,29 @@
+From a37a706547897d77b3194fc507b2546197def430 Mon Sep 17 00:00:00 2001
+From: James Hughes <JamesH65@users.noreply.github.com>
+Date: Tue, 17 Sep 2019 16:22:09 +0100
+Subject: [PATCH] Fix poll rate on touchscreen (#3238)
+
+Was running at 25Hz, rather than he expected 60. Only been doing it
+for the last 5 years....
+
+Replace msleep_interruptible with usleep_range as the msleep call
+is not accurate for times < 20ms.
+
+Fixes: https://github.com/raspberrypi/linux/issues/3227
+
+Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
+---
+ drivers/input/touchscreen/rpi-ft5406.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/input/touchscreen/rpi-ft5406.c
++++ b/drivers/input/touchscreen/rpi-ft5406.c
+@@ -78,7 +78,7 @@ static int ft5406_thread(void *arg)
+       while (!kthread_should_stop()) {
+               /* 60fps polling */
+-              msleep_interruptible(17);
++              usleep_range(16600, 16700);
+               memcpy_fromio(&regs, ts->ts_base, sizeof(struct ft5406_regs));
+               iowrite8(99,
+                        ts->ts_base +
diff --git a/target/linux/brcm2708/patches-4.19/950-0700-regulator-gpio-Allow-nonexclusive-GPIO-access.patch b/target/linux/brcm2708/patches-4.19/950-0700-regulator-gpio-Allow-nonexclusive-GPIO-access.patch
deleted file mode 100644 (file)
index a940736..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-From f6d983b7bc9ae79d0eb4dea7bc30a1ad5ff428a7 Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Fri, 12 Oct 2018 14:54:12 +0200
-Subject: [PATCH] regulator/gpio: Allow nonexclusive GPIO access
-
-commit b0ce7b29bfcd090ddba476f45a75ec0a797b048a upstream.
-
-[ This is a partial cherry-pick, omitting the regulator
-change which isn't required ]
-
-This allows nonexclusive (simultaneous) access to a single
-GPIO line for the fixed regulator enable line. This happens
-when several regulators use the same GPIO for enabling and
-disabling a regulator, and all need a handle on their GPIO
-descriptor.
-
-This solution with a special flag is not entirely elegant
-and should ideally be replaced by something more careful as
-this makes it possible for several consumers to
-enable/disable the same GPIO line to the left and right
-without any consistency. The current use inside the regulator
-core should however be fine as it takes special care to
-handle this.
-
-For the state of the GPIO backend, this is still the
-lesser evil compared to going back to global GPIO
-numbers.
-
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Jon Hunter <jonathanh@nvidia.com>
-Fixes: efdfeb079cc3 ("regulator: fixed: Convert to use GPIO descriptor only")
-Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Tested-by: Jon Hunter <jonathanh@nvidia.com>
-Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- drivers/gpio/gpiolib.c        | 19 +++++++++++++++++--
- include/linux/gpio/consumer.h |  1 +
- 2 files changed, 18 insertions(+), 2 deletions(-)
-
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -3988,8 +3988,23 @@ struct gpio_desc *__must_check gpiod_get
-        * the device name as label
-        */
-       status = gpiod_request(desc, con_id ? con_id : devname);
--      if (status < 0)
--              return ERR_PTR(status);
-+      if (status < 0) {
-+              if (status == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
-+                      /*
-+                       * This happens when there are several consumers for
-+                       * the same GPIO line: we just return here without
-+                       * further initialization. It is a bit if a hack.
-+                       * This is necessary to support fixed regulators.
-+                       *
-+                       * FIXME: Make this more sane and safe.
-+                       */
-+                      dev_info(dev, "nonexclusive access to GPIO for %s\n",
-+                               con_id ? con_id : devname);
-+                      return desc;
-+              } else {
-+                      return ERR_PTR(status);
-+              }
-+      }
-       status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
-       if (status < 0) {
---- a/include/linux/gpio/consumer.h
-+++ b/include/linux/gpio/consumer.h
-@@ -30,6 +30,7 @@ struct gpio_descs {
- #define GPIOD_FLAGS_BIT_DIR_OUT               BIT(1)
- #define GPIOD_FLAGS_BIT_DIR_VAL               BIT(2)
- #define GPIOD_FLAGS_BIT_OPEN_DRAIN    BIT(3)
-+#define GPIOD_FLAGS_BIT_NONEXCLUSIVE  BIT(4)
- /**
-  * Optional flags that can be passed to one of gpiod_* to configure direction
diff --git a/target/linux/brcm2708/patches-4.19/950-0701-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch b/target/linux/brcm2708/patches-4.19/950-0701-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch
new file mode 100644 (file)
index 0000000..1f690a2
--- /dev/null
@@ -0,0 +1,171 @@
+From 75967d69ea58555d12a7d9058653a69210d2ba86 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <pelwell@users.noreply.github.com>
+Date: Wed, 18 Sep 2019 09:02:10 +0100
+Subject: [PATCH] dts: Add DTS for Pi 2B rev 1.2 with BCM2837 (#3235)
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile                    |   1 +
+ arch/arm/boot/dts/bcm2710-rpi-2-b.dts         | 125 ++++++++++++++++++
+ arch/arm64/boot/dts/broadcom/Makefile         |   2 +
+ .../boot/dts/broadcom/bcm2710-rpi-2-b.dts     |   3 +
+ 4 files changed, 131 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2710-rpi-2-b.dts
+ create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-2-b.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2708-rpi-zero.dtb \
+       bcm2708-rpi-zero-w.dtb \
+       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 \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2710-rpi-2-b.dts
+@@ -0,0 +1,125 @@
++/dts-v1/;
++
++#include "bcm2710.dtsi"
++#include "bcm2709-rpi.dtsi"
++#include "bcm283x-rpi-smsc9514.dtsi"
++#include "bcm283x-rpi-csi1-2lane.dtsi"
++
++/ {
++      compatible = "raspberrypi,2-model-b-rev2", "brcm,bcm2837";
++      model = "Raspberry Pi 2 Model B rev 1.2";
++};
++
++&gpio {
++      spi0_pins: spi0_pins {
++              brcm,pins = <9 10 11>;
++              brcm,function = <4>; /* alt0 */
++      };
++
++      spi0_cs_pins: spi0_cs_pins {
++              brcm,pins = <8 7>;
++              brcm,function = <1>; /* output */
++      };
++
++      i2c0_pins: i2c0 {
++              brcm,pins = <0 1>;
++              brcm,function = <4>;
++      };
++
++      i2c1_pins: i2c1 {
++              brcm,pins = <2 3>;
++              brcm,function = <4>;
++      };
++
++      i2s_pins: i2s {
++              brcm,pins = <18 19 20 21>;
++              brcm,function = <4>; /* alt0 */
++      };
++
++      audio_pins: audio_pins {
++              brcm,pins = <40 45>;
++              brcm,function = <4>;
++      };
++};
++
++&uart0 {
++      status = "okay";
++};
++
++&spi0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
++      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
++
++      spidev0: spidev@0{
++              compatible = "spidev";
++              reg = <0>;      /* CE0 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++
++      spidev1: spidev@1{
++              compatible = "spidev";
++              reg = <1>;      /* CE1 */
++              #address-cells = <1>;
++              #size-cells = <0>;
++              spi-max-frequency = <125000000>;
++      };
++};
++
++&i2c0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c0_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2c1_pins>;
++      clock-frequency = <100000>;
++};
++
++&i2c2 {
++      clock-frequency = <100000>;
++};
++
++&i2s {
++      pinctrl-names = "default";
++      pinctrl-0 = <&i2s_pins>;
++};
++
++&leds {
++      act_led: act {
++              label = "led0";
++              linux,default-trigger = "mmc0";
++              gpios = <&gpio 47 0>;
++      };
++
++      pwr_led: pwr {
++              label = "led1";
++              linux,default-trigger = "input";
++              gpios = <&gpio 35 0>;
++      };
++};
++
++&hdmi {
++      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++};
++
++&audio {
++      pinctrl-names = "default";
++      pinctrl-0 = <&audio_pins>;
++};
++
++/ {
++      __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";
++      };
++};
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -1,7 +1,9 @@
+ # SPDX-License-Identifier: GPL-2.0
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb \
+                             bcm2837-rpi-3-b-plus.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
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
+--- /dev/null
++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-2-b.dts
+@@ -0,0 +1,3 @@
++#define RPI364
++
++#include "../../../../arm/boot/dts/bcm2710-rpi-2-b.dts"
diff --git a/target/linux/brcm2708/patches-4.19/950-0701-gpio-Enable-nonexclusive-gpiods-from-DT-nodes.patch b/target/linux/brcm2708/patches-4.19/950-0701-gpio-Enable-nonexclusive-gpiods-from-DT-nodes.patch
deleted file mode 100644 (file)
index a4139e6..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 76870d237adff4c8e419064e7d4f5a8ef87c1085 Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Thu, 6 Dec 2018 13:43:44 +0100
-Subject: [PATCH] gpio: Enable nonexclusive gpiods from DT nodes
-
-commit ec757001c818c175e6b610e8ef80c2a25d1ed1a5 upstream.
-
-This makes gpiod_get_from_of_node() respect the
-GPIOD_FLAGS_BIT_NONEXCLUSIVE flag which is especially
-nice when getting regulator GPIOs right out of device
-tree nodes.
-
-Suggested-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Fixes: b0ce7b29bfcd ("regulator/gpio: Allow nonexclusive GPIO access")
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- drivers/gpio/gpiolib.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -4062,6 +4062,8 @@ struct gpio_desc *gpiod_get_from_of_node
-       transitory = flags & OF_GPIO_TRANSITORY;
-       ret = gpiod_request(desc, label);
-+      if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
-+              return desc;
-       if (ret)
-               return ERR_PTR(ret);
diff --git a/target/linux/brcm2708/patches-4.19/950-0702-Fix-poll-rate-on-touchscreen-3238.patch b/target/linux/brcm2708/patches-4.19/950-0702-Fix-poll-rate-on-touchscreen-3238.patch
deleted file mode 100644 (file)
index b47c819..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From a37a706547897d77b3194fc507b2546197def430 Mon Sep 17 00:00:00 2001
-From: James Hughes <JamesH65@users.noreply.github.com>
-Date: Tue, 17 Sep 2019 16:22:09 +0100
-Subject: [PATCH] Fix poll rate on touchscreen (#3238)
-
-Was running at 25Hz, rather than he expected 60. Only been doing it
-for the last 5 years....
-
-Replace msleep_interruptible with usleep_range as the msleep call
-is not accurate for times < 20ms.
-
-Fixes: https://github.com/raspberrypi/linux/issues/3227
-
-Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
----
- drivers/input/touchscreen/rpi-ft5406.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/input/touchscreen/rpi-ft5406.c
-+++ b/drivers/input/touchscreen/rpi-ft5406.c
-@@ -78,7 +78,7 @@ static int ft5406_thread(void *arg)
-       while (!kthread_should_stop()) {
-               /* 60fps polling */
--              msleep_interruptible(17);
-+              usleep_range(16600, 16700);
-               memcpy_fromio(&regs, ts->ts_base, sizeof(struct ft5406_regs));
-               iowrite8(99,
-                        ts->ts_base +
diff --git a/target/linux/brcm2708/patches-4.19/950-0702-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch b/target/linux/brcm2708/patches-4.19/950-0702-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch
new file mode 100644 (file)
index 0000000..ff7c346
--- /dev/null
@@ -0,0 +1,177 @@
+From bc4661703d132ae1fb91d66641c64851eae44959 Mon Sep 17 00:00:00 2001
+From: Iago Toral Quiroga <itoral@igalia.com>
+Date: Tue, 3 Sep 2019 08:45:24 +0200
+Subject: [PATCH] drm/v3d: clean caches at the end of render jobs on
+ request from user space
+
+Extends the user space ioctl for CL submissions so it can include a request
+to flush the cache once the CL execution has completed. Fixes memory
+write violation messages reported by the kernel in workloads involving
+shader memory writes (SSBOs, shader images, scratch, etc) which sometimes
+also lead to GPU resets during Piglit and CTS workloads.
+
+v2: if v3d_job_init() fails we need to kfree() the job instead of
+    v3d_job_put() it (Eric Anholt).
+
+v3 (Eric Anholt):
+  - Drop _FLAG suffix from the new flag name.
+  - Add a new param so userspace can tell whether cache flushing is
+    implemented in the kernel.
+
+Signed-off-by: Iago Toral Quiroga <itoral@igalia.com>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c |  3 ++
+ drivers/gpu/drm/v3d/v3d_gem.c | 54 +++++++++++++++++++++++++++++------
+ include/uapi/drm/v3d_drm.h    |  6 ++--
+ 3 files changed, 53 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -117,6 +117,9 @@ static int v3d_get_param_ioctl(struct dr
+       case DRM_V3D_PARAM_SUPPORTS_CSD:
+               args->value = v3d_has_csd(v3d);
+               return 0;
++      case DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH:
++              args->value = 1;
++              return 0;
+       default:
+               DRM_DEBUG("Unknown parameter %d\n", args->param);
+               return -EINVAL;
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -709,13 +709,16 @@ v3d_submit_cl_ioctl(struct drm_device *d
+       struct drm_v3d_submit_cl *args = data;
+       struct v3d_bin_job *bin = NULL;
+       struct v3d_render_job *render;
++      struct v3d_job *clean_job = NULL;
++      struct v3d_job *last_job;
+       struct ww_acquire_ctx acquire_ctx;
+       int ret = 0;
+       trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
+-      if (args->pad != 0) {
+-              DRM_INFO("pad must be zero: %d\n", args->pad);
++      if (args->flags != 0 &&
++          args->flags != DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
++              DRM_INFO("invalid flags: %d\n", args->flags);
+               return -EINVAL;
+       }
+@@ -755,12 +758,31 @@ v3d_submit_cl_ioctl(struct drm_device *d
+               bin->render = render;
+       }
+-      ret = v3d_lookup_bos(dev, file_priv, &render->base,
++      if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
++              clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
++              if (!clean_job) {
++                      ret = -ENOMEM;
++                      goto fail;
++              }
++
++              ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
++              if (ret) {
++                      kfree(clean_job);
++                      clean_job = NULL;
++                      goto fail;
++              }
++
++              last_job = clean_job;
++      } else {
++              last_job = &render->base;
++      }
++
++      ret = v3d_lookup_bos(dev, file_priv, last_job,
+                            args->bo_handles, args->bo_handle_count);
+       if (ret)
+               goto fail;
+-      ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
++      ret = v3d_lock_bo_reservations(last_job, &acquire_ctx);
+       if (ret)
+               goto fail;
+@@ -772,33 +794,49 @@ v3d_submit_cl_ioctl(struct drm_device *d
+               ret = v3d_add_dep(&render->base,
+                                 dma_fence_get(bin->base.done_fence));
++              if (ret)
++                      goto fail_unreserve;
+       }
+       ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
+       if (ret)
+               goto fail_unreserve;
++
++      if (clean_job) {
++              ret = v3d_add_dep(clean_job,
++                                dma_fence_get(render->base.done_fence));
++              if (ret)
++                      goto fail_unreserve;
++              ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
++              if (ret)
++                      goto fail_unreserve;
++      }
+       mutex_unlock(&v3d->sched_lock);
+       v3d_attach_fences_and_unlock_reservation(file_priv,
+-                                               &render->base,
++                                               last_job,
+                                                &acquire_ctx,
+                                                args->out_sync,
+-                                               render->base.done_fence);
++                                               last_job->done_fence);
+       if (bin)
+               v3d_job_put(&bin->base);
+       v3d_job_put(&render->base);
++      if (clean_job)
++              v3d_job_put(clean_job);
+       return 0;
+ fail_unreserve:
+       mutex_unlock(&v3d->sched_lock);
+-      v3d_unlock_bo_reservations(render->base.bo,
+-                                 render->base.bo_count, &acquire_ctx);
++      v3d_unlock_bo_reservations(last_job->bo,
++                                 last_job->bo_count, &acquire_ctx);
+ fail:
+       if (bin)
+               v3d_job_put(&bin->base);
+       v3d_job_put(&render->base);
++      if (clean_job)
++              v3d_job_put(clean_job);
+       return ret;
+ }
+--- a/include/uapi/drm/v3d_drm.h
++++ b/include/uapi/drm/v3d_drm.h
+@@ -48,6 +48,8 @@ extern "C" {
+ #define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
+ #define DRM_IOCTL_V3D_SUBMIT_CSD          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
++#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE             0x01
++
+ /**
+  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
+  * engine.
+@@ -106,8 +108,7 @@ struct drm_v3d_submit_cl {
+       /* Number of BO handles passed in (size is that times 4). */
+       __u32 bo_handle_count;
+-      /* Pad, must be zero-filled. */
+-      __u32 pad;
++      __u32 flags;
+ };
+ /**
+@@ -175,6 +176,7 @@ enum drm_v3d_param {
+       DRM_V3D_PARAM_V3D_CORE0_IDENT2,
+       DRM_V3D_PARAM_SUPPORTS_TFU,
+       DRM_V3D_PARAM_SUPPORTS_CSD,
++      DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
+ };
+ struct drm_v3d_get_param {
diff --git a/target/linux/brcm2708/patches-4.19/950-0703-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch b/target/linux/brcm2708/patches-4.19/950-0703-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch
deleted file mode 100644 (file)
index 1f690a2..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-From 75967d69ea58555d12a7d9058653a69210d2ba86 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <pelwell@users.noreply.github.com>
-Date: Wed, 18 Sep 2019 09:02:10 +0100
-Subject: [PATCH] dts: Add DTS for Pi 2B rev 1.2 with BCM2837 (#3235)
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile                    |   1 +
- arch/arm/boot/dts/bcm2710-rpi-2-b.dts         | 125 ++++++++++++++++++
- arch/arm64/boot/dts/broadcom/Makefile         |   2 +
- .../boot/dts/broadcom/bcm2710-rpi-2-b.dts     |   3 +
- 4 files changed, 131 insertions(+)
- create mode 100644 arch/arm/boot/dts/bcm2710-rpi-2-b.dts
- create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-2-b.dts
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
-       bcm2708-rpi-zero.dtb \
-       bcm2708-rpi-zero-w.dtb \
-       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 \
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2710-rpi-2-b.dts
-@@ -0,0 +1,125 @@
-+/dts-v1/;
-+
-+#include "bcm2710.dtsi"
-+#include "bcm2709-rpi.dtsi"
-+#include "bcm283x-rpi-smsc9514.dtsi"
-+#include "bcm283x-rpi-csi1-2lane.dtsi"
-+
-+/ {
-+      compatible = "raspberrypi,2-model-b-rev2", "brcm,bcm2837";
-+      model = "Raspberry Pi 2 Model B rev 1.2";
-+};
-+
-+&gpio {
-+      spi0_pins: spi0_pins {
-+              brcm,pins = <9 10 11>;
-+              brcm,function = <4>; /* alt0 */
-+      };
-+
-+      spi0_cs_pins: spi0_cs_pins {
-+              brcm,pins = <8 7>;
-+              brcm,function = <1>; /* output */
-+      };
-+
-+      i2c0_pins: i2c0 {
-+              brcm,pins = <0 1>;
-+              brcm,function = <4>;
-+      };
-+
-+      i2c1_pins: i2c1 {
-+              brcm,pins = <2 3>;
-+              brcm,function = <4>;
-+      };
-+
-+      i2s_pins: i2s {
-+              brcm,pins = <18 19 20 21>;
-+              brcm,function = <4>; /* alt0 */
-+      };
-+
-+      audio_pins: audio_pins {
-+              brcm,pins = <40 45>;
-+              brcm,function = <4>;
-+      };
-+};
-+
-+&uart0 {
-+      status = "okay";
-+};
-+
-+&spi0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
-+      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
-+
-+      spidev0: spidev@0{
-+              compatible = "spidev";
-+              reg = <0>;      /* CE0 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+
-+      spidev1: spidev@1{
-+              compatible = "spidev";
-+              reg = <1>;      /* CE1 */
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              spi-max-frequency = <125000000>;
-+      };
-+};
-+
-+&i2c0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c0_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2c1_pins>;
-+      clock-frequency = <100000>;
-+};
-+
-+&i2c2 {
-+      clock-frequency = <100000>;
-+};
-+
-+&i2s {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2s_pins>;
-+};
-+
-+&leds {
-+      act_led: act {
-+              label = "led0";
-+              linux,default-trigger = "mmc0";
-+              gpios = <&gpio 47 0>;
-+      };
-+
-+      pwr_led: pwr {
-+              label = "led1";
-+              linux,default-trigger = "input";
-+              gpios = <&gpio 35 0>;
-+      };
-+};
-+
-+&hdmi {
-+      hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+};
-+
-+&audio {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&audio_pins>;
-+};
-+
-+/ {
-+      __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";
-+      };
-+};
---- a/arch/arm64/boot/dts/broadcom/Makefile
-+++ b/arch/arm64/boot/dts/broadcom/Makefile
-@@ -1,7 +1,9 @@
- # SPDX-License-Identifier: GPL-2.0
- dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb \
-                             bcm2837-rpi-3-b-plus.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
- dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
---- /dev/null
-+++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-2-b.dts
-@@ -0,0 +1,3 @@
-+#define RPI364
-+
-+#include "../../../../arm/boot/dts/bcm2710-rpi-2-b.dts"
diff --git a/target/linux/brcm2708/patches-4.19/950-0703-staging-bcm2835-audio-Fix-draining-behavior-regressi.patch b/target/linux/brcm2708/patches-4.19/950-0703-staging-bcm2835-audio-Fix-draining-behavior-regressi.patch
new file mode 100644 (file)
index 0000000..76279ec
--- /dev/null
@@ -0,0 +1,56 @@
+From 9dd926d29051324d8621ca2a18bbdd568523ac93 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 14 Sep 2019 17:24:05 +0200
+Subject: [PATCH] staging: bcm2835-audio: Fix draining behavior
+ regression
+
+The PCM draining behavior got broken since the recent refactoring, and
+this turned out to be the incorrect expectation of the firmware
+behavior regarding "draining".  While I expected the "drain" flag at
+the stop operation would do processing the queued samples, it seems
+rather dropping the samples.
+
+As a quick fix, just drop the SNDRV_PCM_INFO_DRAIN_TRIGGER flag, so
+that the driver uses the normal PCM draining procedure.  Also, put
+some caution comment to the function for future readers not to fall
+into the same pitfall.
+
+Fixes: d7ca3a71545b ("staging: bcm2835-audio: Operate non-atomic PCM ops")
+BugLink: https://github.com/raspberrypi/linux/issues/2983
+Cc: stable@vger.kernel.org
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c   | 4 ++--
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 1 +
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -12,7 +12,7 @@
+ static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+-               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
++               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,
+       .rate_min = 8000,
+@@ -29,7 +29,7 @@ static const struct snd_pcm_hardware snd
+ static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+-               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
++               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 |
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -297,6 +297,7 @@ int bcm2835_audio_stop(struct bcm2835_al
+                                        VC_AUDIO_MSG_TYPE_STOP, false);
+ }
++/* FIXME: this doesn't seem working as expected for "draining" */
+ int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
+ {
+       struct vc_audio_msg m = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0704-bcm2708_fb-Fix-layout-of-struct-vc4_display_settings.patch b/target/linux/brcm2708/patches-4.19/950-0704-bcm2708_fb-Fix-layout-of-struct-vc4_display_settings.patch
new file mode 100644 (file)
index 0000000..adb14fb
--- /dev/null
@@ -0,0 +1,34 @@
+From c6be127c2f4d5f75c60d3778594093ff51593a6e Mon Sep 17 00:00:00 2001
+From: Michael Brown <mbrown@fensystems.co.uk>
+Date: Sun, 22 Sep 2019 21:51:29 +0100
+Subject: [PATCH] bcm2708_fb: Fix layout of struct
+ vc4_display_settings_t
+
+The display parameters returned by the VC4 firmware in response to the
+RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS tag do not match the
+layout of struct vc4_display_settings_t: the colour depth and row
+pitch are erroneously swapped in the kernel definition.  This can
+trigger a kernel warning from pixel_to_pat(), such as:
+
+  pixel_to_pat(): unsupported pixelformat 7296
+
+Fix by adjusting the layout of struct vc4_display_settings_t to match
+the layout as used by the VC4 firmware.
+
+Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -89,8 +89,8 @@ struct vc4_display_settings_t {
+       u32 display_num;
+       u32 width;
+       u32 height;
+-      u32 pitch;
+       u32 depth;
++      u32 pitch;
+       u32 virtual_width;
+       u32 virtual_height;
+       u32 virtual_width_offset;
diff --git a/target/linux/brcm2708/patches-4.19/950-0704-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch b/target/linux/brcm2708/patches-4.19/950-0704-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch
deleted file mode 100644 (file)
index ff7c346..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-From bc4661703d132ae1fb91d66641c64851eae44959 Mon Sep 17 00:00:00 2001
-From: Iago Toral Quiroga <itoral@igalia.com>
-Date: Tue, 3 Sep 2019 08:45:24 +0200
-Subject: [PATCH] drm/v3d: clean caches at the end of render jobs on
- request from user space
-
-Extends the user space ioctl for CL submissions so it can include a request
-to flush the cache once the CL execution has completed. Fixes memory
-write violation messages reported by the kernel in workloads involving
-shader memory writes (SSBOs, shader images, scratch, etc) which sometimes
-also lead to GPU resets during Piglit and CTS workloads.
-
-v2: if v3d_job_init() fails we need to kfree() the job instead of
-    v3d_job_put() it (Eric Anholt).
-
-v3 (Eric Anholt):
-  - Drop _FLAG suffix from the new flag name.
-  - Add a new param so userspace can tell whether cache flushing is
-    implemented in the kernel.
-
-Signed-off-by: Iago Toral Quiroga <itoral@igalia.com>
----
- drivers/gpu/drm/v3d/v3d_drv.c |  3 ++
- drivers/gpu/drm/v3d/v3d_gem.c | 54 +++++++++++++++++++++++++++++------
- include/uapi/drm/v3d_drm.h    |  6 ++--
- 3 files changed, 53 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -117,6 +117,9 @@ static int v3d_get_param_ioctl(struct dr
-       case DRM_V3D_PARAM_SUPPORTS_CSD:
-               args->value = v3d_has_csd(v3d);
-               return 0;
-+      case DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH:
-+              args->value = 1;
-+              return 0;
-       default:
-               DRM_DEBUG("Unknown parameter %d\n", args->param);
-               return -EINVAL;
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -709,13 +709,16 @@ v3d_submit_cl_ioctl(struct drm_device *d
-       struct drm_v3d_submit_cl *args = data;
-       struct v3d_bin_job *bin = NULL;
-       struct v3d_render_job *render;
-+      struct v3d_job *clean_job = NULL;
-+      struct v3d_job *last_job;
-       struct ww_acquire_ctx acquire_ctx;
-       int ret = 0;
-       trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
--      if (args->pad != 0) {
--              DRM_INFO("pad must be zero: %d\n", args->pad);
-+      if (args->flags != 0 &&
-+          args->flags != DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
-+              DRM_INFO("invalid flags: %d\n", args->flags);
-               return -EINVAL;
-       }
-@@ -755,12 +758,31 @@ v3d_submit_cl_ioctl(struct drm_device *d
-               bin->render = render;
-       }
--      ret = v3d_lookup_bos(dev, file_priv, &render->base,
-+      if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
-+              clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
-+              if (!clean_job) {
-+                      ret = -ENOMEM;
-+                      goto fail;
-+              }
-+
-+              ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
-+              if (ret) {
-+                      kfree(clean_job);
-+                      clean_job = NULL;
-+                      goto fail;
-+              }
-+
-+              last_job = clean_job;
-+      } else {
-+              last_job = &render->base;
-+      }
-+
-+      ret = v3d_lookup_bos(dev, file_priv, last_job,
-                            args->bo_handles, args->bo_handle_count);
-       if (ret)
-               goto fail;
--      ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
-+      ret = v3d_lock_bo_reservations(last_job, &acquire_ctx);
-       if (ret)
-               goto fail;
-@@ -772,33 +794,49 @@ v3d_submit_cl_ioctl(struct drm_device *d
-               ret = v3d_add_dep(&render->base,
-                                 dma_fence_get(bin->base.done_fence));
-+              if (ret)
-+                      goto fail_unreserve;
-       }
-       ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
-       if (ret)
-               goto fail_unreserve;
-+
-+      if (clean_job) {
-+              ret = v3d_add_dep(clean_job,
-+                                dma_fence_get(render->base.done_fence));
-+              if (ret)
-+                      goto fail_unreserve;
-+              ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
-+              if (ret)
-+                      goto fail_unreserve;
-+      }
-       mutex_unlock(&v3d->sched_lock);
-       v3d_attach_fences_and_unlock_reservation(file_priv,
--                                               &render->base,
-+                                               last_job,
-                                                &acquire_ctx,
-                                                args->out_sync,
--                                               render->base.done_fence);
-+                                               last_job->done_fence);
-       if (bin)
-               v3d_job_put(&bin->base);
-       v3d_job_put(&render->base);
-+      if (clean_job)
-+              v3d_job_put(clean_job);
-       return 0;
- fail_unreserve:
-       mutex_unlock(&v3d->sched_lock);
--      v3d_unlock_bo_reservations(render->base.bo,
--                                 render->base.bo_count, &acquire_ctx);
-+      v3d_unlock_bo_reservations(last_job->bo,
-+                                 last_job->bo_count, &acquire_ctx);
- fail:
-       if (bin)
-               v3d_job_put(&bin->base);
-       v3d_job_put(&render->base);
-+      if (clean_job)
-+              v3d_job_put(clean_job);
-       return ret;
- }
---- a/include/uapi/drm/v3d_drm.h
-+++ b/include/uapi/drm/v3d_drm.h
-@@ -48,6 +48,8 @@ extern "C" {
- #define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
- #define DRM_IOCTL_V3D_SUBMIT_CSD          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
-+#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE             0x01
-+
- /**
-  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
-  * engine.
-@@ -106,8 +108,7 @@ struct drm_v3d_submit_cl {
-       /* Number of BO handles passed in (size is that times 4). */
-       __u32 bo_handle_count;
--      /* Pad, must be zero-filled. */
--      __u32 pad;
-+      __u32 flags;
- };
- /**
-@@ -175,6 +176,7 @@ enum drm_v3d_param {
-       DRM_V3D_PARAM_V3D_CORE0_IDENT2,
-       DRM_V3D_PARAM_SUPPORTS_TFU,
-       DRM_V3D_PARAM_SUPPORTS_CSD,
-+      DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
- };
- struct drm_v3d_get_param {
diff --git a/target/linux/brcm2708/patches-4.19/950-0705-ARM-dts-bcm283x-Fix-DTC-warning-for-memory-node.patch b/target/linux/brcm2708/patches-4.19/950-0705-ARM-dts-bcm283x-Fix-DTC-warning-for-memory-node.patch
new file mode 100644 (file)
index 0000000..b593d7f
--- /dev/null
@@ -0,0 +1,68 @@
+From b640129382a37105cf2577f251103e550381b797 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 23 Sep 2019 18:56:37 +0200
+Subject: [PATCH] ARM: dts: bcm283x: Fix DTC warning for memory node
+
+commit f090e1bd7b05f17d35b6e2d0e946d8a8085d264f upstream.
+
+Compiling the bcm283x DTS with W=1 leads to the following warning:
+
+Warning (unit_address_vs_reg): /memory: node has a reg or ranges property,
+but no unit name
+
+Fix this by adding the unit address.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Tested-by: Peter Robinson <pbrobinson@gmail.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+---
+ arch/arm/boot/dts/bcm2835-rpi.dtsi         | 2 +-
+ arch/arm/boot/dts/bcm2836-rpi-2-b.dts      | 2 +-
+ arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
+ arch/arm/boot/dts/bcm2837-rpi-3-b.dts      | 2 +-
+ 4 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -1,7 +1,7 @@
+ #include <dt-bindings/power/raspberrypi-power.h>
+ / {
+-      memory {
++      memory@0 {
+               device_type = "memory";
+               reg = <0 0x10000000>;
+       };
+--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+@@ -10,7 +10,7 @@
+       compatible = "raspberrypi,2-model-b", "brcm,bcm2836";
+       model = "Raspberry Pi 2 Model B";
+-      memory {
++      memory@0 {
+               reg = <0 0x40000000>;
+       };
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+@@ -14,7 +14,7 @@
+               stdout-path = "serial1:115200n8";
+       };
+-      memory {
++      memory@0 {
+               reg = <0 0x40000000>;
+       };
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+@@ -15,7 +15,7 @@
+               stdout-path = "serial1:115200n8";
+       };
+-      memory {
++      memory@0 {
+               reg = <0 0x40000000>;
+       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0705-staging-bcm2835-audio-Fix-draining-behavior-regressi.patch b/target/linux/brcm2708/patches-4.19/950-0705-staging-bcm2835-audio-Fix-draining-behavior-regressi.patch
deleted file mode 100644 (file)
index 76279ec..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 9dd926d29051324d8621ca2a18bbdd568523ac93 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Sat, 14 Sep 2019 17:24:05 +0200
-Subject: [PATCH] staging: bcm2835-audio: Fix draining behavior
- regression
-
-The PCM draining behavior got broken since the recent refactoring, and
-this turned out to be the incorrect expectation of the firmware
-behavior regarding "draining".  While I expected the "drain" flag at
-the stop operation would do processing the queued samples, it seems
-rather dropping the samples.
-
-As a quick fix, just drop the SNDRV_PCM_INFO_DRAIN_TRIGGER flag, so
-that the driver uses the normal PCM draining procedure.  Also, put
-some caution comment to the function for future readers not to fall
-into the same pitfall.
-
-Fixes: d7ca3a71545b ("staging: bcm2835-audio: Operate non-atomic PCM ops")
-BugLink: https://github.com/raspberrypi/linux/issues/2983
-Cc: stable@vger.kernel.org
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c   | 4 ++--
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 1 +
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -12,7 +12,7 @@
- static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
--               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
-+               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,
-       .rate_min = 8000,
-@@ -29,7 +29,7 @@ static const struct snd_pcm_hardware snd
- static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
--               SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
-+               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 |
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -297,6 +297,7 @@ int bcm2835_audio_stop(struct bcm2835_al
-                                        VC_AUDIO_MSG_TYPE_STOP, false);
- }
-+/* FIXME: this doesn't seem working as expected for "draining" */
- int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
- {
-       struct vc_audio_msg m = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0706-ARM-dts-bcm27xx-Fix-DTC-warning-for-memory-node.patch b/target/linux/brcm2708/patches-4.19/950-0706-ARM-dts-bcm27xx-Fix-DTC-warning-for-memory-node.patch
new file mode 100644 (file)
index 0000000..3a424b3
--- /dev/null
@@ -0,0 +1,52 @@
+From 10524e83179ad016a379ea99364d6912812a9aa5 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 23 Sep 2019 20:09:12 +0200
+Subject: [PATCH] ARM: dts: bcm27xx: Fix DTC warning for memory node
+
+Compiling the bcm27xx DTS with W=1 leads to the following warning:
+
+Warning (unit_address_vs_reg): /memory: node has a reg or ranges property,
+but no unit name
+
+Fix this by adding the unit address.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi    | 2 +-
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
+ arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -3,7 +3,7 @@
+ #include "bcm2835-rpi.dtsi"
+ / {
+-      memory {
++      memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0>;
+       };
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -8,7 +8,7 @@
+       compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
+       model = "Raspberry Pi 4 Model B";
+-      memory {
++      memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0 0x0>;
+       };
+--- a/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
+@@ -13,7 +13,7 @@
+               stdout-path = "serial1:115200n8";
+       };
+-      memory {
++      memory@0 {
+               reg = <0 0 0x40000000>;
+       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0706-bcm2708_fb-Fix-layout-of-struct-vc4_display_settings.patch b/target/linux/brcm2708/patches-4.19/950-0706-bcm2708_fb-Fix-layout-of-struct-vc4_display_settings.patch
deleted file mode 100644 (file)
index adb14fb..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From c6be127c2f4d5f75c60d3778594093ff51593a6e Mon Sep 17 00:00:00 2001
-From: Michael Brown <mbrown@fensystems.co.uk>
-Date: Sun, 22 Sep 2019 21:51:29 +0100
-Subject: [PATCH] bcm2708_fb: Fix layout of struct
- vc4_display_settings_t
-
-The display parameters returned by the VC4 firmware in response to the
-RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS tag do not match the
-layout of struct vc4_display_settings_t: the colour depth and row
-pitch are erroneously swapped in the kernel definition.  This can
-trigger a kernel warning from pixel_to_pat(), such as:
-
-  pixel_to_pat(): unsupported pixelformat 7296
-
-Fix by adjusting the layout of struct vc4_display_settings_t to match
-the layout as used by the VC4 firmware.
-
-Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
----
- drivers/video/fbdev/bcm2708_fb.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -89,8 +89,8 @@ struct vc4_display_settings_t {
-       u32 display_num;
-       u32 width;
-       u32 height;
--      u32 pitch;
-       u32 depth;
-+      u32 pitch;
-       u32 virtual_width;
-       u32 virtual_height;
-       u32 virtual_width_offset;
diff --git a/target/linux/brcm2708/patches-4.19/950-0707-ARM-bcm283x-Enable-DMA-support-for-SPI-controller.patch b/target/linux/brcm2708/patches-4.19/950-0707-ARM-bcm283x-Enable-DMA-support-for-SPI-controller.patch
new file mode 100644 (file)
index 0000000..27cd2af
--- /dev/null
@@ -0,0 +1,42 @@
+From cce15c51f1afbb1aa9d5f7779c9f7c0a17b39701 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Thu, 9 May 2019 19:03:00 +0200
+Subject: [PATCH] ARM: bcm283x: Enable DMA support for SPI controller
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Without this, the driver for the BCM2835 SPI controller uses interrupt
+mode instead of DMA mode, incurring a significant performance penalty.
+The Foundation's device tree has had these attributes for years, but for
+some reason they were never upstreamed.
+
+They were originally contributed by Noralf Trønnes and Martin Sperl:
+https://github.com/raspberrypi/linux/commit/25f3e064afc8
+https://github.com/raspberrypi/linux/commit/e0edb52b47e6
+
+The DREQ numbers 6 and 7 are documented in section 4.2.1.3 of:
+https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
+
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Martin Sperl <kernel@martin.sperl.org>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Cc: Martin Sperl <kernel@martin.sperl.org>
+Cc: Noralf Trønnes <noralf@tronnes.org>
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -403,6 +403,8 @@
+                       reg = <0x7e204000 0x200>;
+                       interrupts = <2 22>;
+                       clocks = <&clocks BCM2835_CLOCK_VPU>;
++                      dmas = <&dma 6>, <&dma 7>;
++                      dma-names = "tx", "rx";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
diff --git a/target/linux/brcm2708/patches-4.19/950-0707-ARM-dts-bcm283x-Fix-DTC-warning-for-memory-node.patch b/target/linux/brcm2708/patches-4.19/950-0707-ARM-dts-bcm283x-Fix-DTC-warning-for-memory-node.patch
deleted file mode 100644 (file)
index b593d7f..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-From b640129382a37105cf2577f251103e550381b797 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Mon, 23 Sep 2019 18:56:37 +0200
-Subject: [PATCH] ARM: dts: bcm283x: Fix DTC warning for memory node
-
-commit f090e1bd7b05f17d35b6e2d0e946d8a8085d264f upstream.
-
-Compiling the bcm283x DTS with W=1 leads to the following warning:
-
-Warning (unit_address_vs_reg): /memory: node has a reg or ranges property,
-but no unit name
-
-Fix this by adding the unit address.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Tested-by: Peter Robinson <pbrobinson@gmail.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
----
- arch/arm/boot/dts/bcm2835-rpi.dtsi         | 2 +-
- arch/arm/boot/dts/bcm2836-rpi-2-b.dts      | 2 +-
- arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
- arch/arm/boot/dts/bcm2837-rpi-3-b.dts      | 2 +-
- 4 files changed, 4 insertions(+), 4 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -1,7 +1,7 @@
- #include <dt-bindings/power/raspberrypi-power.h>
- / {
--      memory {
-+      memory@0 {
-               device_type = "memory";
-               reg = <0 0x10000000>;
-       };
---- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-@@ -10,7 +10,7 @@
-       compatible = "raspberrypi,2-model-b", "brcm,bcm2836";
-       model = "Raspberry Pi 2 Model B";
--      memory {
-+      memory@0 {
-               reg = <0 0x40000000>;
-       };
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-@@ -14,7 +14,7 @@
-               stdout-path = "serial1:115200n8";
-       };
--      memory {
-+      memory@0 {
-               reg = <0 0x40000000>;
-       };
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-@@ -15,7 +15,7 @@
-               stdout-path = "serial1:115200n8";
-       };
--      memory {
-+      memory@0 {
-               reg = <0 0x40000000>;
-       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0708-ARM-dts-bcm27xx-Fix-DTC-warning-for-memory-node.patch b/target/linux/brcm2708/patches-4.19/950-0708-ARM-dts-bcm27xx-Fix-DTC-warning-for-memory-node.patch
deleted file mode 100644 (file)
index 3a424b3..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 10524e83179ad016a379ea99364d6912812a9aa5 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Mon, 23 Sep 2019 20:09:12 +0200
-Subject: [PATCH] ARM: dts: bcm27xx: Fix DTC warning for memory node
-
-Compiling the bcm27xx DTS with W=1 leads to the following warning:
-
-Warning (unit_address_vs_reg): /memory: node has a reg or ranges property,
-but no unit name
-
-Fix this by adding the unit address.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm2708-rpi.dtsi    | 2 +-
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
- arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -3,7 +3,7 @@
- #include "bcm2835-rpi.dtsi"
- / {
--      memory {
-+      memory@0 {
-               device_type = "memory";
-               reg = <0x0 0x0>;
-       };
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -8,7 +8,7 @@
-       compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
-       model = "Raspberry Pi 4 Model B";
--      memory {
-+      memory@0 {
-               device_type = "memory";
-               reg = <0x0 0x0 0x0>;
-       };
---- a/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
-@@ -13,7 +13,7 @@
-               stdout-path = "serial1:115200n8";
-       };
--      memory {
-+      memory@0 {
-               reg = <0 0 0x40000000>;
-       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0708-ARM-dts-bcm2835-rpi-Drop-unnecessary-address-cells-s.patch b/target/linux/brcm2708/patches-4.19/950-0708-ARM-dts-bcm2835-rpi-Drop-unnecessary-address-cells-s.patch
new file mode 100644 (file)
index 0000000..6986ae9
--- /dev/null
@@ -0,0 +1,30 @@
+From de002983174698762ecd3e42ab5a4b1bceb80af1 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sun, 30 Dec 2018 12:07:16 +0100
+Subject: [PATCH] ARM: dts: bcm2835-rpi: Drop unnecessary
+ #address-cells/#size-cells
+
+Compiling the bcm2835-rpi.dtsi with W=1 leads to the following warning:
+
+Warning (avoid_unnecessary_addr_size): /soc/firmware: unnecessary
+ #address-cells/#size-cells without "ranges" or child "reg" property
+
+Fix this by removing these unnecessary properties.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+---
+ arch/arm/boot/dts/bcm2835-rpi.dtsi | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -19,8 +19,6 @@
+       soc {
+               firmware: firmware {
+                       compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
+-                      #address-cells = <0>;
+-                      #size-cells = <0>;
+                       mboxes = <&mailbox>;
+               };
diff --git a/target/linux/brcm2708/patches-4.19/950-0709-ARM-bcm283x-Enable-DMA-support-for-SPI-controller.patch b/target/linux/brcm2708/patches-4.19/950-0709-ARM-bcm283x-Enable-DMA-support-for-SPI-controller.patch
deleted file mode 100644 (file)
index 27cd2af..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From cce15c51f1afbb1aa9d5f7779c9f7c0a17b39701 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Thu, 9 May 2019 19:03:00 +0200
-Subject: [PATCH] ARM: bcm283x: Enable DMA support for SPI controller
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Without this, the driver for the BCM2835 SPI controller uses interrupt
-mode instead of DMA mode, incurring a significant performance penalty.
-The Foundation's device tree has had these attributes for years, but for
-some reason they were never upstreamed.
-
-They were originally contributed by Noralf Trønnes and Martin Sperl:
-https://github.com/raspberrypi/linux/commit/25f3e064afc8
-https://github.com/raspberrypi/linux/commit/e0edb52b47e6
-
-The DREQ numbers 6 and 7 are documented in section 4.2.1.3 of:
-https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
-
-Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Martin Sperl <kernel@martin.sperl.org>
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
-Cc: Martin Sperl <kernel@martin.sperl.org>
-Cc: Noralf Trønnes <noralf@tronnes.org>
----
- arch/arm/boot/dts/bcm283x.dtsi | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -403,6 +403,8 @@
-                       reg = <0x7e204000 0x200>;
-                       interrupts = <2 22>;
-                       clocks = <&clocks BCM2835_CLOCK_VPU>;
-+                      dmas = <&dma 6>, <&dma 7>;
-+                      dma-names = "tx", "rx";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       status = "disabled";
diff --git a/target/linux/brcm2708/patches-4.19/950-0709-ARM-dts-bcm2708-rpi-Define-the-downstream-MMC-interf.patch b/target/linux/brcm2708/patches-4.19/950-0709-ARM-dts-bcm2708-rpi-Define-the-downstream-MMC-interf.patch
new file mode 100644 (file)
index 0000000..184d397
--- /dev/null
@@ -0,0 +1,40 @@
+From c31c8018e7cef83c827c913a10ac06b465813b22 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 21 Sep 2019 15:29:33 +0200
+Subject: [PATCH] ARM: dts: bcm2708-rpi: Define the downstream MMC
+ interfaces at one place
+
+In order to keep downstream definition of the MMC interfaces separate
+and independent from upstream changes, add them to bcm2708-rpi.dtsi.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -125,13 +125,23 @@
+       firmware = <&firmware>;
+ };
++&sdhci {
++      pinctrl-names = "default";
++      pinctrl-0 = <&emmc_gpio48>;
++      bus-width = <4>;
++};
++
+ sdhost_pins: &sdhost_gpio48 {
+       /* Add alias */
+ };
+ &sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
+       brcm,overclock-50 = <0>;
+       brcm,pio-limit = <1>;
++      status = "okay";
+ };
+ &cpu_thermal {
diff --git a/target/linux/brcm2708/patches-4.19/950-0710-ARM-dts-bcm2835-rpi-Drop-unnecessary-address-cells-s.patch b/target/linux/brcm2708/patches-4.19/950-0710-ARM-dts-bcm2835-rpi-Drop-unnecessary-address-cells-s.patch
deleted file mode 100644 (file)
index 6986ae9..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From de002983174698762ecd3e42ab5a4b1bceb80af1 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sun, 30 Dec 2018 12:07:16 +0100
-Subject: [PATCH] ARM: dts: bcm2835-rpi: Drop unnecessary
- #address-cells/#size-cells
-
-Compiling the bcm2835-rpi.dtsi with W=1 leads to the following warning:
-
-Warning (avoid_unnecessary_addr_size): /soc/firmware: unnecessary
- #address-cells/#size-cells without "ranges" or child "reg" property
-
-Fix this by removing these unnecessary properties.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
----
- arch/arm/boot/dts/bcm2835-rpi.dtsi | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -19,8 +19,6 @@
-       soc {
-               firmware: firmware {
-                       compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
--                      #address-cells = <0>;
--                      #size-cells = <0>;
-                       mboxes = <&mailbox>;
-               };
diff --git a/target/linux/brcm2708/patches-4.19/950-0710-ARM-dts-bcm283x-Define-MMC-interfaces-at-board-level.patch b/target/linux/brcm2708/patches-4.19/950-0710-ARM-dts-bcm283x-Define-MMC-interfaces-at-board-level.patch
new file mode 100644 (file)
index 0000000..7ad61b6
--- /dev/null
@@ -0,0 +1,194 @@
+From a1905aed89ee45f6662f03b77dc604ff1a169671 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Tue, 17 Sep 2019 19:16:17 +0200
+Subject: [PATCH] ARM: dts: bcm283x: Define MMC interfaces at board
+ level
+
+commit e7774049ff255c8ba72bcee9c7ab307a95e8d7bc upstream.
+
+Starting with RPi 4 this is the first board, which doesn't use sdhost
+as default SD interface. So the MMC interfaces should be defined finally at
+board level. Since all boards using sdhci already does this, we can drop the
+pinctrl part from bcm2835-rpi.dtsi.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Acked-by: Eric Anholt <eric@anholt.net>
+---
+ arch/arm/boot/dts/bcm2835-rpi-a-plus.dts  |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi-a.dts       |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi-b-plus.dts  |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts  |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi-b.dts       |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi-zero-w.dts  |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi-zero.dts    |  7 +++++++
+ arch/arm/boot/dts/bcm2835-rpi.dtsi        | 13 -------------
+ arch/arm/boot/dts/bcm2836-rpi-2-b.dts     |  7 +++++++
+ 10 files changed, 63 insertions(+), 13 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
+@@ -108,6 +108,13 @@
+       status = "okay";
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+--- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
+@@ -103,6 +103,13 @@
+       status = "okay";
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
+@@ -110,6 +110,13 @@
+       status = "okay";
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
+@@ -103,6 +103,13 @@
+       status = "okay";
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
+@@ -98,6 +98,13 @@
+       status = "okay";
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+--- a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
+@@ -81,6 +81,13 @@
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+--- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
+@@ -129,6 +129,13 @@
+       };
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio32 &uart0_ctsrts_gpio30>;
+--- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
+@@ -105,6 +105,13 @@
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -84,19 +84,6 @@
+       status = "okay";
+ };
+-&sdhci {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&emmc_gpio48>;
+-      bus-width = <4>;
+-};
+-
+-&sdhost {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&sdhost_gpio48>;
+-      status = "okay";
+-      bus-width = <4>;
+-};
+-
+ &usb {
+       power-domains = <&power RPI_POWER_DOMAIN_USB>;
+ };
+--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+@@ -48,6 +48,13 @@
+       status = "okay";
+ };
++&sdhost {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdhost_gpio48>;
++      bus-width = <4>;
++      status = "okay";
++};
++
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0711-ARM-dts-bcm2708-rpi-Define-the-downstream-MMC-interf.patch b/target/linux/brcm2708/patches-4.19/950-0711-ARM-dts-bcm2708-rpi-Define-the-downstream-MMC-interf.patch
deleted file mode 100644 (file)
index 184d397..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From c31c8018e7cef83c827c913a10ac06b465813b22 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 21 Sep 2019 15:29:33 +0200
-Subject: [PATCH] ARM: dts: bcm2708-rpi: Define the downstream MMC
- interfaces at one place
-
-In order to keep downstream definition of the MMC interfaces separate
-and independent from upstream changes, add them to bcm2708-rpi.dtsi.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -125,13 +125,23 @@
-       firmware = <&firmware>;
- };
-+&sdhci {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&emmc_gpio48>;
-+      bus-width = <4>;
-+};
-+
- sdhost_pins: &sdhost_gpio48 {
-       /* Add alias */
- };
- &sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-       brcm,overclock-50 = <0>;
-       brcm,pio-limit = <1>;
-+      status = "okay";
- };
- &cpu_thermal {
diff --git a/target/linux/brcm2708/patches-4.19/950-0711-ARM-dts-bcm2835-rpi-zero-w-Fix-bus-width-of-sdhci.patch b/target/linux/brcm2708/patches-4.19/950-0711-ARM-dts-bcm2835-rpi-zero-w-Fix-bus-width-of-sdhci.patch
new file mode 100644 (file)
index 0000000..06dd013
--- /dev/null
@@ -0,0 +1,28 @@
+From c60d699be1eb26a14157cfa5b1ac0cf8afce0dcb Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 23 Sep 2019 19:41:33 +0200
+Subject: [PATCH] ARM: dts: bcm2835-rpi-zero-w: Fix bus-width of sdhci
+
+The commit e7774049ff25 ("ARM: dts: bcm283x: Define MMC interfaces at
+board level") accidently dropped the bus width for the sdhci on the
+RPi Zero W, because the board file was relying on the defaults
+from bcm2835-rpi.dtsi. So fix this performance regression by adding
+the bus width to the board file.
+
+Fixes: e7774049ff25 ("ARM: dts: bcm283x: Define MMC interfaces at board level")
+Reported-by: Phil Elwell <phil@raspberrypi.org>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
+@@ -119,6 +119,7 @@
+       #address-cells = <1>;
+       #size-cells = <0>;
+       pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>;
++      bus-width = <4>;
+       mmc-pwrseq = <&wifi_pwrseq>;
+       non-removable;
+       status = "okay";
diff --git a/target/linux/brcm2708/patches-4.19/950-0712-ARM-dts-bcm2708-rpi-Define-the-downstream-HDMI-power.patch b/target/linux/brcm2708/patches-4.19/950-0712-ARM-dts-bcm2708-rpi-Define-the-downstream-HDMI-power.patch
new file mode 100644 (file)
index 0000000..764169f
--- /dev/null
@@ -0,0 +1,24 @@
+From 51908b138907d25df02687c514d59373b2a32f18 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 21 Sep 2019 15:55:19 +0200
+Subject: [PATCH] ARM: dts: bcm2708-rpi: Define the downstream HDMI
+ power at one place
+
+In order to keep downstream definition of the HDMI power domain separate
+and independent from upstream changes, add them to bcm2708-rpi.dtsi.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -102,6 +102,7 @@
+ };
+ &hdmi {
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+       status = "disabled";
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0712-ARM-dts-bcm283x-Define-MMC-interfaces-at-board-level.patch b/target/linux/brcm2708/patches-4.19/950-0712-ARM-dts-bcm283x-Define-MMC-interfaces-at-board-level.patch
deleted file mode 100644 (file)
index 7ad61b6..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-From a1905aed89ee45f6662f03b77dc604ff1a169671 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Tue, 17 Sep 2019 19:16:17 +0200
-Subject: [PATCH] ARM: dts: bcm283x: Define MMC interfaces at board
- level
-
-commit e7774049ff255c8ba72bcee9c7ab307a95e8d7bc upstream.
-
-Starting with RPi 4 this is the first board, which doesn't use sdhost
-as default SD interface. So the MMC interfaces should be defined finally at
-board level. Since all boards using sdhci already does this, we can drop the
-pinctrl part from bcm2835-rpi.dtsi.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
-Acked-by: Eric Anholt <eric@anholt.net>
----
- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts  |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi-a.dts       |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts  |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts  |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi-b.dts       |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi-zero-w.dts  |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi-zero.dts    |  7 +++++++
- arch/arm/boot/dts/bcm2835-rpi.dtsi        | 13 -------------
- arch/arm/boot/dts/bcm2836-rpi-2-b.dts     |  7 +++++++
- 10 files changed, 63 insertions(+), 13 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
-@@ -108,6 +108,13 @@
-       status = "okay";
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
---- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
-@@ -103,6 +103,13 @@
-       status = "okay";
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
---- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
-@@ -110,6 +110,13 @@
-       status = "okay";
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
---- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
-@@ -103,6 +103,13 @@
-       status = "okay";
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
---- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
-@@ -98,6 +98,13 @@
-       status = "okay";
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
---- a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
-@@ -81,6 +81,13 @@
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
---- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
-@@ -129,6 +129,13 @@
-       };
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio32 &uart0_ctsrts_gpio30>;
---- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
-@@ -105,6 +105,13 @@
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -84,19 +84,6 @@
-       status = "okay";
- };
--&sdhci {
--      pinctrl-names = "default";
--      pinctrl-0 = <&emmc_gpio48>;
--      bus-width = <4>;
--};
--
--&sdhost {
--      pinctrl-names = "default";
--      pinctrl-0 = <&sdhost_gpio48>;
--      status = "okay";
--      bus-width = <4>;
--};
--
- &usb {
-       power-domains = <&power RPI_POWER_DOMAIN_USB>;
- };
---- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-@@ -48,6 +48,13 @@
-       status = "okay";
- };
-+&sdhost {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdhost_gpio48>;
-+      bus-width = <4>;
-+      status = "okay";
-+};
-+
- &uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart0_gpio14>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0713-ARM-dts-bcm2835-rpi-zero-w-Fix-bus-width-of-sdhci.patch b/target/linux/brcm2708/patches-4.19/950-0713-ARM-dts-bcm2835-rpi-zero-w-Fix-bus-width-of-sdhci.patch
deleted file mode 100644 (file)
index 06dd013..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From c60d699be1eb26a14157cfa5b1ac0cf8afce0dcb Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Mon, 23 Sep 2019 19:41:33 +0200
-Subject: [PATCH] ARM: dts: bcm2835-rpi-zero-w: Fix bus-width of sdhci
-
-The commit e7774049ff25 ("ARM: dts: bcm283x: Define MMC interfaces at
-board level") accidently dropped the bus width for the sdhci on the
-RPi Zero W, because the board file was relying on the defaults
-from bcm2835-rpi.dtsi. So fix this performance regression by adding
-the bus width to the board file.
-
-Fixes: e7774049ff25 ("ARM: dts: bcm283x: Define MMC interfaces at board level")
-Reported-by: Phil Elwell <phil@raspberrypi.org>
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
-@@ -119,6 +119,7 @@
-       #address-cells = <1>;
-       #size-cells = <0>;
-       pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>;
-+      bus-width = <4>;
-       mmc-pwrseq = <&wifi_pwrseq>;
-       non-removable;
-       status = "okay";
diff --git a/target/linux/brcm2708/patches-4.19/950-0713-ARM-dts-bcm283x-Enable-HDMI-at-board-level.patch b/target/linux/brcm2708/patches-4.19/950-0713-ARM-dts-bcm283x-Enable-HDMI-at-board-level.patch
new file mode 100644 (file)
index 0000000..82e126e
--- /dev/null
@@ -0,0 +1,163 @@
+From a3cbeaaee57b7bda4e921bb2cff649fb56c0292d Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Tue, 17 Sep 2019 19:31:19 +0200
+Subject: [PATCH] ARM: dts: bcm283x: Enable HDMI at board level
+
+commit 60c833d5664e1b3f71c4471233469790adf505ca upstream.
+
+There might be headless setups of the Compute Module without HDMI,
+so better enable HDMI at board level. Btw this allows moving HDMI
+base definition into upcoming bcm2835-common.dtsi.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+---
+ arch/arm/boot/dts/bcm2835-rpi-a-plus.dts   | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi-a.dts        | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi-b-plus.dts   | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts   | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi-b.dts        | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts  | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi-zero-w.dts   | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi-zero.dts     | 2 ++
+ arch/arm/boot/dts/bcm2835-rpi.dtsi         | 5 -----
+ arch/arm/boot/dts/bcm2836-rpi-2-b.dts      | 2 ++
+ arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 ++
+ arch/arm/boot/dts/bcm2837-rpi-3-b.dts      | 2 ++
+ 12 files changed, 22 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
+@@ -100,6 +100,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &pwm {
+--- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
+@@ -95,6 +95,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &pwm {
+--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
+@@ -102,6 +102,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &pwm {
+--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
+@@ -95,6 +95,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &pwm {
+--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
+@@ -90,6 +90,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &pwm {
+--- a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
+@@ -79,6 +79,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &sdhost {
+--- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
+@@ -113,6 +113,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &sdhci {
+--- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
+@@ -103,6 +103,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &sdhost {
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -92,11 +92,6 @@
+       power-domains = <&power RPI_POWER_DOMAIN_V3D>;
+ };
+-&hdmi {
+-      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+-      status = "okay";
+-};
+-
+ &vec {
+       power-domains = <&power RPI_POWER_DOMAIN_VEC>;
+       status = "okay";
+--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+@@ -40,6 +40,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &pwm {
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+@@ -54,6 +54,8 @@
+ &hdmi {
+       hpd-gpios = <&gpio 28 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ &pwm {
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+@@ -56,6 +56,8 @@
+ &hdmi {
+       hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>;
++      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++      status = "okay";
+ };
+ /* uart0 communicates with the BT module */
diff --git a/target/linux/brcm2708/patches-4.19/950-0714-ARM-dts-bcm2708-rpi-Define-the-downstream-HDMI-power.patch b/target/linux/brcm2708/patches-4.19/950-0714-ARM-dts-bcm2708-rpi-Define-the-downstream-HDMI-power.patch
deleted file mode 100644 (file)
index 764169f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 51908b138907d25df02687c514d59373b2a32f18 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 21 Sep 2019 15:55:19 +0200
-Subject: [PATCH] ARM: dts: bcm2708-rpi: Define the downstream HDMI
- power at one place
-
-In order to keep downstream definition of the HDMI power domain separate
-and independent from upstream changes, add them to bcm2708-rpi.dtsi.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -102,6 +102,7 @@
- };
- &hdmi {
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-       status = "disabled";
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0714-clk-bcm2835-Introduce-SoC-specific-clock-registratio.patch b/target/linux/brcm2708/patches-4.19/950-0714-clk-bcm2835-Introduce-SoC-specific-clock-registratio.patch
new file mode 100644 (file)
index 0000000..52f716e
--- /dev/null
@@ -0,0 +1,597 @@
+From 125afc5cf080b29e9114d89f6052fa4a936a3f19 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Thu, 19 Sep 2019 20:12:15 +0200
+Subject: [PATCH] clk: bcm2835: Introduce SoC specific clock
+ registration
+
+commit ee0a5a9013b2b2502571a763c3093d400d18191f upstream.
+
+In order to support SoC specific clocks (e.g. emmc2 for BCM2711), we
+extend the description with a SoC support flag. This approach avoids long
+and mostly redundant lists of clock IDs. Since PLLH is specific to
+BCM2835, we register only rest of the clocks as common to all SoC.
+
+Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Reviewed-by: Matthias Brugger <mbrugger@suse.com>
+Acked-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 115 +++++++++++++++++++++++++++++-----
+ 1 file changed, 98 insertions(+), 17 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -40,7 +40,7 @@
+ #include <linux/debugfs.h>
+ #include <linux/delay.h>
+ #include <linux/module.h>
+-#include <linux/of.h>
++#include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <dt-bindings/clock/bcm2835.h>
+@@ -301,6 +301,9 @@
+ #define VCMSG_ID_CORE_CLOCK     4
++#define SOC_BCM2835           BIT(0)
++#define SOC_ALL                       (SOC_BCM2835)
++
+ /*
+  * Names of clocks used within the driver that need to be replaced
+  * with an external parent's name.  This array is in the order that
+@@ -333,6 +336,10 @@ struct bcm2835_cprman {
+       struct clk_hw_onecell_data onecell;
+ };
++struct cprman_plat_data {
++      unsigned int soc;
++};
++
+ static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
+ {
+       writel(CM_PASSWORD | val, cprman->regs + reg);
+@@ -1528,22 +1535,28 @@ typedef struct clk_hw *(*bcm2835_clk_reg
+                                              const void *data);
+ struct bcm2835_clk_desc {
+       bcm2835_clk_register clk_register;
++      unsigned int supported;
+       const void *data;
+ };
+ /* assignment helper macros for different clock types */
+-#define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \
+-                          .data = __VA_ARGS__ }
+-#define REGISTER_PLL(...)     _REGISTER(&bcm2835_register_pll,        \
++#define _REGISTER(f, s, ...) { .clk_register = (bcm2835_clk_register)f, \
++                             .supported = s,                          \
++                             .data = __VA_ARGS__ }
++#define REGISTER_PLL(s, ...)  _REGISTER(&bcm2835_register_pll,        \
++                                        s,                            \
+                                         &(struct bcm2835_pll_data)    \
+                                         {__VA_ARGS__})
+-#define REGISTER_PLL_DIV(...) _REGISTER(&bcm2835_register_pll_divider, \
+-                                        &(struct bcm2835_pll_divider_data) \
+-                                        {__VA_ARGS__})
+-#define REGISTER_CLK(...)     _REGISTER(&bcm2835_register_clock,      \
++#define REGISTER_PLL_DIV(s, ...) _REGISTER(&bcm2835_register_pll_divider, \
++                                         s,                             \
++                                         &(struct bcm2835_pll_divider_data) \
++                                         {__VA_ARGS__})
++#define REGISTER_CLK(s, ...)  _REGISTER(&bcm2835_register_clock,      \
++                                        s,                            \
+                                         &(struct bcm2835_clock_data)  \
+                                         {__VA_ARGS__})
+-#define REGISTER_GATE(...)    _REGISTER(&bcm2835_register_gate,       \
++#define REGISTER_GATE(s, ...) _REGISTER(&bcm2835_register_gate,       \
++                                        s,                            \
+                                         &(struct bcm2835_gate_data)   \
+                                         {__VA_ARGS__})
+@@ -1557,7 +1570,8 @@ static const char *const bcm2835_clock_o
+       "testdebug1"
+ };
+-#define REGISTER_OSC_CLK(...) REGISTER_CLK(                           \
++#define REGISTER_OSC_CLK(s, ...)      REGISTER_CLK(                   \
++      s,                                                              \
+       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),       \
+       .parents = bcm2835_clock_osc_parents,                           \
+       __VA_ARGS__)
+@@ -1574,7 +1588,8 @@ static const char *const bcm2835_clock_p
+       "pllh_aux",
+ };
+-#define REGISTER_PER_CLK(...) REGISTER_CLK(                           \
++#define REGISTER_PER_CLK(s, ...)      REGISTER_CLK(                   \
++      s,                                                              \
+       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),       \
+       .parents = bcm2835_clock_per_parents,                           \
+       __VA_ARGS__)
+@@ -1599,7 +1614,8 @@ static const char *const bcm2835_pcm_per
+       "-",
+ };
+-#define REGISTER_PCM_CLK(...) REGISTER_CLK(                           \
++#define REGISTER_PCM_CLK(s, ...)      REGISTER_CLK(                   \
++      s,                                                              \
+       .num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents),         \
+       .parents = bcm2835_pcm_per_parents,                             \
+       __VA_ARGS__)
+@@ -1618,7 +1634,8 @@ static const char *const bcm2835_clock_v
+       "pllc_core2",
+ };
+-#define REGISTER_VPU_CLK(...) REGISTER_CLK(                           \
++#define REGISTER_VPU_CLK(s, ...)      REGISTER_CLK(                   \
++      s,                                                              \
+       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),       \
+       .parents = bcm2835_clock_vpu_parents,                           \
+       __VA_ARGS__)
+@@ -1654,12 +1671,14 @@ static const char *const bcm2835_clock_d
+       "dsi1_byte_inv",
+ };
+-#define REGISTER_DSI0_CLK(...)        REGISTER_CLK(                           \
++#define REGISTER_DSI0_CLK(s, ...)     REGISTER_CLK(                   \
++      s,                                                              \
+       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents),      \
+       .parents = bcm2835_clock_dsi0_parents,                          \
+       __VA_ARGS__)
+-#define REGISTER_DSI1_CLK(...)        REGISTER_CLK(                           \
++#define REGISTER_DSI1_CLK(s, ...)     REGISTER_CLK(                   \
++      s,                                                              \
+       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents),      \
+       .parents = bcm2835_clock_dsi1_parents,                          \
+       __VA_ARGS__)
+@@ -1679,6 +1698,7 @@ static const struct bcm2835_clk_desc clk
+        * AUDIO domain is on.
+        */
+       [BCM2835_PLLA]          = REGISTER_PLL(
++              SOC_ALL,
+               .name = "plla",
+               .cm_ctrl_reg = CM_PLLA,
+               .a2w_ctrl_reg = A2W_PLLA_CTRL,
+@@ -1693,6 +1713,7 @@ static const struct bcm2835_clk_desc clk
+               .max_rate = 2400000000u,
+               .max_fb_rate = BCM2835_MAX_FB_RATE),
+       [BCM2835_PLLA_CORE]     = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plla_core",
+               .source_pll = "plla",
+               .cm_reg = CM_PLLA,
+@@ -1702,6 +1723,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLA_PER]      = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plla_per",
+               .source_pll = "plla",
+               .cm_reg = CM_PLLA,
+@@ -1711,6 +1733,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLA_DSI0]     = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plla_dsi0",
+               .source_pll = "plla",
+               .cm_reg = CM_PLLA,
+@@ -1719,6 +1742,7 @@ static const struct bcm2835_clk_desc clk
+               .hold_mask = CM_PLLA_HOLDDSI0,
+               .fixed_divider = 1),
+       [BCM2835_PLLA_CCP2]     = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plla_ccp2",
+               .source_pll = "plla",
+               .cm_reg = CM_PLLA,
+@@ -1730,6 +1754,7 @@ static const struct bcm2835_clk_desc clk
+       /* PLLB is used for the ARM's clock. */
+       [BCM2835_PLLB]          = REGISTER_PLL(
++              SOC_ALL,
+               .name = "pllb",
+               .cm_ctrl_reg = CM_PLLB,
+               .a2w_ctrl_reg = A2W_PLLB_CTRL,
+@@ -1744,6 +1769,7 @@ static const struct bcm2835_clk_desc clk
+               .max_rate = 3000000000u,
+               .max_fb_rate = BCM2835_MAX_FB_RATE),
+       [BCM2835_PLLB_ARM]      = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "pllb_arm",
+               .source_pll = "pllb",
+               .cm_reg = CM_PLLB,
+@@ -1760,6 +1786,7 @@ static const struct bcm2835_clk_desc clk
+        * AUDIO domain is on.
+        */
+       [BCM2835_PLLC]          = REGISTER_PLL(
++              SOC_ALL,
+               .name = "pllc",
+               .cm_ctrl_reg = CM_PLLC,
+               .a2w_ctrl_reg = A2W_PLLC_CTRL,
+@@ -1774,6 +1801,7 @@ static const struct bcm2835_clk_desc clk
+               .max_rate = 3000000000u,
+               .max_fb_rate = BCM2835_MAX_FB_RATE),
+       [BCM2835_PLLC_CORE0]    = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "pllc_core0",
+               .source_pll = "pllc",
+               .cm_reg = CM_PLLC,
+@@ -1783,6 +1811,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLC_CORE1]    = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "pllc_core1",
+               .source_pll = "pllc",
+               .cm_reg = CM_PLLC,
+@@ -1792,6 +1821,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLC_CORE2]    = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "pllc_core2",
+               .source_pll = "pllc",
+               .cm_reg = CM_PLLC,
+@@ -1801,6 +1831,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLC_PER]      = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "pllc_per",
+               .source_pll = "pllc",
+               .cm_reg = CM_PLLC,
+@@ -1817,6 +1848,7 @@ static const struct bcm2835_clk_desc clk
+        * AUDIO domain is on.
+        */
+       [BCM2835_PLLD]          = REGISTER_PLL(
++              SOC_ALL,
+               .name = "plld",
+               .cm_ctrl_reg = CM_PLLD,
+               .a2w_ctrl_reg = A2W_PLLD_CTRL,
+@@ -1831,6 +1863,7 @@ static const struct bcm2835_clk_desc clk
+               .max_rate = 2400000000u,
+               .max_fb_rate = BCM2835_MAX_FB_RATE),
+       [BCM2835_PLLD_CORE]     = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plld_core",
+               .source_pll = "plld",
+               .cm_reg = CM_PLLD,
+@@ -1840,6 +1873,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLD_PER]      = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plld_per",
+               .source_pll = "plld",
+               .cm_reg = CM_PLLD,
+@@ -1849,6 +1883,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLD_DSI0]     = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plld_dsi0",
+               .source_pll = "plld",
+               .cm_reg = CM_PLLD,
+@@ -1857,6 +1892,7 @@ static const struct bcm2835_clk_desc clk
+               .hold_mask = CM_PLLD_HOLDDSI0,
+               .fixed_divider = 1),
+       [BCM2835_PLLD_DSI1]     = REGISTER_PLL_DIV(
++              SOC_ALL,
+               .name = "plld_dsi1",
+               .source_pll = "plld",
+               .cm_reg = CM_PLLD,
+@@ -1872,6 +1908,7 @@ static const struct bcm2835_clk_desc clk
+        * It is in the HDMI power domain.
+        */
+       [BCM2835_PLLH]          = REGISTER_PLL(
++              SOC_BCM2835,
+               "pllh",
+               .cm_ctrl_reg = CM_PLLH,
+               .a2w_ctrl_reg = A2W_PLLH_CTRL,
+@@ -1886,6 +1923,7 @@ static const struct bcm2835_clk_desc clk
+               .max_rate = 3000000000u,
+               .max_fb_rate = BCM2835_MAX_FB_RATE),
+       [BCM2835_PLLH_RCAL]     = REGISTER_PLL_DIV(
++              SOC_BCM2835,
+               .name = "pllh_rcal",
+               .source_pll = "pllh",
+               .cm_reg = CM_PLLH,
+@@ -1895,6 +1933,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 10,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLH_AUX]      = REGISTER_PLL_DIV(
++              SOC_BCM2835,
+               .name = "pllh_aux",
+               .source_pll = "pllh",
+               .cm_reg = CM_PLLH,
+@@ -1904,6 +1943,7 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+       [BCM2835_PLLH_PIX]      = REGISTER_PLL_DIV(
++              SOC_BCM2835,
+               .name = "pllh_pix",
+               .source_pll = "pllh",
+               .cm_reg = CM_PLLH,
+@@ -1919,6 +1959,7 @@ static const struct bcm2835_clk_desc clk
+       /* One Time Programmable Memory clock.  Maximum 10Mhz. */
+       [BCM2835_CLOCK_OTP]     = REGISTER_OSC_CLK(
++              SOC_ALL,
+               .name = "otp",
+               .ctl_reg = CM_OTPCTL,
+               .div_reg = CM_OTPDIV,
+@@ -1930,6 +1971,7 @@ static const struct bcm2835_clk_desc clk
+        * bythe watchdog timer and the camera pulse generator.
+        */
+       [BCM2835_CLOCK_TIMER]   = REGISTER_OSC_CLK(
++              SOC_ALL,
+               .name = "timer",
+               .ctl_reg = CM_TIMERCTL,
+               .div_reg = CM_TIMERDIV,
+@@ -1940,12 +1982,14 @@ static const struct bcm2835_clk_desc clk
+        * Generally run at 2Mhz, max 5Mhz.
+        */
+       [BCM2835_CLOCK_TSENS]   = REGISTER_OSC_CLK(
++              SOC_ALL,
+               .name = "tsens",
+               .ctl_reg = CM_TSENSCTL,
+               .div_reg = CM_TSENSDIV,
+               .int_bits = 5,
+               .frac_bits = 0),
+       [BCM2835_CLOCK_TEC]     = REGISTER_OSC_CLK(
++              SOC_ALL,
+               .name = "tec",
+               .ctl_reg = CM_TECCTL,
+               .div_reg = CM_TECDIV,
+@@ -1954,6 +1998,7 @@ static const struct bcm2835_clk_desc clk
+       /* clocks with vpu parent mux */
+       [BCM2835_CLOCK_H264]    = REGISTER_VPU_CLK(
++              SOC_ALL,
+               .name = "h264",
+               .ctl_reg = CM_H264CTL,
+               .div_reg = CM_H264DIV,
+@@ -1961,6 +2006,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 1),
+       [BCM2835_CLOCK_ISP]     = REGISTER_VPU_CLK(
++              SOC_ALL,
+               .name = "isp",
+               .ctl_reg = CM_ISPCTL,
+               .div_reg = CM_ISPDIV,
+@@ -1973,6 +2019,7 @@ static const struct bcm2835_clk_desc clk
+        * in the SDRAM controller can't be used.
+        */
+       [BCM2835_CLOCK_SDRAM]   = REGISTER_VPU_CLK(
++              SOC_ALL,
+               .name = "sdram",
+               .ctl_reg = CM_SDCCTL,
+               .div_reg = CM_SDCDIV,
+@@ -1980,6 +2027,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 0,
+               .tcnt_mux = 3),
+       [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
++              SOC_ALL,
+               .name = "v3d",
+               .ctl_reg = CM_V3DCTL,
+               .div_reg = CM_V3DDIV,
+@@ -1993,6 +2041,7 @@ static const struct bcm2835_clk_desc clk
+        * in various hardware documentation.
+        */
+       [BCM2835_CLOCK_VPU]     = REGISTER_VPU_CLK(
++              SOC_ALL,
+               .name = "vpu",
+               .ctl_reg = CM_VPUCTL,
+               .div_reg = CM_VPUDIV,
+@@ -2004,6 +2053,7 @@ static const struct bcm2835_clk_desc clk
+       /* clocks with per parent mux */
+       [BCM2835_CLOCK_AVEO]    = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "aveo",
+               .ctl_reg = CM_AVEOCTL,
+               .div_reg = CM_AVEODIV,
+@@ -2011,6 +2061,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 0,
+               .tcnt_mux = 38),
+       [BCM2835_CLOCK_CAM0]    = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "cam0",
+               .ctl_reg = CM_CAM0CTL,
+               .div_reg = CM_CAM0DIV,
+@@ -2018,6 +2069,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 14),
+       [BCM2835_CLOCK_CAM1]    = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "cam1",
+               .ctl_reg = CM_CAM1CTL,
+               .div_reg = CM_CAM1DIV,
+@@ -2025,12 +2077,14 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 15),
+       [BCM2835_CLOCK_DFT]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "dft",
+               .ctl_reg = CM_DFTCTL,
+               .div_reg = CM_DFTDIV,
+               .int_bits = 5,
+               .frac_bits = 0),
+       [BCM2835_CLOCK_DPI]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "dpi",
+               .ctl_reg = CM_DPICTL,
+               .div_reg = CM_DPIDIV,
+@@ -2040,6 +2094,7 @@ static const struct bcm2835_clk_desc clk
+       /* Arasan EMMC clock */
+       [BCM2835_CLOCK_EMMC]    = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "emmc",
+               .ctl_reg = CM_EMMCCTL,
+               .div_reg = CM_EMMCDIV,
+@@ -2049,6 +2104,7 @@ static const struct bcm2835_clk_desc clk
+       /* General purpose (GPIO) clocks */
+       [BCM2835_CLOCK_GP0]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "gp0",
+               .ctl_reg = CM_GP0CTL,
+               .div_reg = CM_GP0DIV,
+@@ -2057,6 +2113,7 @@ static const struct bcm2835_clk_desc clk
+               .is_mash_clock = true,
+               .tcnt_mux = 20),
+       [BCM2835_CLOCK_GP1]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "gp1",
+               .ctl_reg = CM_GP1CTL,
+               .div_reg = CM_GP1DIV,
+@@ -2066,6 +2123,7 @@ static const struct bcm2835_clk_desc clk
+               .is_mash_clock = true,
+               .tcnt_mux = 21),
+       [BCM2835_CLOCK_GP2]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "gp2",
+               .ctl_reg = CM_GP2CTL,
+               .div_reg = CM_GP2DIV,
+@@ -2075,6 +2133,7 @@ static const struct bcm2835_clk_desc clk
+       /* HDMI state machine */
+       [BCM2835_CLOCK_HSM]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "hsm",
+               .ctl_reg = CM_HSMCTL,
+               .div_reg = CM_HSMDIV,
+@@ -2082,6 +2141,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 22),
+       [BCM2835_CLOCK_PCM]     = REGISTER_PCM_CLK(
++              SOC_ALL,
+               .name = "pcm",
+               .ctl_reg = CM_PCMCTL,
+               .div_reg = CM_PCMDIV,
+@@ -2091,6 +2151,7 @@ static const struct bcm2835_clk_desc clk
+               .low_jitter = true,
+               .tcnt_mux = 23),
+       [BCM2835_CLOCK_PWM]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "pwm",
+               .ctl_reg = CM_PWMCTL,
+               .div_reg = CM_PWMDIV,
+@@ -2099,6 +2160,7 @@ static const struct bcm2835_clk_desc clk
+               .is_mash_clock = true,
+               .tcnt_mux = 24),
+       [BCM2835_CLOCK_SLIM]    = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "slim",
+               .ctl_reg = CM_SLIMCTL,
+               .div_reg = CM_SLIMDIV,
+@@ -2107,6 +2169,7 @@ static const struct bcm2835_clk_desc clk
+               .is_mash_clock = true,
+               .tcnt_mux = 25),
+       [BCM2835_CLOCK_SMI]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "smi",
+               .ctl_reg = CM_SMICTL,
+               .div_reg = CM_SMIDIV,
+@@ -2114,6 +2177,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 27),
+       [BCM2835_CLOCK_UART]    = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "uart",
+               .ctl_reg = CM_UARTCTL,
+               .div_reg = CM_UARTDIV,
+@@ -2123,6 +2187,7 @@ static const struct bcm2835_clk_desc clk
+       /* TV encoder clock.  Only operating frequency is 108Mhz.  */
+       [BCM2835_CLOCK_VEC]     = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "vec",
+               .ctl_reg = CM_VECCTL,
+               .div_reg = CM_VECDIV,
+@@ -2137,6 +2202,7 @@ static const struct bcm2835_clk_desc clk
+       /* dsi clocks */
+       [BCM2835_CLOCK_DSI0E]   = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "dsi0e",
+               .ctl_reg = CM_DSI0ECTL,
+               .div_reg = CM_DSI0EDIV,
+@@ -2144,6 +2210,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 18),
+       [BCM2835_CLOCK_DSI1E]   = REGISTER_PER_CLK(
++              SOC_ALL,
+               .name = "dsi1e",
+               .ctl_reg = CM_DSI1ECTL,
+               .div_reg = CM_DSI1EDIV,
+@@ -2151,6 +2218,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 19),
+       [BCM2835_CLOCK_DSI0P]   = REGISTER_DSI0_CLK(
++              SOC_ALL,
+               .name = "dsi0p",
+               .ctl_reg = CM_DSI0PCTL,
+               .div_reg = CM_DSI0PDIV,
+@@ -2158,6 +2226,7 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 0,
+               .tcnt_mux = 12),
+       [BCM2835_CLOCK_DSI1P]   = REGISTER_DSI1_CLK(
++              SOC_ALL,
+               .name = "dsi1p",
+               .ctl_reg = CM_DSI1PCTL,
+               .div_reg = CM_DSI1PDIV,
+@@ -2174,6 +2243,7 @@ static const struct bcm2835_clk_desc clk
+        * non-stop vpu clock.
+        */
+       [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE(
++              SOC_ALL,
+               .name = "peri_image",
+               .parent = "vpu",
+               .ctl_reg = CM_PERIICTL),
+@@ -2221,11 +2291,16 @@ static int bcm2835_clk_probe(struct plat
+       struct resource *res;
+       const struct bcm2835_clk_desc *desc;
+       const size_t asize = ARRAY_SIZE(clk_desc_array);
++      const struct cprman_plat_data *pdata;
+       struct device_node *fw_node;
+       size_t i;
+       u32 clk_id;
+       int ret;
++      pdata = of_device_get_match_data(&pdev->dev);
++      if (!pdata)
++              return -ENODEV;
++
+       cprman = devm_kzalloc(dev,
+                             struct_size(cprman, onecell.hws, asize),
+                             GFP_KERNEL);
+@@ -2276,8 +2351,10 @@ static int bcm2835_clk_probe(struct plat
+       for (i = 0; i < asize; i++) {
+               desc = &clk_desc_array[i];
+-              if (desc->clk_register && desc->data)
++              if (desc->clk_register && desc->data &&
++                  (desc->supported & pdata->soc)) {
+                       hws[i] = desc->clk_register(cprman, desc->data);
++              }
+       }
+       ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
+@@ -2295,8 +2372,12 @@ static int bcm2835_clk_probe(struct plat
+       return 0;
+ }
++static const struct cprman_plat_data cprman_bcm2835_plat_data = {
++      .soc = SOC_BCM2835,
++};
++
+ static const struct of_device_id bcm2835_clk_of_match[] = {
+-      { .compatible = "brcm,bcm2835-cprman", },
++      { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
diff --git a/target/linux/brcm2708/patches-4.19/950-0715-ARM-dts-bcm283x-Enable-HDMI-at-board-level.patch b/target/linux/brcm2708/patches-4.19/950-0715-ARM-dts-bcm283x-Enable-HDMI-at-board-level.patch
deleted file mode 100644 (file)
index 82e126e..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-From a3cbeaaee57b7bda4e921bb2cff649fb56c0292d Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Tue, 17 Sep 2019 19:31:19 +0200
-Subject: [PATCH] ARM: dts: bcm283x: Enable HDMI at board level
-
-commit 60c833d5664e1b3f71c4471233469790adf505ca upstream.
-
-There might be headless setups of the Compute Module without HDMI,
-so better enable HDMI at board level. Btw this allows moving HDMI
-base definition into upcoming bcm2835-common.dtsi.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
-Reviewed-by: Eric Anholt <eric@anholt.net>
----
- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts   | 2 ++
- arch/arm/boot/dts/bcm2835-rpi-a.dts        | 2 ++
- arch/arm/boot/dts/bcm2835-rpi-b-plus.dts   | 2 ++
- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts   | 2 ++
- arch/arm/boot/dts/bcm2835-rpi-b.dts        | 2 ++
- arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts  | 2 ++
- arch/arm/boot/dts/bcm2835-rpi-zero-w.dts   | 2 ++
- arch/arm/boot/dts/bcm2835-rpi-zero.dts     | 2 ++
- arch/arm/boot/dts/bcm2835-rpi.dtsi         | 5 -----
- arch/arm/boot/dts/bcm2836-rpi-2-b.dts      | 2 ++
- arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 ++
- arch/arm/boot/dts/bcm2837-rpi-3-b.dts      | 2 ++
- 12 files changed, 22 insertions(+), 5 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
-@@ -100,6 +100,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &pwm {
---- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
-@@ -95,6 +95,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &pwm {
---- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
-@@ -102,6 +102,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &pwm {
---- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
-@@ -95,6 +95,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &pwm {
---- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
-@@ -90,6 +90,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &pwm {
---- a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
-@@ -79,6 +79,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &sdhost {
---- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
-@@ -113,6 +113,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &sdhci {
---- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts
-+++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
-@@ -103,6 +103,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &sdhost {
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -92,11 +92,6 @@
-       power-domains = <&power RPI_POWER_DOMAIN_V3D>;
- };
--&hdmi {
--      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
--      status = "okay";
--};
--
- &vec {
-       power-domains = <&power RPI_POWER_DOMAIN_VEC>;
-       status = "okay";
---- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-@@ -40,6 +40,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &pwm {
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-@@ -54,6 +54,8 @@
- &hdmi {
-       hpd-gpios = <&gpio 28 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- &pwm {
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-@@ -56,6 +56,8 @@
- &hdmi {
-       hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>;
-+      power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+      status = "okay";
- };
- /* uart0 communicates with the BT module */
diff --git a/target/linux/brcm2708/patches-4.19/950-0715-clk-bcm2835-Add-BCM2711_CLOCK_EMMC2-support.patch b/target/linux/brcm2708/patches-4.19/950-0715-clk-bcm2835-Add-BCM2711_CLOCK_EMMC2-support.patch
new file mode 100644 (file)
index 0000000..8d4b7c9
--- /dev/null
@@ -0,0 +1,91 @@
+From b4c6046e1c55ddf211215191be9ea6316238889b Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Fri, 20 Sep 2019 07:27:03 +0200
+Subject: [PATCH] clk: bcm2835: Add BCM2711_CLOCK_EMMC2 support
+
+commit 42de9ad400afadd41ee027b5feef234a2d2918b9 upstream.
+
+The new BCM2711 supports an additional clock for the emmc2 block.
+So add a new compatible and register this clock only for BCM2711.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Reviewed-by: Matthias Brugger <mbrugger@suse.com>
+Acked-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+---
+ arch/arm/boot/dts/bcm2838.dtsi      |  1 +
+ drivers/clk/bcm/clk-bcm2835.c       | 20 +++++++++++++++++++-
+ include/dt-bindings/clock/bcm2835.h |  2 ++
+ 3 files changed, 22 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -210,7 +210,7 @@
+                       compatible = "brcm,bcm2711-emmc2";
+                       status = "okay";
+                       interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&clocks BCM2838_CLOCK_EMMC2>;
++                      clocks = <&clocks BCM2711_CLOCK_EMMC2>;
+                       reg = <0x7e340000 0x100>;
+               };
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -124,6 +124,8 @@
+ #define CM_AVEODIV            0x1bc
+ #define CM_EMMCCTL            0x1c0
+ #define CM_EMMCDIV            0x1c4
++#define CM_EMMC2CTL           0x1d0
++#define CM_EMMC2DIV           0x1d4
+ /* General bits for the CM_*CTL regs */
+ # define CM_ENABLE                    BIT(4)
+@@ -302,7 +304,8 @@
+ #define VCMSG_ID_CORE_CLOCK     4
+ #define SOC_BCM2835           BIT(0)
+-#define SOC_ALL                       (SOC_BCM2835)
++#define SOC_BCM2711           BIT(1)
++#define SOC_ALL                       (SOC_BCM2835 | SOC_BCM2711)
+ /*
+  * Names of clocks used within the driver that need to be replaced
+@@ -2102,6 +2105,16 @@ static const struct bcm2835_clk_desc clk
+               .frac_bits = 8,
+               .tcnt_mux = 39),
++      /* EMMC2 clock (only available for BCM2711) */
++      [BCM2711_CLOCK_EMMC2]   = REGISTER_PER_CLK(
++              SOC_BCM2711,
++              .name = "emmc2",
++              .ctl_reg = CM_EMMC2CTL,
++              .div_reg = CM_EMMC2DIV,
++              .int_bits = 4,
++              .frac_bits = 8,
++              .tcnt_mux = 42),
++
+       /* General purpose (GPIO) clocks */
+       [BCM2835_CLOCK_GP0]     = REGISTER_PER_CLK(
+               SOC_ALL,
+@@ -2376,8 +2389,13 @@ static const struct cprman_plat_data cpr
+       .soc = SOC_BCM2835,
+ };
++static const struct cprman_plat_data cprman_bcm2711_plat_data = {
++      .soc = SOC_BCM2711,
++};
++
+ static const struct of_device_id bcm2835_clk_of_match[] = {
+       { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
++      { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
+--- a/include/dt-bindings/clock/bcm2835.h
++++ b/include/dt-bindings/clock/bcm2835.h
+@@ -66,3 +66,5 @@
+ #define BCM2835_CLOCK_DSI1E           48
+ #define BCM2835_CLOCK_DSI0P           49
+ #define BCM2835_CLOCK_DSI1P           50
++
++#define BCM2711_CLOCK_EMMC2           51
diff --git a/target/linux/brcm2708/patches-4.19/950-0716-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch b/target/linux/brcm2708/patches-4.19/950-0716-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch
new file mode 100644 (file)
index 0000000..eac69b4
--- /dev/null
@@ -0,0 +1,71 @@
+From 30972497979c65781bb8170743447b45b6dfd3cd Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Thu, 19 Sep 2019 20:45:30 +0200
+Subject: [PATCH] ARM: bcm: Switch board, clk and pinctrl to bcm2711
+ compatible
+
+After the decision to use bcm2711 compatible for upstream, we should
+switch all accepted compatibles to bcm2711. So we can boot with
+one DTB the down- and the upstream kernel.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
+ arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 2 +-
+ arch/arm/boot/dts/bcm2838.dtsi        | 4 ++--
+ arch/arm/mach-bcm/board_bcm2835.c     | 2 +-
+ 4 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -5,7 +5,7 @@
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ / {
+-      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
++      compatible = "raspberrypi,4-model-b", "brcm,bcm2711";
+       model = "Raspberry Pi 4 Model B";
+       memory@0 {
+--- a/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
+@@ -5,7 +5,7 @@
+ #include "bcm2838-rpi.dtsi"
+ / {
+-      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
++      compatible = "raspberrypi,4-model-b", "brcm,bcm2711";
+       model = "Raspberry Pi 4 Model B";
+       chosen {
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -440,7 +440,7 @@
+ };
+ &clocks {
+-      compatible = "brcm,bcm2838-cprman";
++      compatible = "brcm,bcm2711-cprman";
+ };
+ &cpu_thermal {
+@@ -456,7 +456,7 @@
+ };
+ &gpio {
+-      compatible = "brcm,bcm2838-gpio", "brcm,bcm2835-gpio";
++      compatible = "brcm,bcm2711-gpio", "brcm,bcm2835-gpio";
+       gpclk0_gpio49: gpclk0_gpio49 {
+               brcm,pins = <49>;
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -118,7 +118,7 @@ static const char * const bcm2835_compat
+ #ifdef CONFIG_ARCH_MULTI_V7
+       "brcm,bcm2836",
+       "brcm,bcm2837",
+-      "brcm,bcm2838",
++      "brcm,bcm2711",
+ #endif
+       NULL
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0716-clk-bcm2835-Introduce-SoC-specific-clock-registratio.patch b/target/linux/brcm2708/patches-4.19/950-0716-clk-bcm2835-Introduce-SoC-specific-clock-registratio.patch
deleted file mode 100644 (file)
index 52f716e..0000000
+++ /dev/null
@@ -1,597 +0,0 @@
-From 125afc5cf080b29e9114d89f6052fa4a936a3f19 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Thu, 19 Sep 2019 20:12:15 +0200
-Subject: [PATCH] clk: bcm2835: Introduce SoC specific clock
- registration
-
-commit ee0a5a9013b2b2502571a763c3093d400d18191f upstream.
-
-In order to support SoC specific clocks (e.g. emmc2 for BCM2711), we
-extend the description with a SoC support flag. This approach avoids long
-and mostly redundant lists of clock IDs. Since PLLH is specific to
-BCM2835, we register only rest of the clocks as common to all SoC.
-
-Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
-Reviewed-by: Matthias Brugger <mbrugger@suse.com>
-Acked-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Eric Anholt <eric@anholt.net>
----
- drivers/clk/bcm/clk-bcm2835.c | 115 +++++++++++++++++++++++++++++-----
- 1 file changed, 98 insertions(+), 17 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -40,7 +40,7 @@
- #include <linux/debugfs.h>
- #include <linux/delay.h>
- #include <linux/module.h>
--#include <linux/of.h>
-+#include <linux/of_device.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include <dt-bindings/clock/bcm2835.h>
-@@ -301,6 +301,9 @@
- #define VCMSG_ID_CORE_CLOCK     4
-+#define SOC_BCM2835           BIT(0)
-+#define SOC_ALL                       (SOC_BCM2835)
-+
- /*
-  * Names of clocks used within the driver that need to be replaced
-  * with an external parent's name.  This array is in the order that
-@@ -333,6 +336,10 @@ struct bcm2835_cprman {
-       struct clk_hw_onecell_data onecell;
- };
-+struct cprman_plat_data {
-+      unsigned int soc;
-+};
-+
- static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
- {
-       writel(CM_PASSWORD | val, cprman->regs + reg);
-@@ -1528,22 +1535,28 @@ typedef struct clk_hw *(*bcm2835_clk_reg
-                                              const void *data);
- struct bcm2835_clk_desc {
-       bcm2835_clk_register clk_register;
-+      unsigned int supported;
-       const void *data;
- };
- /* assignment helper macros for different clock types */
--#define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \
--                          .data = __VA_ARGS__ }
--#define REGISTER_PLL(...)     _REGISTER(&bcm2835_register_pll,        \
-+#define _REGISTER(f, s, ...) { .clk_register = (bcm2835_clk_register)f, \
-+                             .supported = s,                          \
-+                             .data = __VA_ARGS__ }
-+#define REGISTER_PLL(s, ...)  _REGISTER(&bcm2835_register_pll,        \
-+                                        s,                            \
-                                         &(struct bcm2835_pll_data)    \
-                                         {__VA_ARGS__})
--#define REGISTER_PLL_DIV(...) _REGISTER(&bcm2835_register_pll_divider, \
--                                        &(struct bcm2835_pll_divider_data) \
--                                        {__VA_ARGS__})
--#define REGISTER_CLK(...)     _REGISTER(&bcm2835_register_clock,      \
-+#define REGISTER_PLL_DIV(s, ...) _REGISTER(&bcm2835_register_pll_divider, \
-+                                         s,                             \
-+                                         &(struct bcm2835_pll_divider_data) \
-+                                         {__VA_ARGS__})
-+#define REGISTER_CLK(s, ...)  _REGISTER(&bcm2835_register_clock,      \
-+                                        s,                            \
-                                         &(struct bcm2835_clock_data)  \
-                                         {__VA_ARGS__})
--#define REGISTER_GATE(...)    _REGISTER(&bcm2835_register_gate,       \
-+#define REGISTER_GATE(s, ...) _REGISTER(&bcm2835_register_gate,       \
-+                                        s,                            \
-                                         &(struct bcm2835_gate_data)   \
-                                         {__VA_ARGS__})
-@@ -1557,7 +1570,8 @@ static const char *const bcm2835_clock_o
-       "testdebug1"
- };
--#define REGISTER_OSC_CLK(...) REGISTER_CLK(                           \
-+#define REGISTER_OSC_CLK(s, ...)      REGISTER_CLK(                   \
-+      s,                                                              \
-       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),       \
-       .parents = bcm2835_clock_osc_parents,                           \
-       __VA_ARGS__)
-@@ -1574,7 +1588,8 @@ static const char *const bcm2835_clock_p
-       "pllh_aux",
- };
--#define REGISTER_PER_CLK(...) REGISTER_CLK(                           \
-+#define REGISTER_PER_CLK(s, ...)      REGISTER_CLK(                   \
-+      s,                                                              \
-       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),       \
-       .parents = bcm2835_clock_per_parents,                           \
-       __VA_ARGS__)
-@@ -1599,7 +1614,8 @@ static const char *const bcm2835_pcm_per
-       "-",
- };
--#define REGISTER_PCM_CLK(...) REGISTER_CLK(                           \
-+#define REGISTER_PCM_CLK(s, ...)      REGISTER_CLK(                   \
-+      s,                                                              \
-       .num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents),         \
-       .parents = bcm2835_pcm_per_parents,                             \
-       __VA_ARGS__)
-@@ -1618,7 +1634,8 @@ static const char *const bcm2835_clock_v
-       "pllc_core2",
- };
--#define REGISTER_VPU_CLK(...) REGISTER_CLK(                           \
-+#define REGISTER_VPU_CLK(s, ...)      REGISTER_CLK(                   \
-+      s,                                                              \
-       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),       \
-       .parents = bcm2835_clock_vpu_parents,                           \
-       __VA_ARGS__)
-@@ -1654,12 +1671,14 @@ static const char *const bcm2835_clock_d
-       "dsi1_byte_inv",
- };
--#define REGISTER_DSI0_CLK(...)        REGISTER_CLK(                           \
-+#define REGISTER_DSI0_CLK(s, ...)     REGISTER_CLK(                   \
-+      s,                                                              \
-       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents),      \
-       .parents = bcm2835_clock_dsi0_parents,                          \
-       __VA_ARGS__)
--#define REGISTER_DSI1_CLK(...)        REGISTER_CLK(                           \
-+#define REGISTER_DSI1_CLK(s, ...)     REGISTER_CLK(                   \
-+      s,                                                              \
-       .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents),      \
-       .parents = bcm2835_clock_dsi1_parents,                          \
-       __VA_ARGS__)
-@@ -1679,6 +1698,7 @@ static const struct bcm2835_clk_desc clk
-        * AUDIO domain is on.
-        */
-       [BCM2835_PLLA]          = REGISTER_PLL(
-+              SOC_ALL,
-               .name = "plla",
-               .cm_ctrl_reg = CM_PLLA,
-               .a2w_ctrl_reg = A2W_PLLA_CTRL,
-@@ -1693,6 +1713,7 @@ static const struct bcm2835_clk_desc clk
-               .max_rate = 2400000000u,
-               .max_fb_rate = BCM2835_MAX_FB_RATE),
-       [BCM2835_PLLA_CORE]     = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plla_core",
-               .source_pll = "plla",
-               .cm_reg = CM_PLLA,
-@@ -1702,6 +1723,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLA_PER]      = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plla_per",
-               .source_pll = "plla",
-               .cm_reg = CM_PLLA,
-@@ -1711,6 +1733,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLA_DSI0]     = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plla_dsi0",
-               .source_pll = "plla",
-               .cm_reg = CM_PLLA,
-@@ -1719,6 +1742,7 @@ static const struct bcm2835_clk_desc clk
-               .hold_mask = CM_PLLA_HOLDDSI0,
-               .fixed_divider = 1),
-       [BCM2835_PLLA_CCP2]     = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plla_ccp2",
-               .source_pll = "plla",
-               .cm_reg = CM_PLLA,
-@@ -1730,6 +1754,7 @@ static const struct bcm2835_clk_desc clk
-       /* PLLB is used for the ARM's clock. */
-       [BCM2835_PLLB]          = REGISTER_PLL(
-+              SOC_ALL,
-               .name = "pllb",
-               .cm_ctrl_reg = CM_PLLB,
-               .a2w_ctrl_reg = A2W_PLLB_CTRL,
-@@ -1744,6 +1769,7 @@ static const struct bcm2835_clk_desc clk
-               .max_rate = 3000000000u,
-               .max_fb_rate = BCM2835_MAX_FB_RATE),
-       [BCM2835_PLLB_ARM]      = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "pllb_arm",
-               .source_pll = "pllb",
-               .cm_reg = CM_PLLB,
-@@ -1760,6 +1786,7 @@ static const struct bcm2835_clk_desc clk
-        * AUDIO domain is on.
-        */
-       [BCM2835_PLLC]          = REGISTER_PLL(
-+              SOC_ALL,
-               .name = "pllc",
-               .cm_ctrl_reg = CM_PLLC,
-               .a2w_ctrl_reg = A2W_PLLC_CTRL,
-@@ -1774,6 +1801,7 @@ static const struct bcm2835_clk_desc clk
-               .max_rate = 3000000000u,
-               .max_fb_rate = BCM2835_MAX_FB_RATE),
-       [BCM2835_PLLC_CORE0]    = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "pllc_core0",
-               .source_pll = "pllc",
-               .cm_reg = CM_PLLC,
-@@ -1783,6 +1811,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLC_CORE1]    = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "pllc_core1",
-               .source_pll = "pllc",
-               .cm_reg = CM_PLLC,
-@@ -1792,6 +1821,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLC_CORE2]    = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "pllc_core2",
-               .source_pll = "pllc",
-               .cm_reg = CM_PLLC,
-@@ -1801,6 +1831,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLC_PER]      = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "pllc_per",
-               .source_pll = "pllc",
-               .cm_reg = CM_PLLC,
-@@ -1817,6 +1848,7 @@ static const struct bcm2835_clk_desc clk
-        * AUDIO domain is on.
-        */
-       [BCM2835_PLLD]          = REGISTER_PLL(
-+              SOC_ALL,
-               .name = "plld",
-               .cm_ctrl_reg = CM_PLLD,
-               .a2w_ctrl_reg = A2W_PLLD_CTRL,
-@@ -1831,6 +1863,7 @@ static const struct bcm2835_clk_desc clk
-               .max_rate = 2400000000u,
-               .max_fb_rate = BCM2835_MAX_FB_RATE),
-       [BCM2835_PLLD_CORE]     = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plld_core",
-               .source_pll = "plld",
-               .cm_reg = CM_PLLD,
-@@ -1840,6 +1873,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLD_PER]      = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plld_per",
-               .source_pll = "plld",
-               .cm_reg = CM_PLLD,
-@@ -1849,6 +1883,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLD_DSI0]     = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plld_dsi0",
-               .source_pll = "plld",
-               .cm_reg = CM_PLLD,
-@@ -1857,6 +1892,7 @@ static const struct bcm2835_clk_desc clk
-               .hold_mask = CM_PLLD_HOLDDSI0,
-               .fixed_divider = 1),
-       [BCM2835_PLLD_DSI1]     = REGISTER_PLL_DIV(
-+              SOC_ALL,
-               .name = "plld_dsi1",
-               .source_pll = "plld",
-               .cm_reg = CM_PLLD,
-@@ -1872,6 +1908,7 @@ static const struct bcm2835_clk_desc clk
-        * It is in the HDMI power domain.
-        */
-       [BCM2835_PLLH]          = REGISTER_PLL(
-+              SOC_BCM2835,
-               "pllh",
-               .cm_ctrl_reg = CM_PLLH,
-               .a2w_ctrl_reg = A2W_PLLH_CTRL,
-@@ -1886,6 +1923,7 @@ static const struct bcm2835_clk_desc clk
-               .max_rate = 3000000000u,
-               .max_fb_rate = BCM2835_MAX_FB_RATE),
-       [BCM2835_PLLH_RCAL]     = REGISTER_PLL_DIV(
-+              SOC_BCM2835,
-               .name = "pllh_rcal",
-               .source_pll = "pllh",
-               .cm_reg = CM_PLLH,
-@@ -1895,6 +1933,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 10,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLH_AUX]      = REGISTER_PLL_DIV(
-+              SOC_BCM2835,
-               .name = "pllh_aux",
-               .source_pll = "pllh",
-               .cm_reg = CM_PLLH,
-@@ -1904,6 +1943,7 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
-       [BCM2835_PLLH_PIX]      = REGISTER_PLL_DIV(
-+              SOC_BCM2835,
-               .name = "pllh_pix",
-               .source_pll = "pllh",
-               .cm_reg = CM_PLLH,
-@@ -1919,6 +1959,7 @@ static const struct bcm2835_clk_desc clk
-       /* One Time Programmable Memory clock.  Maximum 10Mhz. */
-       [BCM2835_CLOCK_OTP]     = REGISTER_OSC_CLK(
-+              SOC_ALL,
-               .name = "otp",
-               .ctl_reg = CM_OTPCTL,
-               .div_reg = CM_OTPDIV,
-@@ -1930,6 +1971,7 @@ static const struct bcm2835_clk_desc clk
-        * bythe watchdog timer and the camera pulse generator.
-        */
-       [BCM2835_CLOCK_TIMER]   = REGISTER_OSC_CLK(
-+              SOC_ALL,
-               .name = "timer",
-               .ctl_reg = CM_TIMERCTL,
-               .div_reg = CM_TIMERDIV,
-@@ -1940,12 +1982,14 @@ static const struct bcm2835_clk_desc clk
-        * Generally run at 2Mhz, max 5Mhz.
-        */
-       [BCM2835_CLOCK_TSENS]   = REGISTER_OSC_CLK(
-+              SOC_ALL,
-               .name = "tsens",
-               .ctl_reg = CM_TSENSCTL,
-               .div_reg = CM_TSENSDIV,
-               .int_bits = 5,
-               .frac_bits = 0),
-       [BCM2835_CLOCK_TEC]     = REGISTER_OSC_CLK(
-+              SOC_ALL,
-               .name = "tec",
-               .ctl_reg = CM_TECCTL,
-               .div_reg = CM_TECDIV,
-@@ -1954,6 +1998,7 @@ static const struct bcm2835_clk_desc clk
-       /* clocks with vpu parent mux */
-       [BCM2835_CLOCK_H264]    = REGISTER_VPU_CLK(
-+              SOC_ALL,
-               .name = "h264",
-               .ctl_reg = CM_H264CTL,
-               .div_reg = CM_H264DIV,
-@@ -1961,6 +2006,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 1),
-       [BCM2835_CLOCK_ISP]     = REGISTER_VPU_CLK(
-+              SOC_ALL,
-               .name = "isp",
-               .ctl_reg = CM_ISPCTL,
-               .div_reg = CM_ISPDIV,
-@@ -1973,6 +2019,7 @@ static const struct bcm2835_clk_desc clk
-        * in the SDRAM controller can't be used.
-        */
-       [BCM2835_CLOCK_SDRAM]   = REGISTER_VPU_CLK(
-+              SOC_ALL,
-               .name = "sdram",
-               .ctl_reg = CM_SDCCTL,
-               .div_reg = CM_SDCDIV,
-@@ -1980,6 +2027,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 0,
-               .tcnt_mux = 3),
-       [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
-+              SOC_ALL,
-               .name = "v3d",
-               .ctl_reg = CM_V3DCTL,
-               .div_reg = CM_V3DDIV,
-@@ -1993,6 +2041,7 @@ static const struct bcm2835_clk_desc clk
-        * in various hardware documentation.
-        */
-       [BCM2835_CLOCK_VPU]     = REGISTER_VPU_CLK(
-+              SOC_ALL,
-               .name = "vpu",
-               .ctl_reg = CM_VPUCTL,
-               .div_reg = CM_VPUDIV,
-@@ -2004,6 +2053,7 @@ static const struct bcm2835_clk_desc clk
-       /* clocks with per parent mux */
-       [BCM2835_CLOCK_AVEO]    = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "aveo",
-               .ctl_reg = CM_AVEOCTL,
-               .div_reg = CM_AVEODIV,
-@@ -2011,6 +2061,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 0,
-               .tcnt_mux = 38),
-       [BCM2835_CLOCK_CAM0]    = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "cam0",
-               .ctl_reg = CM_CAM0CTL,
-               .div_reg = CM_CAM0DIV,
-@@ -2018,6 +2069,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 14),
-       [BCM2835_CLOCK_CAM1]    = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "cam1",
-               .ctl_reg = CM_CAM1CTL,
-               .div_reg = CM_CAM1DIV,
-@@ -2025,12 +2077,14 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 15),
-       [BCM2835_CLOCK_DFT]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "dft",
-               .ctl_reg = CM_DFTCTL,
-               .div_reg = CM_DFTDIV,
-               .int_bits = 5,
-               .frac_bits = 0),
-       [BCM2835_CLOCK_DPI]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "dpi",
-               .ctl_reg = CM_DPICTL,
-               .div_reg = CM_DPIDIV,
-@@ -2040,6 +2094,7 @@ static const struct bcm2835_clk_desc clk
-       /* Arasan EMMC clock */
-       [BCM2835_CLOCK_EMMC]    = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "emmc",
-               .ctl_reg = CM_EMMCCTL,
-               .div_reg = CM_EMMCDIV,
-@@ -2049,6 +2104,7 @@ static const struct bcm2835_clk_desc clk
-       /* General purpose (GPIO) clocks */
-       [BCM2835_CLOCK_GP0]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "gp0",
-               .ctl_reg = CM_GP0CTL,
-               .div_reg = CM_GP0DIV,
-@@ -2057,6 +2113,7 @@ static const struct bcm2835_clk_desc clk
-               .is_mash_clock = true,
-               .tcnt_mux = 20),
-       [BCM2835_CLOCK_GP1]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "gp1",
-               .ctl_reg = CM_GP1CTL,
-               .div_reg = CM_GP1DIV,
-@@ -2066,6 +2123,7 @@ static const struct bcm2835_clk_desc clk
-               .is_mash_clock = true,
-               .tcnt_mux = 21),
-       [BCM2835_CLOCK_GP2]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "gp2",
-               .ctl_reg = CM_GP2CTL,
-               .div_reg = CM_GP2DIV,
-@@ -2075,6 +2133,7 @@ static const struct bcm2835_clk_desc clk
-       /* HDMI state machine */
-       [BCM2835_CLOCK_HSM]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "hsm",
-               .ctl_reg = CM_HSMCTL,
-               .div_reg = CM_HSMDIV,
-@@ -2082,6 +2141,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 22),
-       [BCM2835_CLOCK_PCM]     = REGISTER_PCM_CLK(
-+              SOC_ALL,
-               .name = "pcm",
-               .ctl_reg = CM_PCMCTL,
-               .div_reg = CM_PCMDIV,
-@@ -2091,6 +2151,7 @@ static const struct bcm2835_clk_desc clk
-               .low_jitter = true,
-               .tcnt_mux = 23),
-       [BCM2835_CLOCK_PWM]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "pwm",
-               .ctl_reg = CM_PWMCTL,
-               .div_reg = CM_PWMDIV,
-@@ -2099,6 +2160,7 @@ static const struct bcm2835_clk_desc clk
-               .is_mash_clock = true,
-               .tcnt_mux = 24),
-       [BCM2835_CLOCK_SLIM]    = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "slim",
-               .ctl_reg = CM_SLIMCTL,
-               .div_reg = CM_SLIMDIV,
-@@ -2107,6 +2169,7 @@ static const struct bcm2835_clk_desc clk
-               .is_mash_clock = true,
-               .tcnt_mux = 25),
-       [BCM2835_CLOCK_SMI]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "smi",
-               .ctl_reg = CM_SMICTL,
-               .div_reg = CM_SMIDIV,
-@@ -2114,6 +2177,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 27),
-       [BCM2835_CLOCK_UART]    = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "uart",
-               .ctl_reg = CM_UARTCTL,
-               .div_reg = CM_UARTDIV,
-@@ -2123,6 +2187,7 @@ static const struct bcm2835_clk_desc clk
-       /* TV encoder clock.  Only operating frequency is 108Mhz.  */
-       [BCM2835_CLOCK_VEC]     = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "vec",
-               .ctl_reg = CM_VECCTL,
-               .div_reg = CM_VECDIV,
-@@ -2137,6 +2202,7 @@ static const struct bcm2835_clk_desc clk
-       /* dsi clocks */
-       [BCM2835_CLOCK_DSI0E]   = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "dsi0e",
-               .ctl_reg = CM_DSI0ECTL,
-               .div_reg = CM_DSI0EDIV,
-@@ -2144,6 +2210,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 18),
-       [BCM2835_CLOCK_DSI1E]   = REGISTER_PER_CLK(
-+              SOC_ALL,
-               .name = "dsi1e",
-               .ctl_reg = CM_DSI1ECTL,
-               .div_reg = CM_DSI1EDIV,
-@@ -2151,6 +2218,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 19),
-       [BCM2835_CLOCK_DSI0P]   = REGISTER_DSI0_CLK(
-+              SOC_ALL,
-               .name = "dsi0p",
-               .ctl_reg = CM_DSI0PCTL,
-               .div_reg = CM_DSI0PDIV,
-@@ -2158,6 +2226,7 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 0,
-               .tcnt_mux = 12),
-       [BCM2835_CLOCK_DSI1P]   = REGISTER_DSI1_CLK(
-+              SOC_ALL,
-               .name = "dsi1p",
-               .ctl_reg = CM_DSI1PCTL,
-               .div_reg = CM_DSI1PDIV,
-@@ -2174,6 +2243,7 @@ static const struct bcm2835_clk_desc clk
-        * non-stop vpu clock.
-        */
-       [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE(
-+              SOC_ALL,
-               .name = "peri_image",
-               .parent = "vpu",
-               .ctl_reg = CM_PERIICTL),
-@@ -2221,11 +2291,16 @@ static int bcm2835_clk_probe(struct plat
-       struct resource *res;
-       const struct bcm2835_clk_desc *desc;
-       const size_t asize = ARRAY_SIZE(clk_desc_array);
-+      const struct cprman_plat_data *pdata;
-       struct device_node *fw_node;
-       size_t i;
-       u32 clk_id;
-       int ret;
-+      pdata = of_device_get_match_data(&pdev->dev);
-+      if (!pdata)
-+              return -ENODEV;
-+
-       cprman = devm_kzalloc(dev,
-                             struct_size(cprman, onecell.hws, asize),
-                             GFP_KERNEL);
-@@ -2276,8 +2351,10 @@ static int bcm2835_clk_probe(struct plat
-       for (i = 0; i < asize; i++) {
-               desc = &clk_desc_array[i];
--              if (desc->clk_register && desc->data)
-+              if (desc->clk_register && desc->data &&
-+                  (desc->supported & pdata->soc)) {
-                       hws[i] = desc->clk_register(cprman, desc->data);
-+              }
-       }
-       ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
-@@ -2295,8 +2372,12 @@ static int bcm2835_clk_probe(struct plat
-       return 0;
- }
-+static const struct cprman_plat_data cprman_bcm2835_plat_data = {
-+      .soc = SOC_BCM2835,
-+};
-+
- static const struct of_device_id bcm2835_clk_of_match[] = {
--      { .compatible = "brcm,bcm2835-cprman", },
-+      { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
-       {}
- };
- MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
diff --git a/target/linux/brcm2708/patches-4.19/950-0717-clk-bcm2835-Add-BCM2711_CLOCK_EMMC2-support.patch b/target/linux/brcm2708/patches-4.19/950-0717-clk-bcm2835-Add-BCM2711_CLOCK_EMMC2-support.patch
deleted file mode 100644 (file)
index 8d4b7c9..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-From b4c6046e1c55ddf211215191be9ea6316238889b Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Fri, 20 Sep 2019 07:27:03 +0200
-Subject: [PATCH] clk: bcm2835: Add BCM2711_CLOCK_EMMC2 support
-
-commit 42de9ad400afadd41ee027b5feef234a2d2918b9 upstream.
-
-The new BCM2711 supports an additional clock for the emmc2 block.
-So add a new compatible and register this clock only for BCM2711.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
-Reviewed-by: Matthias Brugger <mbrugger@suse.com>
-Acked-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Eric Anholt <eric@anholt.net>
----
- arch/arm/boot/dts/bcm2838.dtsi      |  1 +
- drivers/clk/bcm/clk-bcm2835.c       | 20 +++++++++++++++++++-
- include/dt-bindings/clock/bcm2835.h |  2 ++
- 3 files changed, 22 insertions(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -210,7 +210,7 @@
-                       compatible = "brcm,bcm2711-emmc2";
-                       status = "okay";
-                       interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
--                      clocks = <&clocks BCM2838_CLOCK_EMMC2>;
-+                      clocks = <&clocks BCM2711_CLOCK_EMMC2>;
-                       reg = <0x7e340000 0x100>;
-               };
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -124,6 +124,8 @@
- #define CM_AVEODIV            0x1bc
- #define CM_EMMCCTL            0x1c0
- #define CM_EMMCDIV            0x1c4
-+#define CM_EMMC2CTL           0x1d0
-+#define CM_EMMC2DIV           0x1d4
- /* General bits for the CM_*CTL regs */
- # define CM_ENABLE                    BIT(4)
-@@ -302,7 +304,8 @@
- #define VCMSG_ID_CORE_CLOCK     4
- #define SOC_BCM2835           BIT(0)
--#define SOC_ALL                       (SOC_BCM2835)
-+#define SOC_BCM2711           BIT(1)
-+#define SOC_ALL                       (SOC_BCM2835 | SOC_BCM2711)
- /*
-  * Names of clocks used within the driver that need to be replaced
-@@ -2102,6 +2105,16 @@ static const struct bcm2835_clk_desc clk
-               .frac_bits = 8,
-               .tcnt_mux = 39),
-+      /* EMMC2 clock (only available for BCM2711) */
-+      [BCM2711_CLOCK_EMMC2]   = REGISTER_PER_CLK(
-+              SOC_BCM2711,
-+              .name = "emmc2",
-+              .ctl_reg = CM_EMMC2CTL,
-+              .div_reg = CM_EMMC2DIV,
-+              .int_bits = 4,
-+              .frac_bits = 8,
-+              .tcnt_mux = 42),
-+
-       /* General purpose (GPIO) clocks */
-       [BCM2835_CLOCK_GP0]     = REGISTER_PER_CLK(
-               SOC_ALL,
-@@ -2376,8 +2389,13 @@ static const struct cprman_plat_data cpr
-       .soc = SOC_BCM2835,
- };
-+static const struct cprman_plat_data cprman_bcm2711_plat_data = {
-+      .soc = SOC_BCM2711,
-+};
-+
- static const struct of_device_id bcm2835_clk_of_match[] = {
-       { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
-+      { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
-       {}
- };
- MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
---- a/include/dt-bindings/clock/bcm2835.h
-+++ b/include/dt-bindings/clock/bcm2835.h
-@@ -66,3 +66,5 @@
- #define BCM2835_CLOCK_DSI1E           48
- #define BCM2835_CLOCK_DSI0P           49
- #define BCM2835_CLOCK_DSI1P           50
-+
-+#define BCM2711_CLOCK_EMMC2           51
diff --git a/target/linux/brcm2708/patches-4.19/950-0717-pinctrl-bcm2835-Switch-to-SPDX-identifier.patch b/target/linux/brcm2708/patches-4.19/950-0717-pinctrl-bcm2835-Switch-to-SPDX-identifier.patch
new file mode 100644 (file)
index 0000000..e45c657
--- /dev/null
@@ -0,0 +1,62 @@
+From e60428993b9ba03e2389eeb61c4b5efaa80b9e05 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sat, 10 Nov 2018 17:15:11 +0100
+Subject: [PATCH] pinctrl: bcm2835: Switch to SPDX identifier
+
+commit a62c36775ba873611b00b82ce7ebcd4ff2126111 upstream.
+
+Adopt the SPDX license identifier headers to ease license compliance
+management.
+
+Cc: Simon Arlott <simon@arlott.org>
+Cc: Stephen Warren <swarren@wwwdotorg.org>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 11 +----------
+ include/dt-bindings/pinctrl/bcm2835.h |  8 +-------
+ 2 files changed, 2 insertions(+), 17 deletions(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO)
+  *
+@@ -6,16 +7,6 @@
+  * This driver is inspired by:
+  * pinctrl-nomadik.c, please see original file for copyright information
+  * pinctrl-tegra.c, please see original file for copyright information
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * 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/bitmap.h>
+--- a/include/dt-bindings/pinctrl/bcm2835.h
++++ b/include/dt-bindings/pinctrl/bcm2835.h
+@@ -1,14 +1,8 @@
++/* SPDX-License-Identifier: GPL-2.0 */
+ /*
+  * Header providing constants for bcm2835 pinctrl bindings.
+  *
+  * Copyright (C) 2015 Stefan Wahren <stefan.wahren@i2se.com>
+- *
+- * The code contained herein is licensed under the GNU General Public
+- * License. You may obtain a copy of the GNU General Public License
+- * Version 2 at the following locations:
+- *
+- * http://www.opensource.org/licenses/gpl-license.html
+- * http://www.gnu.org/copyleft/gpl.html
+  */
+ #ifndef __DT_BINDINGS_PINCTRL_BCM2835_H__
diff --git a/target/linux/brcm2708/patches-4.19/950-0718-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch b/target/linux/brcm2708/patches-4.19/950-0718-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch
deleted file mode 100644 (file)
index eac69b4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-From 30972497979c65781bb8170743447b45b6dfd3cd Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Thu, 19 Sep 2019 20:45:30 +0200
-Subject: [PATCH] ARM: bcm: Switch board, clk and pinctrl to bcm2711
- compatible
-
-After the decision to use bcm2711 compatible for upstream, we should
-switch all accepted compatibles to bcm2711. So we can boot with
-one DTB the down- and the upstream kernel.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
- arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 2 +-
- arch/arm/boot/dts/bcm2838.dtsi        | 4 ++--
- arch/arm/mach-bcm/board_bcm2835.c     | 2 +-
- 4 files changed, 5 insertions(+), 5 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -5,7 +5,7 @@
- #include "bcm283x-rpi-csi1-2lane.dtsi"
- / {
--      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
-+      compatible = "raspberrypi,4-model-b", "brcm,bcm2711";
-       model = "Raspberry Pi 4 Model B";
-       memory@0 {
---- a/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
-@@ -5,7 +5,7 @@
- #include "bcm2838-rpi.dtsi"
- / {
--      compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
-+      compatible = "raspberrypi,4-model-b", "brcm,bcm2711";
-       model = "Raspberry Pi 4 Model B";
-       chosen {
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -440,7 +440,7 @@
- };
- &clocks {
--      compatible = "brcm,bcm2838-cprman";
-+      compatible = "brcm,bcm2711-cprman";
- };
- &cpu_thermal {
-@@ -456,7 +456,7 @@
- };
- &gpio {
--      compatible = "brcm,bcm2838-gpio", "brcm,bcm2835-gpio";
-+      compatible = "brcm,bcm2711-gpio", "brcm,bcm2835-gpio";
-       gpclk0_gpio49: gpclk0_gpio49 {
-               brcm,pins = <49>;
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -118,7 +118,7 @@ static const char * const bcm2835_compat
- #ifdef CONFIG_ARCH_MULTI_V7
-       "brcm,bcm2836",
-       "brcm,bcm2837",
--      "brcm,bcm2838",
-+      "brcm,bcm2711",
- #endif
-       NULL
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0718-pinctrl-bcm2835-declare-pin-config-as-generic.patch b/target/linux/brcm2708/patches-4.19/950-0718-pinctrl-bcm2835-declare-pin-config-as-generic.patch
new file mode 100644 (file)
index 0000000..d1ffc9b
--- /dev/null
@@ -0,0 +1,27 @@
+From 2729832886181a4f8bfe1e2c028a7bdb92004ce7 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sun, 3 Feb 2019 14:02:33 +0100
+Subject: [PATCH] pinctrl: bcm2835: declare pin config as generic
+
+commit 1cb66f080c27349fbf87fb327d587b4b0b624fa3 upstream.
+
+Since commit 0de704955ee44 ("pinctrl: bcm2835: Add support for
+generic pinctrl binding") this driver is capable to use the generic
+interface. So declare this accordingly.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -969,6 +969,7 @@ static int bcm2835_pinconf_set(struct pi
+ }
+ static const struct pinconf_ops bcm2835_pinconf_ops = {
++      .is_generic = true,
+       .pin_config_get = bcm2835_pinconf_get,
+       .pin_config_set = bcm2835_pinconf_set,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0719-pinctrl-bcm2835-Direct-GPIO-config-changes-to-generi.patch b/target/linux/brcm2708/patches-4.19/950-0719-pinctrl-bcm2835-Direct-GPIO-config-changes-to-generi.patch
new file mode 100644 (file)
index 0000000..e3d2301
--- /dev/null
@@ -0,0 +1,37 @@
+From 289685a9b369bda990c4f22bbc7659ad492e6dbb Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Sun, 3 Feb 2019 14:02:34 +0100
+Subject: [PATCH] pinctrl: bcm2835: Direct GPIO config changes to
+ generic pinctrl
+
+commit b6e5531c0f80de2779c87d0235b4fde5310a83b5 upstream.
+
+In order to support GPIO config changes direct these to the generic pinctrl.
+This also requires an adjust of the return code for unsupported parameter
+otherwise gpiod_configure_flags wont work as expected.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -342,6 +342,7 @@ static const struct gpio_chip bcm2835_gp
+       .get = bcm2835_gpio_get,
+       .set = bcm2835_gpio_set,
+       .base = 0,
++      .set_config = gpiochip_generic_config,
+       .ngpio = BCM2835_NUM_GPIOS,
+       .can_sleep = false,
+ };
+@@ -960,7 +961,7 @@ static int bcm2835_pinconf_set(struct pi
+                       break;
+               default:
+-                      return -EINVAL;
++                      return -ENOTSUPP;
+               } /* switch param type */
+       } /* for each config */
diff --git a/target/linux/brcm2708/patches-4.19/950-0719-pinctrl-bcm2835-Switch-to-SPDX-identifier.patch b/target/linux/brcm2708/patches-4.19/950-0719-pinctrl-bcm2835-Switch-to-SPDX-identifier.patch
deleted file mode 100644 (file)
index e45c657..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-From e60428993b9ba03e2389eeb61c4b5efaa80b9e05 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sat, 10 Nov 2018 17:15:11 +0100
-Subject: [PATCH] pinctrl: bcm2835: Switch to SPDX identifier
-
-commit a62c36775ba873611b00b82ce7ebcd4ff2126111 upstream.
-
-Adopt the SPDX license identifier headers to ease license compliance
-management.
-
-Cc: Simon Arlott <simon@arlott.org>
-Cc: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 11 +----------
- include/dt-bindings/pinctrl/bcm2835.h |  8 +-------
- 2 files changed, 2 insertions(+), 17 deletions(-)
-
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -1,3 +1,4 @@
-+// SPDX-License-Identifier: GPL-2.0+
- /*
-  * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO)
-  *
-@@ -6,16 +7,6 @@
-  * This driver is inspired by:
-  * pinctrl-nomadik.c, please see original file for copyright information
-  * pinctrl-tegra.c, please see original file for copyright information
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * 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/bitmap.h>
---- a/include/dt-bindings/pinctrl/bcm2835.h
-+++ b/include/dt-bindings/pinctrl/bcm2835.h
-@@ -1,14 +1,8 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
- /*
-  * Header providing constants for bcm2835 pinctrl bindings.
-  *
-  * Copyright (C) 2015 Stefan Wahren <stefan.wahren@i2se.com>
-- *
-- * The code contained herein is licensed under the GNU General Public
-- * License. You may obtain a copy of the GNU General Public License
-- * Version 2 at the following locations:
-- *
-- * http://www.opensource.org/licenses/gpl-license.html
-- * http://www.gnu.org/copyleft/gpl.html
-  */
- #ifndef __DT_BINDINGS_PINCTRL_BCM2835_H__
diff --git a/target/linux/brcm2708/patches-4.19/950-0720-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch b/target/linux/brcm2708/patches-4.19/950-0720-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch
new file mode 100644 (file)
index 0000000..e062477
--- /dev/null
@@ -0,0 +1,183 @@
+From 268bd5b5557ccb0ac4eae998ad7c6261c240b89b Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 21 Jul 2019 16:01:36 +0200
+Subject: [PATCH] pinctrl: bcm2835: Add support for BCM2711 pull-up
+ functionality
+
+commit e38a9a437fb93ddafab5030165e4c6a3a5021669 upstream.
+
+The BCM2711 has a new way of selecting the pull-up/pull-down setting
+for a GPIO pin. The registers used for the BCM2835, GP_PUD and
+GP_PUDCLKn0, are no longer connected. A new set of registers,
+GP_GPIO_PUP_PDN_CNTRL_REGx must be used. This commit will add
+a new compatible string "brcm,bcm2711-gpio" and the kernel
+driver will use it to select which method is used to select
+pull-up/pull-down.
+
+This patch based on a patch by Al Cooper which was intended for the
+BCM7211. This is a bugfixed and improved version.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Acked-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 105 ++++++++++++++++++++++++--
+ 1 file changed, 100 insertions(+), 5 deletions(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -57,15 +57,24 @@
+ #define GPAFEN0               0x88    /* Pin Async Falling Edge Detect */
+ #define GPPUD         0x94    /* Pin Pull-up/down Enable */
+ #define GPPUDCLK0     0x98    /* Pin Pull-up/down Enable Clock */
++#define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */
+ #define FSEL_REG(p)           (GPFSEL0 + (((p) / 10) * 4))
+ #define FSEL_SHIFT(p)         (((p) % 10) * 3)
+ #define GPIO_REG_OFFSET(p)    ((p) / 32)
+ #define GPIO_REG_SHIFT(p)     ((p) % 32)
++#define PUD_2711_MASK         0x3
++#define PUD_2711_REG_OFFSET(p)        ((p) / 16)
++#define PUD_2711_REG_SHIFT(p) (((p) % 16) * 2)
++
+ /* argument: bcm2835_pinconf_pull */
+ #define BCM2835_PINCONF_PARAM_PULL    (PIN_CONFIG_END + 1)
++#define BCM2711_PULL_NONE     0x0
++#define BCM2711_PULL_UP               0x1
++#define BCM2711_PULL_DOWN     0x2
++
+ struct bcm2835_pinctrl {
+       struct device *dev;
+       void __iomem *base;
+@@ -975,6 +984,77 @@ static const struct pinconf_ops bcm2835_
+       .pin_config_set = bcm2835_pinconf_set,
+ };
++static void bcm2711_pull_config_set(struct bcm2835_pinctrl *pc,
++                                  unsigned int pin, unsigned int arg)
++{
++      u32 shifter;
++      u32 value;
++      u32 off;
++
++      off = PUD_2711_REG_OFFSET(pin);
++      shifter = PUD_2711_REG_SHIFT(pin);
++
++      value = bcm2835_gpio_rd(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4));
++      value &= ~(PUD_2711_MASK << shifter);
++      value |= (arg << shifter);
++      bcm2835_gpio_wr(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4), value);
++}
++
++static int bcm2711_pinconf_set(struct pinctrl_dev *pctldev,
++                             unsigned int pin, unsigned long *configs,
++                             unsigned int num_configs)
++{
++      struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
++      u32 param, arg;
++      int i;
++
++      for (i = 0; i < num_configs; i++) {
++              param = pinconf_to_config_param(configs[i]);
++              arg = pinconf_to_config_argument(configs[i]);
++
++              switch (param) {
++              /* convert legacy brcm,pull */
++              case BCM2835_PINCONF_PARAM_PULL:
++                      if (arg == BCM2835_PUD_UP)
++                              arg = BCM2711_PULL_UP;
++                      else if (arg == BCM2835_PUD_DOWN)
++                              arg = BCM2711_PULL_DOWN;
++                      else
++                              arg = BCM2711_PULL_NONE;
++
++                      bcm2711_pull_config_set(pc, pin, arg);
++                      break;
++
++              /* Set pull generic bindings */
++              case PIN_CONFIG_BIAS_DISABLE:
++                      bcm2711_pull_config_set(pc, pin, BCM2711_PULL_NONE);
++                      break;
++              case PIN_CONFIG_BIAS_PULL_DOWN:
++                      bcm2711_pull_config_set(pc, pin, BCM2711_PULL_DOWN);
++                      break;
++              case PIN_CONFIG_BIAS_PULL_UP:
++                      bcm2711_pull_config_set(pc, pin, BCM2711_PULL_UP);
++                      break;
++
++              /* Set output-high or output-low */
++              case PIN_CONFIG_OUTPUT:
++                      bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin);
++                      break;
++
++              default:
++                      return -ENOTSUPP;
++              }
++      } /* for each config */
++
++      return 0;
++}
++
++static const struct pinconf_ops bcm2711_pinconf_ops = {
++      .is_generic = true,
++      .pin_config_get = bcm2835_pinconf_get,
++      .pin_config_set = bcm2711_pinconf_set,
++};
++
+ static struct pinctrl_desc bcm2835_pinctrl_desc = {
+       .name = MODULE_NAME,
+       .pins = bcm2835_gpio_pins,
+@@ -990,6 +1070,18 @@ static struct pinctrl_gpio_range bcm2835
+       .npins = BCM2835_NUM_GPIOS,
+ };
++static const struct of_device_id bcm2835_pinctrl_match[] = {
++      {
++              .compatible = "brcm,bcm2835-gpio",
++              .data = &bcm2835_pinconf_ops,
++      },
++      {
++              .compatible = "brcm,bcm2711-gpio",
++              .data = &bcm2711_pinconf_ops,
++      },
++      {}
++};
++
+ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -997,6 +1089,8 @@ static int bcm2835_pinctrl_probe(struct
+       struct bcm2835_pinctrl *pc;
+       struct resource iomem;
+       int err, i;
++      const struct of_device_id *match;
++
+       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
+       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);
+@@ -1073,6 +1167,12 @@ static int bcm2835_pinctrl_probe(struct
+                                            bcm2835_gpio_irq_handler);
+       }
++      match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
++      if (match) {
++              bcm2835_pinctrl_desc.confops =
++                      (const struct pinconf_ops *)match->data;
++      }
++
+       pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
+       if (IS_ERR(pc->pctl_dev)) {
+               gpiochip_remove(&pc->gpio_chip);
+@@ -1087,11 +1187,6 @@ static int bcm2835_pinctrl_probe(struct
+       return 0;
+ }
+-static const struct of_device_id bcm2835_pinctrl_match[] = {
+-      { .compatible = "brcm,bcm2835-gpio" },
+-      {}
+-};
+-
+ static struct platform_driver bcm2835_pinctrl_driver = {
+       .probe = bcm2835_pinctrl_probe,
+       .driver = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0720-pinctrl-bcm2835-declare-pin-config-as-generic.patch b/target/linux/brcm2708/patches-4.19/950-0720-pinctrl-bcm2835-declare-pin-config-as-generic.patch
deleted file mode 100644 (file)
index d1ffc9b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 2729832886181a4f8bfe1e2c028a7bdb92004ce7 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sun, 3 Feb 2019 14:02:33 +0100
-Subject: [PATCH] pinctrl: bcm2835: declare pin config as generic
-
-commit 1cb66f080c27349fbf87fb327d587b4b0b624fa3 upstream.
-
-Since commit 0de704955ee44 ("pinctrl: bcm2835: Add support for
-generic pinctrl binding") this driver is capable to use the generic
-interface. So declare this accordingly.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -969,6 +969,7 @@ static int bcm2835_pinconf_set(struct pi
- }
- static const struct pinconf_ops bcm2835_pinconf_ops = {
-+      .is_generic = true,
-       .pin_config_get = bcm2835_pinconf_get,
-       .pin_config_set = bcm2835_pinconf_set,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0721-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch b/target/linux/brcm2708/patches-4.19/950-0721-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch
new file mode 100644 (file)
index 0000000..fa3c3a6
--- /dev/null
@@ -0,0 +1,139 @@
+From 1ed6ab5bf2180bd96a78f27fde848f57f4d6b636 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Tue, 24 Sep 2019 18:26:55 +0100
+Subject: [PATCH] Rename HDMI ALSA device names, check for enable state
+
+HDMI Alsa devices renamed to match names used by DRM, to
+HDMI 1 and HDMI 2
+
+Check for which HDMI devices are connected and only create
+devices for those that are present.
+
+The rename of the devices might cause some backwards compatibility
+issues, but since this particular part of the driver needs to be
+specifically enabled, I suspect the number of people who will see
+the problem will be very small.
+
+Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c     | 70 +++++++++++++++++--
+ 1 file changed, 63 insertions(+), 7 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -9,8 +9,9 @@
+ #include <linux/of.h>
+ #include "bcm2835.h"
++#include <soc/bcm2835/raspberrypi-firmware.h>
+-static bool enable_hdmi;
++static bool enable_hdmi, enable_hdmi0, enable_hdmi1;
+ static bool enable_headphones;
+ static bool enable_compat_alsa = true;
+@@ -115,8 +116,8 @@ static struct bcm2835_audio_driver bcm28
+               .name = "bcm2835_hdmi",
+               .owner = THIS_MODULE,
+       },
+-      .shortname = "bcm2835 HDMI",
+-      .longname  = "bcm2835 HDMI",
++      .shortname = "bcm2835 HDMI 1",
++      .longname  = "bcm2835 HDMI 1",
+       .minchannels = 1,
+       .newpcm = bcm2835_audio_simple_newpcm,
+       .newctl = snd_bcm2835_new_hdmi_ctl,
+@@ -128,8 +129,8 @@ static struct bcm2835_audio_driver bcm28
+               .name = "bcm2835_hdmi",
+               .owner = THIS_MODULE,
+       },
+-      .shortname = "bcm2835 HDMI 1",
+-      .longname  = "bcm2835 HDMI 1",
++      .shortname = "bcm2835 HDMI 2",
++      .longname  = "bcm2835 HDMI 2",
+       .minchannels = 1,
+       .newpcm = bcm2835_audio_simple_newpcm,
+       .newctl = snd_bcm2835_new_hdmi_ctl,
+@@ -161,11 +162,11 @@ static struct bcm2835_audio_drivers chil
+       },
+       {
+               .audio_driver = &bcm2835_audio_hdmi0,
+-              .is_enabled = &enable_hdmi,
++              .is_enabled = &enable_hdmi0,
+       },
+       {
+               .audio_driver = &bcm2835_audio_hdmi1,
+-              .is_enabled = &enable_hdmi,
++              .is_enabled = &enable_hdmi1,
+       },
+       {
+               .audio_driver = &bcm2835_audio_headphones,
+@@ -312,6 +313,53 @@ static int snd_add_child_devices(struct
+       return 0;
+ }
++static void set_hdmi_enables(struct device *dev)
++{
++      struct device_node *firmware_node;
++      struct rpi_firmware *firmware;
++      u32 num_displays, i, display_id;
++      int ret;
++
++      firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
++      firmware = rpi_firmware_get(firmware_node);
++
++      if (!firmware)
++              return;
++
++      of_node_put(firmware_node);
++
++      ret = rpi_firmware_property(firmware,
++                                  RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
++                                  &num_displays, sizeof(u32));
++
++      if (ret)
++              return;
++
++      for (i = 0; i < num_displays; i++) {
++              display_id = i;
++              ret = rpi_firmware_property(firmware,
++                              RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
++                              &display_id, sizeof(display_id));
++              if (!ret) {
++                      if (display_id == 2)
++                              enable_hdmi0 = true;
++                      if (display_id == 7)
++                              enable_hdmi1 = true;
++              }
++      }
++
++      if (!enable_hdmi0 && enable_hdmi1) {
++              /* Swap them over and reassign route. This means
++               * that if we only have one connected, it is always named
++               *  HDMI1, irrespective of if its on port HDMI0 or HDMI1.
++               *  This should match with the naming of HDMI ports in DRM
++               */
++              enable_hdmi0 = true;
++              enable_hdmi1 = false;
++              bcm2835_audio_hdmi0.route = AUDIO_DEST_HDMI1;
++      }
++}
++
+ static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -332,6 +380,14 @@ static int snd_bcm2835_alsa_probe(struct
+                        numchans);
+       }
++      if (!enable_compat_alsa) {
++              set_hdmi_enables(dev);
++              // In this mode, always enable analog output
++              enable_headphones = true;
++      } else {
++              enable_hdmi0 = enable_hdmi;
++      }
++
+       err = bcm2835_devm_add_vchi_ctx(dev);
+       if (err)
+               return err;
diff --git a/target/linux/brcm2708/patches-4.19/950-0721-pinctrl-bcm2835-Direct-GPIO-config-changes-to-generi.patch b/target/linux/brcm2708/patches-4.19/950-0721-pinctrl-bcm2835-Direct-GPIO-config-changes-to-generi.patch
deleted file mode 100644 (file)
index e3d2301..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 289685a9b369bda990c4f22bbc7659ad492e6dbb Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Sun, 3 Feb 2019 14:02:34 +0100
-Subject: [PATCH] pinctrl: bcm2835: Direct GPIO config changes to
- generic pinctrl
-
-commit b6e5531c0f80de2779c87d0235b4fde5310a83b5 upstream.
-
-In order to support GPIO config changes direct these to the generic pinctrl.
-This also requires an adjust of the return code for unsupported parameter
-otherwise gpiod_configure_flags wont work as expected.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -342,6 +342,7 @@ static const struct gpio_chip bcm2835_gp
-       .get = bcm2835_gpio_get,
-       .set = bcm2835_gpio_set,
-       .base = 0,
-+      .set_config = gpiochip_generic_config,
-       .ngpio = BCM2835_NUM_GPIOS,
-       .can_sleep = false,
- };
-@@ -960,7 +961,7 @@ static int bcm2835_pinconf_set(struct pi
-                       break;
-               default:
--                      return -EINVAL;
-+                      return -ENOTSUPP;
-               } /* switch param type */
-       } /* for each config */
diff --git a/target/linux/brcm2708/patches-4.19/950-0722-pcie-brcmstb-bounce64.c-dev_err-dev_info-for-info-me.patch b/target/linux/brcm2708/patches-4.19/950-0722-pcie-brcmstb-bounce64.c-dev_err-dev_info-for-info-me.patch
new file mode 100644 (file)
index 0000000..aefa3b8
--- /dev/null
@@ -0,0 +1,25 @@
+From 592f7ebf2755acc81cd794b73916f3b2bcccaa68 Mon Sep 17 00:00:00 2001
+From: Floris Bos <bos@je-eigen-domein.nl>
+Date: Fri, 4 Oct 2019 16:41:30 +0200
+Subject: [PATCH] pcie-brcmstb-bounce64.c: dev_err() -> dev_info() for
+ info messages
+
+"dmabounce: initialised" is not an error, so do not log it as such.
+Prevents screen polution on OS with "quiet" as kernel parameter.
+
+Closes #3266
+---
+ drivers/pci/controller/pcie-brcmstb-bounce64.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb-bounce64.c
++++ b/drivers/pci/controller/pcie-brcmstb-bounce64.c
+@@ -524,7 +524,7 @@ int brcm_pcie_bounce_init(struct device
+       g_dmabounce_device_info = device_info;
+-      dev_err(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
++      dev_info(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
+                buffer_size / 1024, &threshold);
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0722-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch b/target/linux/brcm2708/patches-4.19/950-0722-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch
deleted file mode 100644 (file)
index e062477..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-From 268bd5b5557ccb0ac4eae998ad7c6261c240b89b Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sun, 21 Jul 2019 16:01:36 +0200
-Subject: [PATCH] pinctrl: bcm2835: Add support for BCM2711 pull-up
- functionality
-
-commit e38a9a437fb93ddafab5030165e4c6a3a5021669 upstream.
-
-The BCM2711 has a new way of selecting the pull-up/pull-down setting
-for a GPIO pin. The registers used for the BCM2835, GP_PUD and
-GP_PUDCLKn0, are no longer connected. A new set of registers,
-GP_GPIO_PUP_PDN_CNTRL_REGx must be used. This commit will add
-a new compatible string "brcm,bcm2711-gpio" and the kernel
-driver will use it to select which method is used to select
-pull-up/pull-down.
-
-This patch based on a patch by Al Cooper which was intended for the
-BCM7211. This is a bugfixed and improved version.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
-Acked-by: Eric Anholt <eric@anholt.net>
----
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 105 ++++++++++++++++++++++++--
- 1 file changed, 100 insertions(+), 5 deletions(-)
-
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -57,15 +57,24 @@
- #define GPAFEN0               0x88    /* Pin Async Falling Edge Detect */
- #define GPPUD         0x94    /* Pin Pull-up/down Enable */
- #define GPPUDCLK0     0x98    /* Pin Pull-up/down Enable Clock */
-+#define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */
- #define FSEL_REG(p)           (GPFSEL0 + (((p) / 10) * 4))
- #define FSEL_SHIFT(p)         (((p) % 10) * 3)
- #define GPIO_REG_OFFSET(p)    ((p) / 32)
- #define GPIO_REG_SHIFT(p)     ((p) % 32)
-+#define PUD_2711_MASK         0x3
-+#define PUD_2711_REG_OFFSET(p)        ((p) / 16)
-+#define PUD_2711_REG_SHIFT(p) (((p) % 16) * 2)
-+
- /* argument: bcm2835_pinconf_pull */
- #define BCM2835_PINCONF_PARAM_PULL    (PIN_CONFIG_END + 1)
-+#define BCM2711_PULL_NONE     0x0
-+#define BCM2711_PULL_UP               0x1
-+#define BCM2711_PULL_DOWN     0x2
-+
- struct bcm2835_pinctrl {
-       struct device *dev;
-       void __iomem *base;
-@@ -975,6 +984,77 @@ static const struct pinconf_ops bcm2835_
-       .pin_config_set = bcm2835_pinconf_set,
- };
-+static void bcm2711_pull_config_set(struct bcm2835_pinctrl *pc,
-+                                  unsigned int pin, unsigned int arg)
-+{
-+      u32 shifter;
-+      u32 value;
-+      u32 off;
-+
-+      off = PUD_2711_REG_OFFSET(pin);
-+      shifter = PUD_2711_REG_SHIFT(pin);
-+
-+      value = bcm2835_gpio_rd(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4));
-+      value &= ~(PUD_2711_MASK << shifter);
-+      value |= (arg << shifter);
-+      bcm2835_gpio_wr(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4), value);
-+}
-+
-+static int bcm2711_pinconf_set(struct pinctrl_dev *pctldev,
-+                             unsigned int pin, unsigned long *configs,
-+                             unsigned int num_configs)
-+{
-+      struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-+      u32 param, arg;
-+      int i;
-+
-+      for (i = 0; i < num_configs; i++) {
-+              param = pinconf_to_config_param(configs[i]);
-+              arg = pinconf_to_config_argument(configs[i]);
-+
-+              switch (param) {
-+              /* convert legacy brcm,pull */
-+              case BCM2835_PINCONF_PARAM_PULL:
-+                      if (arg == BCM2835_PUD_UP)
-+                              arg = BCM2711_PULL_UP;
-+                      else if (arg == BCM2835_PUD_DOWN)
-+                              arg = BCM2711_PULL_DOWN;
-+                      else
-+                              arg = BCM2711_PULL_NONE;
-+
-+                      bcm2711_pull_config_set(pc, pin, arg);
-+                      break;
-+
-+              /* Set pull generic bindings */
-+              case PIN_CONFIG_BIAS_DISABLE:
-+                      bcm2711_pull_config_set(pc, pin, BCM2711_PULL_NONE);
-+                      break;
-+              case PIN_CONFIG_BIAS_PULL_DOWN:
-+                      bcm2711_pull_config_set(pc, pin, BCM2711_PULL_DOWN);
-+                      break;
-+              case PIN_CONFIG_BIAS_PULL_UP:
-+                      bcm2711_pull_config_set(pc, pin, BCM2711_PULL_UP);
-+                      break;
-+
-+              /* Set output-high or output-low */
-+              case PIN_CONFIG_OUTPUT:
-+                      bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin);
-+                      break;
-+
-+              default:
-+                      return -ENOTSUPP;
-+              }
-+      } /* for each config */
-+
-+      return 0;
-+}
-+
-+static const struct pinconf_ops bcm2711_pinconf_ops = {
-+      .is_generic = true,
-+      .pin_config_get = bcm2835_pinconf_get,
-+      .pin_config_set = bcm2711_pinconf_set,
-+};
-+
- static struct pinctrl_desc bcm2835_pinctrl_desc = {
-       .name = MODULE_NAME,
-       .pins = bcm2835_gpio_pins,
-@@ -990,6 +1070,18 @@ static struct pinctrl_gpio_range bcm2835
-       .npins = BCM2835_NUM_GPIOS,
- };
-+static const struct of_device_id bcm2835_pinctrl_match[] = {
-+      {
-+              .compatible = "brcm,bcm2835-gpio",
-+              .data = &bcm2835_pinconf_ops,
-+      },
-+      {
-+              .compatible = "brcm,bcm2711-gpio",
-+              .data = &bcm2711_pinconf_ops,
-+      },
-+      {}
-+};
-+
- static int bcm2835_pinctrl_probe(struct platform_device *pdev)
- {
-       struct device *dev = &pdev->dev;
-@@ -997,6 +1089,8 @@ static int bcm2835_pinctrl_probe(struct
-       struct bcm2835_pinctrl *pc;
-       struct resource iomem;
-       int err, i;
-+      const struct of_device_id *match;
-+
-       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
-       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);
-@@ -1073,6 +1167,12 @@ static int bcm2835_pinctrl_probe(struct
-                                            bcm2835_gpio_irq_handler);
-       }
-+      match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
-+      if (match) {
-+              bcm2835_pinctrl_desc.confops =
-+                      (const struct pinconf_ops *)match->data;
-+      }
-+
-       pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
-       if (IS_ERR(pc->pctl_dev)) {
-               gpiochip_remove(&pc->gpio_chip);
-@@ -1087,11 +1187,6 @@ static int bcm2835_pinctrl_probe(struct
-       return 0;
- }
--static const struct of_device_id bcm2835_pinctrl_match[] = {
--      { .compatible = "brcm,bcm2835-gpio" },
--      {}
--};
--
- static struct platform_driver bcm2835_pinctrl_driver = {
-       .probe = bcm2835_pinctrl_probe,
-       .driver = {
diff --git a/target/linux/brcm2708/patches-4.19/950-0723-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch b/target/linux/brcm2708/patches-4.19/950-0723-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch
deleted file mode 100644 (file)
index fa3c3a6..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-From 1ed6ab5bf2180bd96a78f27fde848f57f4d6b636 Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Tue, 24 Sep 2019 18:26:55 +0100
-Subject: [PATCH] Rename HDMI ALSA device names, check for enable state
-
-HDMI Alsa devices renamed to match names used by DRM, to
-HDMI 1 and HDMI 2
-
-Check for which HDMI devices are connected and only create
-devices for those that are present.
-
-The rename of the devices might cause some backwards compatibility
-issues, but since this particular part of the driver needs to be
-specifically enabled, I suspect the number of people who will see
-the problem will be very small.
-
-Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
----
- .../vc04_services/bcm2835-audio/bcm2835.c     | 70 +++++++++++++++++--
- 1 file changed, 63 insertions(+), 7 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -9,8 +9,9 @@
- #include <linux/of.h>
- #include "bcm2835.h"
-+#include <soc/bcm2835/raspberrypi-firmware.h>
--static bool enable_hdmi;
-+static bool enable_hdmi, enable_hdmi0, enable_hdmi1;
- static bool enable_headphones;
- static bool enable_compat_alsa = true;
-@@ -115,8 +116,8 @@ static struct bcm2835_audio_driver bcm28
-               .name = "bcm2835_hdmi",
-               .owner = THIS_MODULE,
-       },
--      .shortname = "bcm2835 HDMI",
--      .longname  = "bcm2835 HDMI",
-+      .shortname = "bcm2835 HDMI 1",
-+      .longname  = "bcm2835 HDMI 1",
-       .minchannels = 1,
-       .newpcm = bcm2835_audio_simple_newpcm,
-       .newctl = snd_bcm2835_new_hdmi_ctl,
-@@ -128,8 +129,8 @@ static struct bcm2835_audio_driver bcm28
-               .name = "bcm2835_hdmi",
-               .owner = THIS_MODULE,
-       },
--      .shortname = "bcm2835 HDMI 1",
--      .longname  = "bcm2835 HDMI 1",
-+      .shortname = "bcm2835 HDMI 2",
-+      .longname  = "bcm2835 HDMI 2",
-       .minchannels = 1,
-       .newpcm = bcm2835_audio_simple_newpcm,
-       .newctl = snd_bcm2835_new_hdmi_ctl,
-@@ -161,11 +162,11 @@ static struct bcm2835_audio_drivers chil
-       },
-       {
-               .audio_driver = &bcm2835_audio_hdmi0,
--              .is_enabled = &enable_hdmi,
-+              .is_enabled = &enable_hdmi0,
-       },
-       {
-               .audio_driver = &bcm2835_audio_hdmi1,
--              .is_enabled = &enable_hdmi,
-+              .is_enabled = &enable_hdmi1,
-       },
-       {
-               .audio_driver = &bcm2835_audio_headphones,
-@@ -312,6 +313,53 @@ static int snd_add_child_devices(struct
-       return 0;
- }
-+static void set_hdmi_enables(struct device *dev)
-+{
-+      struct device_node *firmware_node;
-+      struct rpi_firmware *firmware;
-+      u32 num_displays, i, display_id;
-+      int ret;
-+
-+      firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
-+      firmware = rpi_firmware_get(firmware_node);
-+
-+      if (!firmware)
-+              return;
-+
-+      of_node_put(firmware_node);
-+
-+      ret = rpi_firmware_property(firmware,
-+                                  RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
-+                                  &num_displays, sizeof(u32));
-+
-+      if (ret)
-+              return;
-+
-+      for (i = 0; i < num_displays; i++) {
-+              display_id = i;
-+              ret = rpi_firmware_property(firmware,
-+                              RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
-+                              &display_id, sizeof(display_id));
-+              if (!ret) {
-+                      if (display_id == 2)
-+                              enable_hdmi0 = true;
-+                      if (display_id == 7)
-+                              enable_hdmi1 = true;
-+              }
-+      }
-+
-+      if (!enable_hdmi0 && enable_hdmi1) {
-+              /* Swap them over and reassign route. This means
-+               * that if we only have one connected, it is always named
-+               *  HDMI1, irrespective of if its on port HDMI0 or HDMI1.
-+               *  This should match with the naming of HDMI ports in DRM
-+               */
-+              enable_hdmi0 = true;
-+              enable_hdmi1 = false;
-+              bcm2835_audio_hdmi0.route = AUDIO_DEST_HDMI1;
-+      }
-+}
-+
- static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
- {
-       struct device *dev = &pdev->dev;
-@@ -332,6 +380,14 @@ static int snd_bcm2835_alsa_probe(struct
-                        numchans);
-       }
-+      if (!enable_compat_alsa) {
-+              set_hdmi_enables(dev);
-+              // In this mode, always enable analog output
-+              enable_headphones = true;
-+      } else {
-+              enable_hdmi0 = enable_hdmi;
-+      }
-+
-       err = bcm2835_devm_add_vchi_ctx(dev);
-       if (err)
-               return err;
diff --git a/target/linux/brcm2708/patches-4.19/950-0723-overlays-gpio-shutdown-Add-debounce-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0723-overlays-gpio-shutdown-Add-debounce-parameter.patch
new file mode 100644 (file)
index 0000000..d928458
--- /dev/null
@@ -0,0 +1,48 @@
+From 499e28e3a38f0de843b07bf4bbf7692b07c5e3ba Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 7 Oct 2019 13:51:07 +0100
+Subject: [PATCH] overlays: gpio-shutdown: Add debounce parameter
+
+Give the gpio-shutdown overlay a debounce parameter that requires
+the GPIO to be held at the relevant level for a specified number
+of milliseconds. The default value is 100 - higher than the driver
+default of 5ms to avoid unfortunate glitches.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=253680
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README                    | 3 +++
+ arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts | 2 ++
+ 2 files changed, 5 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -803,6 +803,9 @@ Params: gpio_pin                GPIO pin
+                                 Note that the default pin (GPIO3) has an
+                                 external pullup.
++        debounce                Specify the debounce interval in milliseconds
++                                (default 100)
++
+ Name:   hd44780-lcd
+ Info:   Configures an HD44780 compatible LCD display. Uses 4 gpio pins for
+--- a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
+@@ -53,6 +53,7 @@
+                                       label = "shutdown";
+                                       linux,code = <116>; // KEY_POWER
+                                       gpios = <&gpio 3 1>;
++                                      debounce-interval = <100>; // ms
+                               };
+                       };
+               };
+@@ -75,6 +76,7 @@
+               // Allow setting the active_low flag. 0 = active high, 1 = active low
+               active_low = <&button>,"gpios:8";
++              debounce = <&button>,"debounce-interval:0";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0724-overlays-fix-compatible-for-RPi4.patch b/target/linux/brcm2708/patches-4.19/950-0724-overlays-fix-compatible-for-RPi4.patch
new file mode 100644 (file)
index 0000000..f11066f
--- /dev/null
@@ -0,0 +1,204 @@
+From 8ad712b22e410a5d13bc6678fbee4a5b0ec9b518 Mon Sep 17 00:00:00 2001
+From: Matthias Brugger <mbrugger@suse.com>
+Date: Wed, 2 Oct 2019 18:41:32 +0200
+Subject: [PATCH] overlays: fix compatible for RPi4
+
+RPi4 compatible is now bcm2711, but some overlays refer to the SoC as
+bcm2838. Fix this overlays as they otherwise won't apply.
+
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ arch/arm/boot/dts/overlays/i2c3-overlay.dts     | 2 +-
+ arch/arm/boot/dts/overlays/i2c4-overlay.dts     | 2 +-
+ arch/arm/boot/dts/overlays/i2c5-overlay.dts     | 2 +-
+ arch/arm/boot/dts/overlays/i2c6-overlay.dts     | 2 +-
+ arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/uart2-overlay.dts    | 2 +-
+ arch/arm/boot/dts/overlays/uart3-overlay.dts    | 2 +-
+ arch/arm/boot/dts/overlays/uart4-overlay.dts    | 2 +-
+ arch/arm/boot/dts/overlays/uart5-overlay.dts    | 2 +-
+ 16 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/i2c3-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&i2c3>;
+--- a/arch/arm/boot/dts/overlays/i2c4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&i2c4>;
+--- a/arch/arm/boot/dts/overlays/i2c5-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&i2c5>;
+--- a/arch/arm/boot/dts/overlays/i2c6-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&i2c6>;
+--- a/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi3_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi3_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi4_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi4_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi5_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi5_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi6_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+ / {
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&spi6_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/uart2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart2-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&uart2>;
+--- a/arch/arm/boot/dts/overlays/uart3-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart3-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&uart3>;
+--- a/arch/arm/boot/dts/overlays/uart4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart4-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&uart4>;
+--- a/arch/arm/boot/dts/overlays/uart5-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart5-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+ /{
+-      compatible = "brcm,bcm2838";
++      compatible = "brcm,bcm2711";
+       fragment@0 {
+               target = <&uart5>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0724-pcie-brcmstb-bounce64.c-dev_err-dev_info-for-info-me.patch b/target/linux/brcm2708/patches-4.19/950-0724-pcie-brcmstb-bounce64.c-dev_err-dev_info-for-info-me.patch
deleted file mode 100644 (file)
index aefa3b8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 592f7ebf2755acc81cd794b73916f3b2bcccaa68 Mon Sep 17 00:00:00 2001
-From: Floris Bos <bos@je-eigen-domein.nl>
-Date: Fri, 4 Oct 2019 16:41:30 +0200
-Subject: [PATCH] pcie-brcmstb-bounce64.c: dev_err() -> dev_info() for
- info messages
-
-"dmabounce: initialised" is not an error, so do not log it as such.
-Prevents screen polution on OS with "quiet" as kernel parameter.
-
-Closes #3266
----
- drivers/pci/controller/pcie-brcmstb-bounce64.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/pci/controller/pcie-brcmstb-bounce64.c
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce64.c
-@@ -524,7 +524,7 @@ int brcm_pcie_bounce_init(struct device
-       g_dmabounce_device_info = device_info;
--      dev_err(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
-+      dev_info(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
-                buffer_size / 1024, &threshold);
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0725-bcm2711-Retain-support-for-old-dtbs.patch b/target/linux/brcm2708/patches-4.19/950-0725-bcm2711-Retain-support-for-old-dtbs.patch
new file mode 100644 (file)
index 0000000..14f086c
--- /dev/null
@@ -0,0 +1,55 @@
+From 7d7f6a80f12fb6e7ba903d070512970e304bcd02 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 9 Oct 2019 17:22:07 +0100
+Subject: [PATCH] bcm2711: Retain support for old dtbs
+
+The recent series switching to bcm2711 as the DT identifier broke Pis
+running with old DTBs. Add some bcm2838 compatible strings as a
+temporary measure, at least until the next full Raspbian image with
+bcm2711 DTBs.
+
+See: https://github.com/raspberrypi/linux/pull/3244
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c     | 2 ++
+ drivers/clk/bcm/clk-bcm2835.c         | 2 ++
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 5 +++++
+ 3 files changed, 9 insertions(+)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -119,6 +119,8 @@ static const char * const bcm2835_compat
+       "brcm,bcm2836",
+       "brcm,bcm2837",
+       "brcm,bcm2711",
++      // Temporary, for backwards-compatibility with old DTBs
++      "brcm,bcm2838",
+ #endif
+       NULL
+ };
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -2396,6 +2396,8 @@ static const struct cprman_plat_data cpr
+ static const struct of_device_id bcm2835_clk_of_match[] = {
+       { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
+       { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
++      // Temporary, for backwards-compatibility with old DTBs
++      { .compatible = "brcm,bcm2838-cprman", .data = &cprman_bcm2711_plat_data },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -1079,6 +1079,11 @@ static const struct of_device_id bcm2835
+               .compatible = "brcm,bcm2711-gpio",
+               .data = &bcm2711_pinconf_ops,
+       },
++      // Temporary, for backwards-compatibility with old DTBs
++      {
++              .compatible = "brcm,bcm2838-gpio",
++              .data = &bcm2711_pinconf_ops,
++      },
+       {}
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0725-overlays-gpio-shutdown-Add-debounce-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0725-overlays-gpio-shutdown-Add-debounce-parameter.patch
deleted file mode 100644 (file)
index d928458..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 499e28e3a38f0de843b07bf4bbf7692b07c5e3ba Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 7 Oct 2019 13:51:07 +0100
-Subject: [PATCH] overlays: gpio-shutdown: Add debounce parameter
-
-Give the gpio-shutdown overlay a debounce parameter that requires
-the GPIO to be held at the relevant level for a specified number
-of milliseconds. The default value is 100 - higher than the driver
-default of 5ms to avoid unfortunate glitches.
-
-See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=253680
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README                    | 3 +++
- arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts | 2 ++
- 2 files changed, 5 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -803,6 +803,9 @@ Params: gpio_pin                GPIO pin
-                                 Note that the default pin (GPIO3) has an
-                                 external pullup.
-+        debounce                Specify the debounce interval in milliseconds
-+                                (default 100)
-+
- Name:   hd44780-lcd
- Info:   Configures an HD44780 compatible LCD display. Uses 4 gpio pins for
---- a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
-@@ -53,6 +53,7 @@
-                                       label = "shutdown";
-                                       linux,code = <116>; // KEY_POWER
-                                       gpios = <&gpio 3 1>;
-+                                      debounce-interval = <100>; // ms
-                               };
-                       };
-               };
-@@ -75,6 +76,7 @@
-               // Allow setting the active_low flag. 0 = active high, 1 = active low
-               active_low = <&button>,"gpios:8";
-+              debounce = <&button>,"debounce-interval:0";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0726-media-bcm2835-unicam-Add-support-for-raw14-formats.patch b/target/linux/brcm2708/patches-4.19/950-0726-media-bcm2835-unicam-Add-support-for-raw14-formats.patch
new file mode 100644 (file)
index 0000000..f7fe151
--- /dev/null
@@ -0,0 +1,49 @@
+From 13b916fa2b8a99c9953073316e102e9d027dd708 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 2 Oct 2019 16:09:24 +0100
+Subject: [PATCH] media: bcm2835-unicam: Add support for raw14 formats
+
+The V4L2 has gained defines for V4L2_PIX_FMT_Sxxxx14P,
+therefore add support for it to bcm2835-unicam.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 25 +++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -273,10 +273,31 @@ static const struct unicam_fmt formats[]
+               .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,
+       },
+       /*
+-       * 14 and 16 bit Bayer formats could be supported, but there are no V4L2
+-       * defines for 14bit packed Bayer, and no CSI2 data_type for raw 16.
++       * 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.
+        */
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0726-overlays-fix-compatible-for-RPi4.patch b/target/linux/brcm2708/patches-4.19/950-0726-overlays-fix-compatible-for-RPi4.patch
deleted file mode 100644 (file)
index f11066f..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-From 8ad712b22e410a5d13bc6678fbee4a5b0ec9b518 Mon Sep 17 00:00:00 2001
-From: Matthias Brugger <mbrugger@suse.com>
-Date: Wed, 2 Oct 2019 18:41:32 +0200
-Subject: [PATCH] overlays: fix compatible for RPi4
-
-RPi4 compatible is now bcm2711, but some overlays refer to the SoC as
-bcm2838. Fix this overlays as they otherwise won't apply.
-
-Signed-off-by: Matthias Brugger <mbrugger@suse.com>
----
- arch/arm/boot/dts/overlays/i2c3-overlay.dts     | 2 +-
- arch/arm/boot/dts/overlays/i2c4-overlay.dts     | 2 +-
- arch/arm/boot/dts/overlays/i2c5-overlay.dts     | 2 +-
- arch/arm/boot/dts/overlays/i2c6-overlay.dts     | 2 +-
- arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/uart2-overlay.dts    | 2 +-
- arch/arm/boot/dts/overlays/uart3-overlay.dts    | 2 +-
- arch/arm/boot/dts/overlays/uart4-overlay.dts    | 2 +-
- arch/arm/boot/dts/overlays/uart5-overlay.dts    | 2 +-
- 16 files changed, 16 insertions(+), 16 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/i2c3-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&i2c3>;
---- a/arch/arm/boot/dts/overlays/i2c4-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&i2c4>;
---- a/arch/arm/boot/dts/overlays/i2c5-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&i2c5>;
---- a/arch/arm/boot/dts/overlays/i2c6-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&i2c6>;
---- a/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi3_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi3_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi4_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi4_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi5_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi5_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi6_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
-@@ -3,7 +3,7 @@
- / {
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&spi6_cs_pins>;
---- a/arch/arm/boot/dts/overlays/uart2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart2-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&uart2>;
---- a/arch/arm/boot/dts/overlays/uart3-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart3-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&uart3>;
---- a/arch/arm/boot/dts/overlays/uart4-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart4-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&uart4>;
---- a/arch/arm/boot/dts/overlays/uart5-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart5-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
- /{
--      compatible = "brcm,bcm2838";
-+      compatible = "brcm,bcm2711";
-       fragment@0 {
-               target = <&uart5>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0727-bcm2711-Retain-support-for-old-dtbs.patch b/target/linux/brcm2708/patches-4.19/950-0727-bcm2711-Retain-support-for-old-dtbs.patch
deleted file mode 100644 (file)
index 14f086c..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From 7d7f6a80f12fb6e7ba903d070512970e304bcd02 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 9 Oct 2019 17:22:07 +0100
-Subject: [PATCH] bcm2711: Retain support for old dtbs
-
-The recent series switching to bcm2711 as the DT identifier broke Pis
-running with old DTBs. Add some bcm2838 compatible strings as a
-temporary measure, at least until the next full Raspbian image with
-bcm2711 DTBs.
-
-See: https://github.com/raspberrypi/linux/pull/3244
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/mach-bcm/board_bcm2835.c     | 2 ++
- drivers/clk/bcm/clk-bcm2835.c         | 2 ++
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 5 +++++
- 3 files changed, 9 insertions(+)
-
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -119,6 +119,8 @@ static const char * const bcm2835_compat
-       "brcm,bcm2836",
-       "brcm,bcm2837",
-       "brcm,bcm2711",
-+      // Temporary, for backwards-compatibility with old DTBs
-+      "brcm,bcm2838",
- #endif
-       NULL
- };
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -2396,6 +2396,8 @@ static const struct cprman_plat_data cpr
- static const struct of_device_id bcm2835_clk_of_match[] = {
-       { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
-       { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
-+      // Temporary, for backwards-compatibility with old DTBs
-+      { .compatible = "brcm,bcm2838-cprman", .data = &cprman_bcm2711_plat_data },
-       {}
- };
- MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -1079,6 +1079,11 @@ static const struct of_device_id bcm2835
-               .compatible = "brcm,bcm2711-gpio",
-               .data = &bcm2711_pinconf_ops,
-       },
-+      // Temporary, for backwards-compatibility with old DTBs
-+      {
-+              .compatible = "brcm,bcm2838-gpio",
-+              .data = &bcm2711_pinconf_ops,
-+      },
-       {}
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0727-media-bcm2835-unicam-Rework-to-not-cache-the-list-of.patch b/target/linux/brcm2708/patches-4.19/950-0727-media-bcm2835-unicam-Rework-to-not-cache-the-list-of.patch
new file mode 100644 (file)
index 0000000..3a63871
--- /dev/null
@@ -0,0 +1,387 @@
+From 2c51b8e533a8b43bde18072c9dbbd0fc5084bbe7 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 2 Oct 2019 17:40:38 +0100
+Subject: [PATCH] media: bcm2835-unicam: Rework to not cache the list
+ of active fmts
+
+Some sensors will change Bayer order based on H & V flips,
+therefore collecting the list of formats at async_bound has
+problems.
+
+Enumerate the formats from the sensor every time.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 246 ++++++++++--------
+ 1 file changed, 136 insertions(+), 110 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -363,8 +363,6 @@ struct unicam_device {
+       /* Used to store current mbus frame format */
+       struct v4l2_mbus_framefmt m_fmt;
+-      struct unicam_fmt active_fmts[MAX_POSSIBLE_PIX_FMTS];
+-      int num_active_fmt;
+       unsigned int virtual_channel;
+       enum v4l2_mbus_type bus_type;
+       /*
+@@ -455,48 +453,30 @@ static int find_mbus_depth_by_code(u32 c
+       return 0;
+ }
+-static const struct unicam_fmt *find_format_by_code(struct unicam_device *dev,
+-                                                  u32 code)
++static const struct unicam_fmt *find_format_by_code(u32 code)
+ {
+-      const struct unicam_fmt *fmt;
+       unsigned int k;
+-      for (k = 0; k < dev->num_active_fmt; k++) {
+-              fmt = &dev->active_fmts[k];
+-              if (fmt->code == code)
+-                      return fmt;
++      for (k = 0; k < ARRAY_SIZE(formats); k++) {
++              if (formats[k].code == code)
++                      return &formats[k];
+       }
+       return NULL;
+ }
+-static const struct unicam_fmt *find_format_by_pix(struct unicam_device *dev,
+-                                                 u32 pixelformat)
++static const struct unicam_fmt *find_format_by_pix(u32 pixelformat)
+ {
+-      const struct unicam_fmt *fmt;
+       unsigned int k;
+-      for (k = 0; k < dev->num_active_fmt; k++) {
+-              fmt = &dev->active_fmts[k];
+-              if (fmt->fourcc == pixelformat)
+-                      return fmt;
++      for (k = 0; k < ARRAY_SIZE(formats); k++) {
++              if (formats[k].fourcc == pixelformat)
++                      return &formats[k];
+       }
+       return NULL;
+ }
+-static void dump_active_formats(struct unicam_device *dev)
+-{
+-      int i;
+-
+-      for (i = 0; i < dev->num_active_fmt; i++) {
+-              unicam_dbg(3, dev, "active_fmt[%d] (%p) is code %04x, fourcc " V4L2_FOURCC_CONV ", depth %d\n",
+-                         i, &dev->active_fmts[i], dev->active_fmts[i].code,
+-                         V4L2_FOURCC_CONV_ARGS(dev->active_fmts[i].fourcc),
+-                         dev->active_fmts[i].depth);
+-      }
+-}
+-
+ static inline unsigned int bytes_per_line(u32 width,
+                                         const struct unicam_fmt *fmt)
+ {
+@@ -726,14 +706,40 @@ static int unicam_enum_fmt_vid_cap(struc
+                                  struct v4l2_fmtdesc *f)
+ {
+       struct unicam_device *dev = video_drvdata(file);
++      struct v4l2_subdev_mbus_code_enum mbus_code;
+       const struct unicam_fmt *fmt = NULL;
++      int index = 0;
++      int ret = 0;
++      int i;
+-      if (f->index >= dev->num_active_fmt)
+-              return -EINVAL;
++      /* Loop whilst the sensor driver says it has more formats, but add a
++       * failsafe against a dodgy driver at 128 (more than any sensor will
++       * ever sensibly advertise)
++       */
++      for (i = 0; !ret && i < 128 ; i++) {
++              memset(&mbus_code, 0, sizeof(mbus_code));
++              mbus_code.index = i;
+-      fmt = &dev->active_fmts[f->index];
++              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;
++              }
+-      f->pixelformat = fmt->fourcc;
++              fmt = find_format_by_code(mbus_code.code);
++              if (fmt) {
++                      if (fmt->fourcc) {
++                              if (index == f->index) {
++                                      f->pixelformat = fmt->fourcc;
++                                      break;
++                              }
++                              index++;
++                      }
++              }
++      }
+       return 0;
+ }
+@@ -748,6 +754,39 @@ static int unicam_g_fmt_vid_cap(struct f
+       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;
++      int j;
++
++      for (j = 0; ret != -EINVAL && ret != -ENOIOCTLCMD; ++j) {
++              memset(&mbus_code, 0, sizeof(mbus_code));
++              mbus_code.index = j;
++              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: %04x idx: %d\n",
++                         dev->sensor->name, mbus_code.code, j);
++
++              fmt = find_format_by_code(mbus_code.code);
++              unicam_dbg(2, dev, "fmt %04x returned as %p, V4L2 FOURCC %04x, csi_dt %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)
+ {
+@@ -759,13 +798,15 @@ static int unicam_try_fmt_vid_cap(struct
+       struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
+       int ret;
+-      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
++      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+       if (!fmt) {
+-              unicam_dbg(3, dev, "Fourcc format (0x%08x) not found. Use default of %08X\n",
+-                         f->fmt.pix.pixelformat, dev->active_fmts[0].fourcc);
++              /* 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);
+-              /* Just get the first one enumerated */
+-              fmt = &dev->active_fmts[0];
++              fmt = &formats[0];
+               f->fmt.pix.pixelformat = fmt->fourcc;
+       }
+@@ -785,6 +826,40 @@ static int unicam_try_fmt_vid_cap(struct
+               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");
++                      }
++              }
++
++              f->fmt.pix.pixelformat = fmt->fourcc;
++      }
+       return unicam_calc_format_size_bpl(dev, fmt, f);
+ }
+@@ -805,10 +880,18 @@ static int unicam_s_fmt_vid_cap(struct f
+       if (ret < 0)
+               return ret;
+-      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
++      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+       if (!fmt) {
+-              /* Unknown pixel format - adopt a default */
+-              fmt = &dev->active_fmts[0];
++              /* 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;
+       }
+@@ -944,6 +1027,7 @@ static void unicam_set_packing_config(st
+                       unpack = UNICAM_PUM_NONE;
+                       break;
+               }
++
+               switch (v4l2_depth) {
+               case 8:
+                       pack = UNICAM_PPM_PACK8;
+@@ -1439,7 +1523,7 @@ static int unicam_enum_framesizes(struct
+       int ret;
+       /* check for valid format */
+-      fmt = find_format_by_pix(dev, fsize->pixel_format);
++      fmt = find_format_by_pix(fsize->pixel_format);
+       if (!fmt) {
+               unicam_dbg(3, dev, "Invalid pixel code: %x\n",
+                          fsize->pixel_format);
+@@ -1478,7 +1562,7 @@ static int unicam_enum_frameintervals(st
+       };
+       int ret;
+-      fmt = find_format_by_pix(dev, fival->pixel_format);
++      fmt = find_format_by_pix(fival->pixel_format);
+       if (!fmt)
+               return -EINVAL;
+@@ -1742,27 +1826,6 @@ static const struct v4l2_ioctl_ops unica
+       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
+ };
+-/*
+- * Adds an entry to the active_fmts array
+- * Returns non-zero if attempting to write off the end of the array.
+- */
+-static int unicam_add_active_format(struct unicam_device *unicam,
+-                                  const struct unicam_fmt *fmt)
+-{
+-      //Ensure we don't run off the end of the array.
+-      if (unicam->num_active_fmt >= MAX_POSSIBLE_PIX_FMTS)
+-              return 1;
+-
+-      unicam->active_fmts[unicam->num_active_fmt] = *fmt;
+-      unicam_dbg(2, unicam,
+-                 "matched fourcc: " V4L2_FOURCC_CONV ": code: %04x idx: %d\n",
+-                 V4L2_FOURCC_CONV_ARGS(fmt->fourcc),
+-                 fmt->code, unicam->num_active_fmt);
+-      unicam->num_active_fmt++;
+-
+-      return 0;
+-}
+-
+ static int
+ unicam_async_bound(struct v4l2_async_notifier *notifier,
+                  struct v4l2_subdev *subdev,
+@@ -1770,9 +1833,6 @@ unicam_async_bound(struct v4l2_async_not
+ {
+       struct unicam_device *unicam = container_of(notifier->v4l2_dev,
+                                              struct unicam_device, v4l2_dev);
+-      struct v4l2_subdev_mbus_code_enum mbus_code;
+-      int ret = 0;
+-      int j;
+       if (unicam->sensor) {
+               unicam_info(unicam, "Rejecting subdev %s (Already set!!)",
+@@ -1783,47 +1843,6 @@ unicam_async_bound(struct v4l2_async_not
+       unicam->sensor = subdev;
+       unicam_dbg(1, unicam, "Using sensor %s for capture\n", subdev->name);
+-      /* Enumerate sub device formats and enable all matching local formats */
+-      unicam->num_active_fmt = 0;
+-      unicam_dbg(2, unicam, "Get supported formats...\n");
+-      for (j = 0; ret != -EINVAL && ret != -ENOIOCTLCMD; ++j) {
+-              const struct unicam_fmt *fmt = NULL;
+-              int k;
+-
+-              memset(&mbus_code, 0, sizeof(mbus_code));
+-              mbus_code.index = j;
+-              ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
+-                                     NULL, &mbus_code);
+-              if (ret < 0) {
+-                      unicam_dbg(2, unicam,
+-                                 "subdev->enum_mbus_code idx %d returned %d - continue\n",
+-                                 j, ret);
+-                      continue;
+-              }
+-
+-              unicam_dbg(2, unicam, "subdev %s: code: %04x idx: %d\n",
+-                         subdev->name, mbus_code.code, j);
+-
+-              for (k = 0; k < ARRAY_SIZE(formats); k++) {
+-                      if (mbus_code.code == formats[k].code) {
+-                              fmt = &formats[k];
+-                              break;
+-                      }
+-              }
+-              unicam_dbg(2, unicam, "fmt %04x returned as %p, V4L2 FOURCC %04x, csi_dt %02X\n",
+-                         mbus_code.code, fmt, fmt ? fmt->fourcc : 0,
+-                         fmt ? fmt->csi_dt : 0);
+-              if (fmt) {
+-                      if (unicam_add_active_format(unicam, fmt)) {
+-                              unicam_dbg(1, unicam, "Active fmt list truncated\n");
+-                              break;
+-                      }
+-              }
+-      }
+-      unicam_dbg(2, unicam,
+-                 "Done all formats\n");
+-      dump_active_formats(unicam);
+-
+       return 0;
+ }
+@@ -1849,10 +1868,17 @@ static int unicam_probe_complete(struct
+               return ret;
+       }
+-      fmt = find_format_by_code(unicam, mbus_fmt.code);
++      fmt = find_format_by_code(mbus_fmt.code);
+       if (!fmt) {
+-              /* Default image format not valid. Choose first active fmt. */
+-              fmt = &unicam->active_fmts[0];
++              /* 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);
+               if (ret)
diff --git a/target/linux/brcm2708/patches-4.19/950-0728-media-bcm2835-unicam-Add-support-for-raw14-formats.patch b/target/linux/brcm2708/patches-4.19/950-0728-media-bcm2835-unicam-Add-support-for-raw14-formats.patch
deleted file mode 100644 (file)
index f7fe151..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 13b916fa2b8a99c9953073316e102e9d027dd708 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 2 Oct 2019 16:09:24 +0100
-Subject: [PATCH] media: bcm2835-unicam: Add support for raw14 formats
-
-The V4L2 has gained defines for V4L2_PIX_FMT_Sxxxx14P,
-therefore add support for it to bcm2835-unicam.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c   | 25 +++++++++++++++++--
- 1 file changed, 23 insertions(+), 2 deletions(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -273,10 +273,31 @@ static const struct unicam_fmt formats[]
-               .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,
-       },
-       /*
--       * 14 and 16 bit Bayer formats could be supported, but there are no V4L2
--       * defines for 14bit packed Bayer, and no CSI2 data_type for raw 16.
-+       * 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.
-        */
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0728-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch b/target/linux/brcm2708/patches-4.19/950-0728-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch
new file mode 100644 (file)
index 0000000..199c496
--- /dev/null
@@ -0,0 +1,254 @@
+From 5ae0488f5fc682877ae2a5d454f70884e62120ef Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 3 Oct 2019 13:35:01 +0100
+Subject: [PATCH] media: bcm2835-unicam: Support unpacking CSI format
+ to 16bpp
+
+The CSI packed formats are not the easiest to work with, and
+the peripheral supports unpacking them to 16bpp (but NOT
+shifting the data up into the MSBs).
+Where V4L2 exposes a pixfmt for both packed and unpacked
+formats advertise both as being supported, and unpack the
+data in the peripheral.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 102 +++++++++---------
+ 1 file changed, 51 insertions(+), 51 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -15,12 +15,15 @@
+  *
+  * 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 could repack V4L2_PIX_FMT_Sxxxx10P
++ * 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.
+- * Adding support for repacking and windowing may be added later.
++ * 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.
+@@ -122,13 +125,16 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
+ /*
+  * struct unicam_fmt - Unicam media bus format information
+- * @pixelformat: V4L2 pixel format FCC identifier.
++ * @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 (when stored in memory).
++ * @depth: Bits per pixel as delivered from the source.
+  * @csi_dt: CSI data type.
+  */
+ struct unicam_fmt {
+       u32     fourcc;
++      u32     repacked_fourcc;
+       u32     code;
+       u8      depth;
+       u8      csi_dt;
+@@ -235,41 +241,49 @@ static const struct unicam_fmt formats[]
+               .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,
+@@ -439,20 +453,6 @@ static inline void unicam_runtime_put(st
+ }
+ /* Format setup functions */
+-static int find_mbus_depth_by_code(u32 code)
+-{
+-      const struct unicam_fmt *fmt;
+-      unsigned int k;
+-
+-      for (k = 0; k < ARRAY_SIZE(formats); k++) {
+-              fmt = &formats[k];
+-              if (fmt->code == code)
+-                      return fmt->depth;
+-      }
+-
+-      return 0;
+-}
+-
+ static const struct unicam_fmt *find_format_by_code(u32 code)
+ {
+       unsigned int k;
+@@ -470,7 +470,8 @@ static const struct unicam_fmt *find_for
+       unsigned int k;
+       for (k = 0; k < ARRAY_SIZE(formats); k++) {
+-              if (formats[k].fourcc == pixelformat)
++              if (formats[k].fourcc == pixelformat ||
++                  formats[k].repacked_fourcc == pixelformat)
+                       return &formats[k];
+       }
+@@ -478,9 +479,14 @@ static const struct unicam_fmt *find_for
+ }
+ static inline unsigned int bytes_per_line(u32 width,
+-                                        const struct unicam_fmt *fmt)
++                                        const struct unicam_fmt *fmt,
++                                        u32 v4l2_fourcc)
+ {
+-      return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
++      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,
+@@ -538,7 +544,8 @@ static int unicam_calc_format_size_bpl(s
+                             &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0,
+                             0);
+-      min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt);
++      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)
+@@ -738,6 +745,13 @@ static int unicam_enum_fmt_vid_cap(struc
+                               }
+                               index++;
+                       }
++                      if (fmt->repacked_fourcc) {
++                              if (index == f->index) {
++                                      f->pixelformat = fmt->repacked_fourcc;
++                                      break;
++                              }
++                              index++;
++                      }
+               }
+       }
+@@ -858,7 +872,10 @@ static int unicam_try_fmt_vid_cap(struct
+                       }
+               }
+-              f->fmt.pix.pixelformat = fmt->fourcc;
++              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);
+@@ -998,16 +1015,14 @@ static void unicam_wr_dma_config(struct
+ static void unicam_set_packing_config(struct unicam_device *dev)
+ {
+-      int mbus_depth = find_mbus_depth_by_code(dev->fmt->code);
+-      int v4l2_depth = dev->fmt->depth;
+       int pack, unpack;
+       u32 val;
+-      if (mbus_depth == v4l2_depth) {
++      if (dev->v_fmt.fmt.pix.pixelformat == dev->fmt->fourcc) {
+               unpack = UNICAM_PUM_NONE;
+               pack = UNICAM_PPM_NONE;
+       } else {
+-              switch (mbus_depth) {
++              switch (dev->fmt->depth) {
+               case 8:
+                       unpack = UNICAM_PUM_UNPACK8;
+                       break;
+@@ -1028,26 +1043,8 @@ static void unicam_set_packing_config(st
+                       break;
+               }
+-              switch (v4l2_depth) {
+-              case 8:
+-                      pack = UNICAM_PPM_PACK8;
+-                      break;
+-              case 10:
+-                      pack = UNICAM_PPM_PACK10;
+-                      break;
+-              case 12:
+-                      pack = UNICAM_PPM_PACK12;
+-                      break;
+-              case 14:
+-                      pack = UNICAM_PPM_PACK14;
+-                      break;
+-              case 16:
+-                      pack = UNICAM_PPM_PACK16;
+-                      break;
+-              default:
+-                      pack = UNICAM_PPM_NONE;
+-                      break;
+-              }
++              /* Repacking is always to 16bpp */
++              pack = UNICAM_PPM_PACK16;
+       }
+       val = 0;
+@@ -1893,7 +1890,10 @@ static int unicam_probe_complete(struct
+       }
+       unicam->fmt = fmt;
+-      unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
++      if (fmt->fourcc)
++              unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
++      else
++              unicam->v_fmt.fmt.pix.pixelformat = fmt->repacked_fourcc;
+       /* Read current subdev format */
+       unicam_reset_format(unicam);
diff --git a/target/linux/brcm2708/patches-4.19/950-0729-media-bcm2835-unicam-Add-support-for-luma-greyscale-.patch b/target/linux/brcm2708/patches-4.19/950-0729-media-bcm2835-unicam-Add-support-for-luma-greyscale-.patch
new file mode 100644 (file)
index 0000000..61a817a
--- /dev/null
@@ -0,0 +1,50 @@
+From 253dd469e6403b6c2afd25d4f8338a0c1588583f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 3 Oct 2019 13:45:51 +0100
+Subject: [PATCH] media: bcm2835-unicam: Add support for luma/greyscale
+ formats
+
+Add support for V4L2_PIX_FMT_GREY, V4L2_PIX_FMT_Y10P,
+V4L2_PIX_FMT_Y10, and V4L2_PIX_FMT_Y12 image formats from the
+appropriate mediabus formats advertised by sensors.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 21 ++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -307,12 +307,31 @@ static const struct unicam_fmt formats[]
+               .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,
++      },
+ };
+ struct unicam_dmaqueue {
diff --git a/target/linux/brcm2708/patches-4.19/950-0729-media-bcm2835-unicam-Rework-to-not-cache-the-list-of.patch b/target/linux/brcm2708/patches-4.19/950-0729-media-bcm2835-unicam-Rework-to-not-cache-the-list-of.patch
deleted file mode 100644 (file)
index 3a63871..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-From 2c51b8e533a8b43bde18072c9dbbd0fc5084bbe7 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 2 Oct 2019 17:40:38 +0100
-Subject: [PATCH] media: bcm2835-unicam: Rework to not cache the list
- of active fmts
-
-Some sensors will change Bayer order based on H & V flips,
-therefore collecting the list of formats at async_bound has
-problems.
-
-Enumerate the formats from the sensor every time.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c   | 246 ++++++++++--------
- 1 file changed, 136 insertions(+), 110 deletions(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -363,8 +363,6 @@ struct unicam_device {
-       /* Used to store current mbus frame format */
-       struct v4l2_mbus_framefmt m_fmt;
--      struct unicam_fmt active_fmts[MAX_POSSIBLE_PIX_FMTS];
--      int num_active_fmt;
-       unsigned int virtual_channel;
-       enum v4l2_mbus_type bus_type;
-       /*
-@@ -455,48 +453,30 @@ static int find_mbus_depth_by_code(u32 c
-       return 0;
- }
--static const struct unicam_fmt *find_format_by_code(struct unicam_device *dev,
--                                                  u32 code)
-+static const struct unicam_fmt *find_format_by_code(u32 code)
- {
--      const struct unicam_fmt *fmt;
-       unsigned int k;
--      for (k = 0; k < dev->num_active_fmt; k++) {
--              fmt = &dev->active_fmts[k];
--              if (fmt->code == code)
--                      return fmt;
-+      for (k = 0; k < ARRAY_SIZE(formats); k++) {
-+              if (formats[k].code == code)
-+                      return &formats[k];
-       }
-       return NULL;
- }
--static const struct unicam_fmt *find_format_by_pix(struct unicam_device *dev,
--                                                 u32 pixelformat)
-+static const struct unicam_fmt *find_format_by_pix(u32 pixelformat)
- {
--      const struct unicam_fmt *fmt;
-       unsigned int k;
--      for (k = 0; k < dev->num_active_fmt; k++) {
--              fmt = &dev->active_fmts[k];
--              if (fmt->fourcc == pixelformat)
--                      return fmt;
-+      for (k = 0; k < ARRAY_SIZE(formats); k++) {
-+              if (formats[k].fourcc == pixelformat)
-+                      return &formats[k];
-       }
-       return NULL;
- }
--static void dump_active_formats(struct unicam_device *dev)
--{
--      int i;
--
--      for (i = 0; i < dev->num_active_fmt; i++) {
--              unicam_dbg(3, dev, "active_fmt[%d] (%p) is code %04x, fourcc " V4L2_FOURCC_CONV ", depth %d\n",
--                         i, &dev->active_fmts[i], dev->active_fmts[i].code,
--                         V4L2_FOURCC_CONV_ARGS(dev->active_fmts[i].fourcc),
--                         dev->active_fmts[i].depth);
--      }
--}
--
- static inline unsigned int bytes_per_line(u32 width,
-                                         const struct unicam_fmt *fmt)
- {
-@@ -726,14 +706,40 @@ static int unicam_enum_fmt_vid_cap(struc
-                                  struct v4l2_fmtdesc *f)
- {
-       struct unicam_device *dev = video_drvdata(file);
-+      struct v4l2_subdev_mbus_code_enum mbus_code;
-       const struct unicam_fmt *fmt = NULL;
-+      int index = 0;
-+      int ret = 0;
-+      int i;
--      if (f->index >= dev->num_active_fmt)
--              return -EINVAL;
-+      /* Loop whilst the sensor driver says it has more formats, but add a
-+       * failsafe against a dodgy driver at 128 (more than any sensor will
-+       * ever sensibly advertise)
-+       */
-+      for (i = 0; !ret && i < 128 ; i++) {
-+              memset(&mbus_code, 0, sizeof(mbus_code));
-+              mbus_code.index = i;
--      fmt = &dev->active_fmts[f->index];
-+              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;
-+              }
--      f->pixelformat = fmt->fourcc;
-+              fmt = find_format_by_code(mbus_code.code);
-+              if (fmt) {
-+                      if (fmt->fourcc) {
-+                              if (index == f->index) {
-+                                      f->pixelformat = fmt->fourcc;
-+                                      break;
-+                              }
-+                              index++;
-+                      }
-+              }
-+      }
-       return 0;
- }
-@@ -748,6 +754,39 @@ static int unicam_g_fmt_vid_cap(struct f
-       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;
-+      int j;
-+
-+      for (j = 0; ret != -EINVAL && ret != -ENOIOCTLCMD; ++j) {
-+              memset(&mbus_code, 0, sizeof(mbus_code));
-+              mbus_code.index = j;
-+              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: %04x idx: %d\n",
-+                         dev->sensor->name, mbus_code.code, j);
-+
-+              fmt = find_format_by_code(mbus_code.code);
-+              unicam_dbg(2, dev, "fmt %04x returned as %p, V4L2 FOURCC %04x, csi_dt %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)
- {
-@@ -759,13 +798,15 @@ static int unicam_try_fmt_vid_cap(struct
-       struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
-       int ret;
--      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
-+      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
-       if (!fmt) {
--              unicam_dbg(3, dev, "Fourcc format (0x%08x) not found. Use default of %08X\n",
--                         f->fmt.pix.pixelformat, dev->active_fmts[0].fourcc);
-+              /* 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);
--              /* Just get the first one enumerated */
--              fmt = &dev->active_fmts[0];
-+              fmt = &formats[0];
-               f->fmt.pix.pixelformat = fmt->fourcc;
-       }
-@@ -785,6 +826,40 @@ static int unicam_try_fmt_vid_cap(struct
-               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");
-+                      }
-+              }
-+
-+              f->fmt.pix.pixelformat = fmt->fourcc;
-+      }
-       return unicam_calc_format_size_bpl(dev, fmt, f);
- }
-@@ -805,10 +880,18 @@ static int unicam_s_fmt_vid_cap(struct f
-       if (ret < 0)
-               return ret;
--      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
-+      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
-       if (!fmt) {
--              /* Unknown pixel format - adopt a default */
--              fmt = &dev->active_fmts[0];
-+              /* 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;
-       }
-@@ -944,6 +1027,7 @@ static void unicam_set_packing_config(st
-                       unpack = UNICAM_PUM_NONE;
-                       break;
-               }
-+
-               switch (v4l2_depth) {
-               case 8:
-                       pack = UNICAM_PPM_PACK8;
-@@ -1439,7 +1523,7 @@ static int unicam_enum_framesizes(struct
-       int ret;
-       /* check for valid format */
--      fmt = find_format_by_pix(dev, fsize->pixel_format);
-+      fmt = find_format_by_pix(fsize->pixel_format);
-       if (!fmt) {
-               unicam_dbg(3, dev, "Invalid pixel code: %x\n",
-                          fsize->pixel_format);
-@@ -1478,7 +1562,7 @@ static int unicam_enum_frameintervals(st
-       };
-       int ret;
--      fmt = find_format_by_pix(dev, fival->pixel_format);
-+      fmt = find_format_by_pix(fival->pixel_format);
-       if (!fmt)
-               return -EINVAL;
-@@ -1742,27 +1826,6 @@ static const struct v4l2_ioctl_ops unica
-       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
- };
--/*
-- * Adds an entry to the active_fmts array
-- * Returns non-zero if attempting to write off the end of the array.
-- */
--static int unicam_add_active_format(struct unicam_device *unicam,
--                                  const struct unicam_fmt *fmt)
--{
--      //Ensure we don't run off the end of the array.
--      if (unicam->num_active_fmt >= MAX_POSSIBLE_PIX_FMTS)
--              return 1;
--
--      unicam->active_fmts[unicam->num_active_fmt] = *fmt;
--      unicam_dbg(2, unicam,
--                 "matched fourcc: " V4L2_FOURCC_CONV ": code: %04x idx: %d\n",
--                 V4L2_FOURCC_CONV_ARGS(fmt->fourcc),
--                 fmt->code, unicam->num_active_fmt);
--      unicam->num_active_fmt++;
--
--      return 0;
--}
--
- static int
- unicam_async_bound(struct v4l2_async_notifier *notifier,
-                  struct v4l2_subdev *subdev,
-@@ -1770,9 +1833,6 @@ unicam_async_bound(struct v4l2_async_not
- {
-       struct unicam_device *unicam = container_of(notifier->v4l2_dev,
-                                              struct unicam_device, v4l2_dev);
--      struct v4l2_subdev_mbus_code_enum mbus_code;
--      int ret = 0;
--      int j;
-       if (unicam->sensor) {
-               unicam_info(unicam, "Rejecting subdev %s (Already set!!)",
-@@ -1783,47 +1843,6 @@ unicam_async_bound(struct v4l2_async_not
-       unicam->sensor = subdev;
-       unicam_dbg(1, unicam, "Using sensor %s for capture\n", subdev->name);
--      /* Enumerate sub device formats and enable all matching local formats */
--      unicam->num_active_fmt = 0;
--      unicam_dbg(2, unicam, "Get supported formats...\n");
--      for (j = 0; ret != -EINVAL && ret != -ENOIOCTLCMD; ++j) {
--              const struct unicam_fmt *fmt = NULL;
--              int k;
--
--              memset(&mbus_code, 0, sizeof(mbus_code));
--              mbus_code.index = j;
--              ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
--                                     NULL, &mbus_code);
--              if (ret < 0) {
--                      unicam_dbg(2, unicam,
--                                 "subdev->enum_mbus_code idx %d returned %d - continue\n",
--                                 j, ret);
--                      continue;
--              }
--
--              unicam_dbg(2, unicam, "subdev %s: code: %04x idx: %d\n",
--                         subdev->name, mbus_code.code, j);
--
--              for (k = 0; k < ARRAY_SIZE(formats); k++) {
--                      if (mbus_code.code == formats[k].code) {
--                              fmt = &formats[k];
--                              break;
--                      }
--              }
--              unicam_dbg(2, unicam, "fmt %04x returned as %p, V4L2 FOURCC %04x, csi_dt %02X\n",
--                         mbus_code.code, fmt, fmt ? fmt->fourcc : 0,
--                         fmt ? fmt->csi_dt : 0);
--              if (fmt) {
--                      if (unicam_add_active_format(unicam, fmt)) {
--                              unicam_dbg(1, unicam, "Active fmt list truncated\n");
--                              break;
--                      }
--              }
--      }
--      unicam_dbg(2, unicam,
--                 "Done all formats\n");
--      dump_active_formats(unicam);
--
-       return 0;
- }
-@@ -1849,10 +1868,17 @@ static int unicam_probe_complete(struct
-               return ret;
-       }
--      fmt = find_format_by_code(unicam, mbus_fmt.code);
-+      fmt = find_format_by_code(mbus_fmt.code);
-       if (!fmt) {
--              /* Default image format not valid. Choose first active fmt. */
--              fmt = &unicam->active_fmts[0];
-+              /* 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);
-               if (ret)
diff --git a/target/linux/brcm2708/patches-4.19/950-0730-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch b/target/linux/brcm2708/patches-4.19/950-0730-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch
new file mode 100644 (file)
index 0000000..76129fe
--- /dev/null
@@ -0,0 +1,138 @@
+From 799c83fb9b72bcd473099e3da1395c92a5a581ff Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 17 Sep 2019 18:28:17 +0100
+Subject: [PATCH] drm/vc4: Add support for YUV color encodings and
+ ranges
+
+The BT601/BT709 color encoding and limited vs full
+range properties were not being exposed, defaulting
+always to BT601 limited range.
+
+Expose the parameters and set the registers appropriately.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 72 +++++++++++++++++++++++++++++++--
+ drivers/gpu/drm/vc4/vc4_regs.h  |  3 ++
+ 2 files changed, 72 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -500,6 +500,53 @@ static void vc4_write_scaling_parameters
+       }
+ }
++/* The colorspace conversion matrices are held in 3 entries in the dlist.
++ * Create an array of them, with entries for each full and limited mode, and
++ * each supported colorspace.
++ */
++#define VC4_LIMITED_RANGE     0
++#define VC4_FULL_RANGE                1
++
++static const u32 colorspace_coeffs[2][DRM_COLOR_ENCODING_MAX][3] = {
++      {
++              /* Limited range */
++              {
++                      /* BT601 */
++                      SCALER_CSC0_ITR_R_601_5,
++                      SCALER_CSC1_ITR_R_601_5,
++                      SCALER_CSC2_ITR_R_601_5,
++              }, {
++                      /* BT709 */
++                      SCALER_CSC0_ITR_R_709_3,
++                      SCALER_CSC1_ITR_R_709_3,
++                      SCALER_CSC2_ITR_R_709_3,
++              }, {
++                      /* BT2020. Not supported yet - copy 601 */
++                      SCALER_CSC0_ITR_R_601_5,
++                      SCALER_CSC1_ITR_R_601_5,
++                      SCALER_CSC2_ITR_R_601_5,
++              }
++      }, {
++              /* Full range */
++              {
++                      /* JFIF */
++                      SCALER_CSC0_JPEG_JFIF,
++                      SCALER_CSC1_JPEG_JFIF,
++                      SCALER_CSC2_JPEG_JFIF,
++              }, {
++                      /* BT709 */
++                      SCALER_CSC0_ITR_R_709_3_FR,
++                      SCALER_CSC1_ITR_R_709_3_FR,
++                      SCALER_CSC2_ITR_R_709_3_FR,
++              }, {
++                      /* BT2020. Not supported yet - copy JFIF */
++                      SCALER_CSC0_JPEG_JFIF,
++                      SCALER_CSC1_JPEG_JFIF,
++                      SCALER_CSC2_JPEG_JFIF,
++              }
++      }
++};
++
+ /* Writes out a full display list for an active plane to the plane's
+  * private dlist state.
+  */
+@@ -760,9 +807,20 @@ static int vc4_plane_mode_set(struct drm
+       /* Colorspace conversion words */
+       if (vc4_state->is_yuv) {
+-              vc4_dlist_write(vc4_state, SCALER_CSC0_ITR_R_601_5);
+-              vc4_dlist_write(vc4_state, SCALER_CSC1_ITR_R_601_5);
+-              vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5);
++              enum drm_color_encoding color_encoding = state->color_encoding;
++              enum drm_color_range color_range = state->color_range;
++              const u32 *ccm;
++
++              if (color_encoding >= DRM_COLOR_ENCODING_MAX)
++                      color_encoding = DRM_COLOR_YCBCR_BT601;
++              if (color_range >= DRM_COLOR_RANGE_MAX)
++                      color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
++
++              ccm = colorspace_coeffs[color_range][color_encoding];
++
++              vc4_dlist_write(vc4_state, ccm[0]);
++              vc4_dlist_write(vc4_state, ccm[1]);
++              vc4_dlist_write(vc4_state, ccm[2]);
+       }
+       if (vc4_state->x_scaling[0] != VC4_SCALING_NONE ||
+@@ -1116,5 +1174,13 @@ struct drm_plane *vc4_plane_init(struct
+       drm_plane_create_alpha_property(plane);
++      drm_plane_create_color_properties(plane,
++                                        BIT(DRM_COLOR_YCBCR_BT601) |
++                                        BIT(DRM_COLOR_YCBCR_BT709),
++                                        BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
++                                        BIT(DRM_COLOR_YCBCR_FULL_RANGE),
++                                        DRM_COLOR_YCBCR_BT709,
++                                        DRM_COLOR_YCBCR_LIMITED_RANGE);
++
+       return plane;
+ }
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -972,6 +972,7 @@ enum hvs_pixel_format {
+ #define SCALER_CSC0_ITR_R_601_5                       0x00f00000
+ #define SCALER_CSC0_ITR_R_709_3                       0x00f00000
+ #define SCALER_CSC0_JPEG_JFIF                 0x00000000
++#define SCALER_CSC0_ITR_R_709_3_FR            0x00000000
+ /* S2.8 contribution of Cb to Green */
+ #define SCALER_CSC1_COEF_CB_GRN_MASK          VC4_MASK(31, 22)
+@@ -988,6 +989,7 @@ enum hvs_pixel_format {
+ #define SCALER_CSC1_ITR_R_601_5                       0xe73304a8
+ #define SCALER_CSC1_ITR_R_709_3                       0xf2b784a8
+ #define SCALER_CSC1_JPEG_JFIF                 0xea34a400
++#define SCALER_CSC1_ITR_R_709_3_FR            0xe23d0400
+ /* S2.8 contribution of Cb to Red */
+ #define SCALER_CSC2_COEF_CB_RED_MASK          VC4_MASK(29, 20)
+@@ -1001,6 +1003,7 @@ enum hvs_pixel_format {
+ #define SCALER_CSC2_ITR_R_601_5                       0x00066204
+ #define SCALER_CSC2_ITR_R_709_3                       0x00072a1c
+ #define SCALER_CSC2_JPEG_JFIF                 0x000599c5
++#define SCALER_CSC2_ITR_R_709_3_FR            0x00064ddb
+ #define SCALER_TPZ0_VERT_RECALC                       BIT(31)
+ #define SCALER_TPZ0_SCALE_MASK                        VC4_MASK(28, 8)
diff --git a/target/linux/brcm2708/patches-4.19/950-0730-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch b/target/linux/brcm2708/patches-4.19/950-0730-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch
deleted file mode 100644 (file)
index 199c496..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-From 5ae0488f5fc682877ae2a5d454f70884e62120ef Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 3 Oct 2019 13:35:01 +0100
-Subject: [PATCH] media: bcm2835-unicam: Support unpacking CSI format
- to 16bpp
-
-The CSI packed formats are not the easiest to work with, and
-the peripheral supports unpacking them to 16bpp (but NOT
-shifting the data up into the MSBs).
-Where V4L2 exposes a pixfmt for both packed and unpacked
-formats advertise both as being supported, and unpack the
-data in the peripheral.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c   | 102 +++++++++---------
- 1 file changed, 51 insertions(+), 51 deletions(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -15,12 +15,15 @@
-  *
-  * 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 could repack V4L2_PIX_FMT_Sxxxx10P
-+ * 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.
-- * Adding support for repacking and windowing may be added later.
-+ * 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.
-@@ -122,13 +125,16 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
- /*
-  * struct unicam_fmt - Unicam media bus format information
-- * @pixelformat: V4L2 pixel format FCC identifier.
-+ * @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 (when stored in memory).
-+ * @depth: Bits per pixel as delivered from the source.
-  * @csi_dt: CSI data type.
-  */
- struct unicam_fmt {
-       u32     fourcc;
-+      u32     repacked_fourcc;
-       u32     code;
-       u8      depth;
-       u8      csi_dt;
-@@ -235,41 +241,49 @@ static const struct unicam_fmt formats[]
-               .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,
-@@ -439,20 +453,6 @@ static inline void unicam_runtime_put(st
- }
- /* Format setup functions */
--static int find_mbus_depth_by_code(u32 code)
--{
--      const struct unicam_fmt *fmt;
--      unsigned int k;
--
--      for (k = 0; k < ARRAY_SIZE(formats); k++) {
--              fmt = &formats[k];
--              if (fmt->code == code)
--                      return fmt->depth;
--      }
--
--      return 0;
--}
--
- static const struct unicam_fmt *find_format_by_code(u32 code)
- {
-       unsigned int k;
-@@ -470,7 +470,8 @@ static const struct unicam_fmt *find_for
-       unsigned int k;
-       for (k = 0; k < ARRAY_SIZE(formats); k++) {
--              if (formats[k].fourcc == pixelformat)
-+              if (formats[k].fourcc == pixelformat ||
-+                  formats[k].repacked_fourcc == pixelformat)
-                       return &formats[k];
-       }
-@@ -478,9 +479,14 @@ static const struct unicam_fmt *find_for
- }
- static inline unsigned int bytes_per_line(u32 width,
--                                        const struct unicam_fmt *fmt)
-+                                        const struct unicam_fmt *fmt,
-+                                        u32 v4l2_fourcc)
- {
--      return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
-+      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,
-@@ -538,7 +544,8 @@ static int unicam_calc_format_size_bpl(s
-                             &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0,
-                             0);
--      min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt);
-+      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)
-@@ -738,6 +745,13 @@ static int unicam_enum_fmt_vid_cap(struc
-                               }
-                               index++;
-                       }
-+                      if (fmt->repacked_fourcc) {
-+                              if (index == f->index) {
-+                                      f->pixelformat = fmt->repacked_fourcc;
-+                                      break;
-+                              }
-+                              index++;
-+                      }
-               }
-       }
-@@ -858,7 +872,10 @@ static int unicam_try_fmt_vid_cap(struct
-                       }
-               }
--              f->fmt.pix.pixelformat = fmt->fourcc;
-+              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);
-@@ -998,16 +1015,14 @@ static void unicam_wr_dma_config(struct
- static void unicam_set_packing_config(struct unicam_device *dev)
- {
--      int mbus_depth = find_mbus_depth_by_code(dev->fmt->code);
--      int v4l2_depth = dev->fmt->depth;
-       int pack, unpack;
-       u32 val;
--      if (mbus_depth == v4l2_depth) {
-+      if (dev->v_fmt.fmt.pix.pixelformat == dev->fmt->fourcc) {
-               unpack = UNICAM_PUM_NONE;
-               pack = UNICAM_PPM_NONE;
-       } else {
--              switch (mbus_depth) {
-+              switch (dev->fmt->depth) {
-               case 8:
-                       unpack = UNICAM_PUM_UNPACK8;
-                       break;
-@@ -1028,26 +1043,8 @@ static void unicam_set_packing_config(st
-                       break;
-               }
--              switch (v4l2_depth) {
--              case 8:
--                      pack = UNICAM_PPM_PACK8;
--                      break;
--              case 10:
--                      pack = UNICAM_PPM_PACK10;
--                      break;
--              case 12:
--                      pack = UNICAM_PPM_PACK12;
--                      break;
--              case 14:
--                      pack = UNICAM_PPM_PACK14;
--                      break;
--              case 16:
--                      pack = UNICAM_PPM_PACK16;
--                      break;
--              default:
--                      pack = UNICAM_PPM_NONE;
--                      break;
--              }
-+              /* Repacking is always to 16bpp */
-+              pack = UNICAM_PPM_PACK16;
-       }
-       val = 0;
-@@ -1893,7 +1890,10 @@ static int unicam_probe_complete(struct
-       }
-       unicam->fmt = fmt;
--      unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
-+      if (fmt->fourcc)
-+              unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
-+      else
-+              unicam->v_fmt.fmt.pix.pixelformat = fmt->repacked_fourcc;
-       /* Read current subdev format */
-       unicam_reset_format(unicam);
diff --git a/target/linux/brcm2708/patches-4.19/950-0731-drm-vc4-Fix-negative-X-Y-positioning-on-SAND-planes.patch b/target/linux/brcm2708/patches-4.19/950-0731-drm-vc4-Fix-negative-X-Y-positioning-on-SAND-planes.patch
new file mode 100644 (file)
index 0000000..8c8bb69
--- /dev/null
@@ -0,0 +1,68 @@
+From a8af2085e26bcefad8fb65e2b44d12777a84e219 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Fri, 7 Dec 2018 09:36:05 +0100
+Subject: [PATCH] drm/vc4: Fix negative X/Y positioning on SAND planes
+
+Commit 8e75d582db02bcb171d65ec71eecbd3072a5fd3a upstream.
+
+Commit 3e407417b192 ("drm/vc4: Fix X/Y positioning of planes using
+T_TILES modifier") fixed the problem with T_TILES format, but left
+things in a non-working state for SAND formats. Address that now.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181207083606.15449-1-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -684,6 +684,7 @@ static int vc4_plane_mode_set(struct drm
+       case DRM_FORMAT_MOD_BROADCOM_SAND128:
+       case DRM_FORMAT_MOD_BROADCOM_SAND256: {
+               uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
++              u32 tile_w, tile, x_off, pix_per_tile;
+               /* Column-based NV12 or RGBA.
+                */
+@@ -703,12 +704,15 @@ static int vc4_plane_mode_set(struct drm
+               switch (base_format_mod) {
+               case DRM_FORMAT_MOD_BROADCOM_SAND64:
+                       tiling = SCALER_CTL0_TILING_64B;
++                      tile_w = 64;
+                       break;
+               case DRM_FORMAT_MOD_BROADCOM_SAND128:
+                       tiling = SCALER_CTL0_TILING_128B;
++                      tile_w = 128;
+                       break;
+               case DRM_FORMAT_MOD_BROADCOM_SAND256:
+                       tiling = SCALER_CTL0_TILING_256B_OR_T;
++                      tile_w = 256;
+                       break;
+               default:
+                       break;
+@@ -719,6 +723,23 @@ static int vc4_plane_mode_set(struct drm
+                       return -EINVAL;
+               }
++              pix_per_tile = tile_w / fb->format->cpp[0];
++              tile = vc4_state->src_x / pix_per_tile;
++              x_off = vc4_state->src_x % pix_per_tile;
++
++              /* Adjust the base pointer to the first pixel to be scanned
++               * out.
++               */
++              for (i = 0; i < num_planes; i++) {
++                      vc4_state->offsets[i] += param * tile_w * tile;
++                      vc4_state->offsets[i] += vc4_state->src_y /
++                                               (i ? v_subsample : 1) *
++                                               tile_w;
++                      vc4_state->offsets[i] += x_off /
++                                               (i ? h_subsample : 1) *
++                                               fb->format->cpp[i];
++              }
++
+               pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
+               break;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0731-media-bcm2835-unicam-Add-support-for-luma-greyscale-.patch b/target/linux/brcm2708/patches-4.19/950-0731-media-bcm2835-unicam-Add-support-for-luma-greyscale-.patch
deleted file mode 100644 (file)
index 61a817a..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-From 253dd469e6403b6c2afd25d4f8338a0c1588583f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 3 Oct 2019 13:45:51 +0100
-Subject: [PATCH] media: bcm2835-unicam: Add support for luma/greyscale
- formats
-
-Add support for V4L2_PIX_FMT_GREY, V4L2_PIX_FMT_Y10P,
-V4L2_PIX_FMT_Y10, and V4L2_PIX_FMT_Y12 image formats from the
-appropriate mediabus formats advertised by sensors.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c   | 21 ++++++++++++++++++-
- 1 file changed, 20 insertions(+), 1 deletion(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -307,12 +307,31 @@ static const struct unicam_fmt formats[]
-               .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,
-+      },
- };
- struct unicam_dmaqueue {
diff --git a/target/linux/brcm2708/patches-4.19/950-0732-drm-vc4-Add-support-for-H-V-flips.patch b/target/linux/brcm2708/patches-4.19/950-0732-drm-vc4-Add-support-for-H-V-flips.patch
new file mode 100644 (file)
index 0000000..4c9cb76
--- /dev/null
@@ -0,0 +1,135 @@
+From 1246d16c393a2f5790e5492053f26e6b0b62cec8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 17 Sep 2019 18:36:32 +0100
+Subject: [PATCH] drm/vc4: Add support for H & V flips
+
+The HVS supports horizontal and vertical flips whilst composing.
+
+Expose these through the standard DRM rotation property.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 54 +++++++++++++++++++++++++++------
+ 1 file changed, 45 insertions(+), 9 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -560,7 +560,9 @@ static int vc4_plane_mode_set(struct drm
+       const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
+       u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
+       int num_planes = drm_format_num_planes(format->drm);
++      bool hflip = false, vflip = false;
+       u32 h_subsample, v_subsample;
++      unsigned int rotation;
+       bool mix_plane_alpha;
+       bool covers_screen;
+       u32 scl0, scl1, pitch0;
+@@ -568,11 +570,26 @@ static int vc4_plane_mode_set(struct drm
+       unsigned long irqflags;
+       u32 hvs_format = format->hvs;
+       int ret, i;
++      u32 src_y;
+       ret = vc4_plane_setup_clipping_and_scaling(state);
+       if (ret)
+               return ret;
++      rotation = drm_rotation_simplify(state->rotation,
++                                       DRM_MODE_ROTATE_0 |
++                                       DRM_MODE_REFLECT_X |
++                                       DRM_MODE_REFLECT_Y);
++
++      if ((rotation & DRM_MODE_ROTATE_MASK) == DRM_MODE_ROTATE_180) {
++              hflip = true;
++              vflip = true;
++      }
++      if (rotation & DRM_MODE_REFLECT_X)
++              hflip ^= true;
++      if (rotation & DRM_MODE_REFLECT_Y)
++              vflip ^= true;
++
+       /* Allocate the LBM memory that the HVS will use for temporary
+        * storage due to our scaling/format conversion.
+        */
+@@ -609,6 +626,16 @@ static int vc4_plane_mode_set(struct drm
+       h_subsample = drm_format_horz_chroma_subsampling(format->drm);
+       v_subsample = drm_format_vert_chroma_subsampling(format->drm);
++      if (!vflip)
++              src_y = vc4_state->src_y;
++      else
++              /* When vflipped the image offset needs to be
++               * the start of the last line of the image, and
++               * the pitch will be subtracted from the offset.
++               */
++              src_y = vc4_state->src_y +
++                      vc4_state->src_h[0] - 1;
++
+       switch (base_format_mod) {
+       case DRM_FORMAT_MOD_LINEAR:
+               tiling = SCALER_CTL0_TILING_LINEAR;
+@@ -618,12 +645,13 @@ static int vc4_plane_mode_set(struct drm
+                * out.
+                */
+               for (i = 0; i < num_planes; i++) {
+-                      vc4_state->offsets[i] += vc4_state->src_y /
++                      vc4_state->offsets[i] += src_y /
+                                                (i ? v_subsample : 1) *
+                                                fb->pitches[i];
++
+                       vc4_state->offsets[i] += vc4_state->src_x /
+-                                               (i ? h_subsample : 1) *
+-                                               fb->format->cpp[i];
++                                              (i ? h_subsample : 1) *
++                                              fb->format->cpp[i];
+               }
+               break;
+@@ -651,11 +679,11 @@ static int vc4_plane_mode_set(struct drm
+                * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
+                * base address).
+                */
+-              u32 tile_y = (vc4_state->src_y >> 4) & 1;
+-              u32 subtile_y = (vc4_state->src_y >> 2) & 3;
+-              u32 utile_y = vc4_state->src_y & 3;
++              u32 tile_y = (src_y >> 4) & 1;
++              u32 subtile_y = (src_y >> 2) & 3;
++              u32 utile_y = src_y & 3;
+               u32 x_off = vc4_state->src_x & tile_w_mask;
+-              u32 y_off = vc4_state->src_y & tile_h_mask;
++              u32 y_off = src_y & tile_h_mask;
+               tiling = SCALER_CTL0_TILING_256B_OR_T;
+               pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
+@@ -732,7 +760,7 @@ static int vc4_plane_mode_set(struct drm
+                */
+               for (i = 0; i < num_planes; i++) {
+                       vc4_state->offsets[i] += param * tile_w * tile;
+-                      vc4_state->offsets[i] += vc4_state->src_y /
++                      vc4_state->offsets[i] += src_y /
+                                                (i ? v_subsample : 1) *
+                                                tile_w;
+                       vc4_state->offsets[i] += x_off /
+@@ -759,7 +787,9 @@ static int vc4_plane_mode_set(struct drm
+                       VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
+                       (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
+                       VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
+-                      VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
++                      VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1) |
++                      (vflip ? SCALER_CTL0_VFLIP : 0) |
++                      (hflip ? SCALER_CTL0_HFLIP : 0));
+       /* Position Word 0: Image Positions and Alpha Value */
+       vc4_state->pos0_offset = vc4_state->dlist_count;
+@@ -1203,5 +1233,11 @@ struct drm_plane *vc4_plane_init(struct
+                                         DRM_COLOR_YCBCR_BT709,
+                                         DRM_COLOR_YCBCR_LIMITED_RANGE);
++      drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
++                                         DRM_MODE_ROTATE_0 |
++                                         DRM_MODE_ROTATE_180 |
++                                         DRM_MODE_REFLECT_X |
++                                         DRM_MODE_REFLECT_Y);
++
+       return plane;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0732-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch b/target/linux/brcm2708/patches-4.19/950-0732-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch
deleted file mode 100644 (file)
index 76129fe..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-From 799c83fb9b72bcd473099e3da1395c92a5a581ff Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 17 Sep 2019 18:28:17 +0100
-Subject: [PATCH] drm/vc4: Add support for YUV color encodings and
- ranges
-
-The BT601/BT709 color encoding and limited vs full
-range properties were not being exposed, defaulting
-always to BT601 limited range.
-
-Expose the parameters and set the registers appropriately.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_plane.c | 72 +++++++++++++++++++++++++++++++--
- drivers/gpu/drm/vc4/vc4_regs.h  |  3 ++
- 2 files changed, 72 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -500,6 +500,53 @@ static void vc4_write_scaling_parameters
-       }
- }
-+/* The colorspace conversion matrices are held in 3 entries in the dlist.
-+ * Create an array of them, with entries for each full and limited mode, and
-+ * each supported colorspace.
-+ */
-+#define VC4_LIMITED_RANGE     0
-+#define VC4_FULL_RANGE                1
-+
-+static const u32 colorspace_coeffs[2][DRM_COLOR_ENCODING_MAX][3] = {
-+      {
-+              /* Limited range */
-+              {
-+                      /* BT601 */
-+                      SCALER_CSC0_ITR_R_601_5,
-+                      SCALER_CSC1_ITR_R_601_5,
-+                      SCALER_CSC2_ITR_R_601_5,
-+              }, {
-+                      /* BT709 */
-+                      SCALER_CSC0_ITR_R_709_3,
-+                      SCALER_CSC1_ITR_R_709_3,
-+                      SCALER_CSC2_ITR_R_709_3,
-+              }, {
-+                      /* BT2020. Not supported yet - copy 601 */
-+                      SCALER_CSC0_ITR_R_601_5,
-+                      SCALER_CSC1_ITR_R_601_5,
-+                      SCALER_CSC2_ITR_R_601_5,
-+              }
-+      }, {
-+              /* Full range */
-+              {
-+                      /* JFIF */
-+                      SCALER_CSC0_JPEG_JFIF,
-+                      SCALER_CSC1_JPEG_JFIF,
-+                      SCALER_CSC2_JPEG_JFIF,
-+              }, {
-+                      /* BT709 */
-+                      SCALER_CSC0_ITR_R_709_3_FR,
-+                      SCALER_CSC1_ITR_R_709_3_FR,
-+                      SCALER_CSC2_ITR_R_709_3_FR,
-+              }, {
-+                      /* BT2020. Not supported yet - copy JFIF */
-+                      SCALER_CSC0_JPEG_JFIF,
-+                      SCALER_CSC1_JPEG_JFIF,
-+                      SCALER_CSC2_JPEG_JFIF,
-+              }
-+      }
-+};
-+
- /* Writes out a full display list for an active plane to the plane's
-  * private dlist state.
-  */
-@@ -760,9 +807,20 @@ static int vc4_plane_mode_set(struct drm
-       /* Colorspace conversion words */
-       if (vc4_state->is_yuv) {
--              vc4_dlist_write(vc4_state, SCALER_CSC0_ITR_R_601_5);
--              vc4_dlist_write(vc4_state, SCALER_CSC1_ITR_R_601_5);
--              vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5);
-+              enum drm_color_encoding color_encoding = state->color_encoding;
-+              enum drm_color_range color_range = state->color_range;
-+              const u32 *ccm;
-+
-+              if (color_encoding >= DRM_COLOR_ENCODING_MAX)
-+                      color_encoding = DRM_COLOR_YCBCR_BT601;
-+              if (color_range >= DRM_COLOR_RANGE_MAX)
-+                      color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
-+
-+              ccm = colorspace_coeffs[color_range][color_encoding];
-+
-+              vc4_dlist_write(vc4_state, ccm[0]);
-+              vc4_dlist_write(vc4_state, ccm[1]);
-+              vc4_dlist_write(vc4_state, ccm[2]);
-       }
-       if (vc4_state->x_scaling[0] != VC4_SCALING_NONE ||
-@@ -1116,5 +1174,13 @@ struct drm_plane *vc4_plane_init(struct
-       drm_plane_create_alpha_property(plane);
-+      drm_plane_create_color_properties(plane,
-+                                        BIT(DRM_COLOR_YCBCR_BT601) |
-+                                        BIT(DRM_COLOR_YCBCR_BT709),
-+                                        BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
-+                                        BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-+                                        DRM_COLOR_YCBCR_BT709,
-+                                        DRM_COLOR_YCBCR_LIMITED_RANGE);
-+
-       return plane;
- }
---- a/drivers/gpu/drm/vc4/vc4_regs.h
-+++ b/drivers/gpu/drm/vc4/vc4_regs.h
-@@ -972,6 +972,7 @@ enum hvs_pixel_format {
- #define SCALER_CSC0_ITR_R_601_5                       0x00f00000
- #define SCALER_CSC0_ITR_R_709_3                       0x00f00000
- #define SCALER_CSC0_JPEG_JFIF                 0x00000000
-+#define SCALER_CSC0_ITR_R_709_3_FR            0x00000000
- /* S2.8 contribution of Cb to Green */
- #define SCALER_CSC1_COEF_CB_GRN_MASK          VC4_MASK(31, 22)
-@@ -988,6 +989,7 @@ enum hvs_pixel_format {
- #define SCALER_CSC1_ITR_R_601_5                       0xe73304a8
- #define SCALER_CSC1_ITR_R_709_3                       0xf2b784a8
- #define SCALER_CSC1_JPEG_JFIF                 0xea34a400
-+#define SCALER_CSC1_ITR_R_709_3_FR            0xe23d0400
- /* S2.8 contribution of Cb to Red */
- #define SCALER_CSC2_COEF_CB_RED_MASK          VC4_MASK(29, 20)
-@@ -1001,6 +1003,7 @@ enum hvs_pixel_format {
- #define SCALER_CSC2_ITR_R_601_5                       0x00066204
- #define SCALER_CSC2_ITR_R_709_3                       0x00072a1c
- #define SCALER_CSC2_JPEG_JFIF                 0x000599c5
-+#define SCALER_CSC2_ITR_R_709_3_FR            0x00064ddb
- #define SCALER_TPZ0_VERT_RECALC                       BIT(31)
- #define SCALER_TPZ0_SCALE_MASK                        VC4_MASK(28, 8)
diff --git a/target/linux/brcm2708/patches-4.19/950-0733-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch b/target/linux/brcm2708/patches-4.19/950-0733-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch
new file mode 100644 (file)
index 0000000..d08b7f0
--- /dev/null
@@ -0,0 +1,87 @@
+From e99a60f018524bf7b1ba382e3994c22ebcdbafe6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 18 Sep 2019 15:49:13 +0100
+Subject: [PATCH] drm/vc4: Correct handling of rotation parameter in
+ fkms
+
+One bit within DRM_MODE_ROTATE_MASK will always be set to
+determine the base rotation 0/90/180/270, and then REFLECT_X
+and REFLECT_Y are on top.
+
+Correct the handling which was assuming that REFLECT_[X|Y]
+was instead of ROTATE_x.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 37 ++++++++++----------------
+ 1 file changed, 14 insertions(+), 23 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -79,11 +79,6 @@ struct set_plane {
+ #define TRANSFORM_FLIP_HRIZ   BIT(16)
+ #define TRANSFORM_FLIP_VERT   BIT(17)
+-#define SUPPORTED_ROTATIONS   (DRM_MODE_ROTATE_0 | \
+-                               DRM_MODE_ROTATE_180 | \
+-                               DRM_MODE_REFLECT_X | \
+-                               DRM_MODE_REFLECT_Y)
+-
+ struct mailbox_set_plane {
+       struct rpi_firmware_property_tag_header tag;
+       struct set_plane plane;
+@@ -523,7 +518,7 @@ static int vc4_plane_to_mb(struct drm_pl
+       const struct vc_image_format *vc_fmt =
+                                       vc4_get_vc_image_fmt(drm_fmt->format);
+       int num_planes = fb->format->num_planes;
+-      unsigned int rotation = SUPPORTED_ROTATIONS;
++      unsigned int rotation;
+       mb->plane.vc_image_type = vc_fmt->vc_image;
+       mb->plane.width = fb->width;
+@@ -544,23 +539,16 @@ static int vc4_plane_to_mb(struct drm_pl
+       mb->plane.is_vu = vc_fmt->is_vu;
+       mb->plane.planes[0] = bo->paddr + fb->offsets[0];
+-      rotation = drm_rotation_simplify(state->rotation, rotation);
+-
+-      switch (rotation) {
+-      default:
+-      case DRM_MODE_ROTATE_0:
+-              mb->plane.transform = TRANSFORM_NO_ROTATE;
+-              break;
+-      case DRM_MODE_ROTATE_180:
+-              mb->plane.transform = TRANSFORM_ROTATE_180;
+-              break;
+-      case DRM_MODE_REFLECT_X:
+-              mb->plane.transform = TRANSFORM_FLIP_HRIZ;
+-              break;
+-      case DRM_MODE_REFLECT_Y:
+-              mb->plane.transform = TRANSFORM_FLIP_VERT;
+-              break;
+-      }
++      rotation = drm_rotation_simplify(state->rotation,
++                                       DRM_MODE_ROTATE_0 |
++                                       DRM_MODE_REFLECT_X |
++                                       DRM_MODE_REFLECT_Y);
++
++      mb->plane.transform = TRANSFORM_NO_ROTATE;
++      if (rotation & DRM_MODE_REFLECT_X)
++              mb->plane.transform |= TRANSFORM_FLIP_HRIZ;
++      if (rotation & DRM_MODE_REFLECT_Y)
++              mb->plane.transform |= TRANSFORM_FLIP_VERT;
+       vc4_fkms_margins_adj(state, &mb->plane);
+@@ -772,7 +760,10 @@ static struct drm_plane *vc4_fkms_plane_
+       drm_plane_create_alpha_property(plane);
+       drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
+-                                         SUPPORTED_ROTATIONS);
++                                         DRM_MODE_ROTATE_0 |
++                                         DRM_MODE_ROTATE_180 |
++                                         DRM_MODE_REFLECT_X |
++                                         DRM_MODE_REFLECT_Y);
+       drm_plane_create_color_properties(plane,
+                                         BIT(DRM_COLOR_YCBCR_BT601) |
+                                         BIT(DRM_COLOR_YCBCR_BT709) |
diff --git a/target/linux/brcm2708/patches-4.19/950-0733-drm-vc4-Fix-negative-X-Y-positioning-on-SAND-planes.patch b/target/linux/brcm2708/patches-4.19/950-0733-drm-vc4-Fix-negative-X-Y-positioning-on-SAND-planes.patch
deleted file mode 100644 (file)
index 8c8bb69..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-From a8af2085e26bcefad8fb65e2b44d12777a84e219 Mon Sep 17 00:00:00 2001
-From: Boris Brezillon <boris.brezillon@bootlin.com>
-Date: Fri, 7 Dec 2018 09:36:05 +0100
-Subject: [PATCH] drm/vc4: Fix negative X/Y positioning on SAND planes
-
-Commit 8e75d582db02bcb171d65ec71eecbd3072a5fd3a upstream.
-
-Commit 3e407417b192 ("drm/vc4: Fix X/Y positioning of planes using
-T_TILES modifier") fixed the problem with T_TILES format, but left
-things in a non-working state for SAND formats. Address that now.
-
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181207083606.15449-1-boris.brezillon@bootlin.com
----
- drivers/gpu/drm/vc4/vc4_plane.c | 21 +++++++++++++++++++++
- 1 file changed, 21 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -684,6 +684,7 @@ static int vc4_plane_mode_set(struct drm
-       case DRM_FORMAT_MOD_BROADCOM_SAND128:
-       case DRM_FORMAT_MOD_BROADCOM_SAND256: {
-               uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
-+              u32 tile_w, tile, x_off, pix_per_tile;
-               /* Column-based NV12 or RGBA.
-                */
-@@ -703,12 +704,15 @@ static int vc4_plane_mode_set(struct drm
-               switch (base_format_mod) {
-               case DRM_FORMAT_MOD_BROADCOM_SAND64:
-                       tiling = SCALER_CTL0_TILING_64B;
-+                      tile_w = 64;
-                       break;
-               case DRM_FORMAT_MOD_BROADCOM_SAND128:
-                       tiling = SCALER_CTL0_TILING_128B;
-+                      tile_w = 128;
-                       break;
-               case DRM_FORMAT_MOD_BROADCOM_SAND256:
-                       tiling = SCALER_CTL0_TILING_256B_OR_T;
-+                      tile_w = 256;
-                       break;
-               default:
-                       break;
-@@ -719,6 +723,23 @@ static int vc4_plane_mode_set(struct drm
-                       return -EINVAL;
-               }
-+              pix_per_tile = tile_w / fb->format->cpp[0];
-+              tile = vc4_state->src_x / pix_per_tile;
-+              x_off = vc4_state->src_x % pix_per_tile;
-+
-+              /* Adjust the base pointer to the first pixel to be scanned
-+               * out.
-+               */
-+              for (i = 0; i < num_planes; i++) {
-+                      vc4_state->offsets[i] += param * tile_w * tile;
-+                      vc4_state->offsets[i] += vc4_state->src_y /
-+                                               (i ? v_subsample : 1) *
-+                                               tile_w;
-+                      vc4_state->offsets[i] += x_off /
-+                                               (i ? h_subsample : 1) *
-+                                               fb->format->cpp[i];
-+              }
-+
-               pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
-               break;
-       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0734-drm-vc4-Add-support-for-H-V-flips.patch b/target/linux/brcm2708/patches-4.19/950-0734-drm-vc4-Add-support-for-H-V-flips.patch
deleted file mode 100644 (file)
index 4c9cb76..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-From 1246d16c393a2f5790e5492053f26e6b0b62cec8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 17 Sep 2019 18:36:32 +0100
-Subject: [PATCH] drm/vc4: Add support for H & V flips
-
-The HVS supports horizontal and vertical flips whilst composing.
-
-Expose these through the standard DRM rotation property.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_plane.c | 54 +++++++++++++++++++++++++++------
- 1 file changed, 45 insertions(+), 9 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_plane.c
-+++ b/drivers/gpu/drm/vc4/vc4_plane.c
-@@ -560,7 +560,9 @@ static int vc4_plane_mode_set(struct drm
-       const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
-       u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
-       int num_planes = drm_format_num_planes(format->drm);
-+      bool hflip = false, vflip = false;
-       u32 h_subsample, v_subsample;
-+      unsigned int rotation;
-       bool mix_plane_alpha;
-       bool covers_screen;
-       u32 scl0, scl1, pitch0;
-@@ -568,11 +570,26 @@ static int vc4_plane_mode_set(struct drm
-       unsigned long irqflags;
-       u32 hvs_format = format->hvs;
-       int ret, i;
-+      u32 src_y;
-       ret = vc4_plane_setup_clipping_and_scaling(state);
-       if (ret)
-               return ret;
-+      rotation = drm_rotation_simplify(state->rotation,
-+                                       DRM_MODE_ROTATE_0 |
-+                                       DRM_MODE_REFLECT_X |
-+                                       DRM_MODE_REFLECT_Y);
-+
-+      if ((rotation & DRM_MODE_ROTATE_MASK) == DRM_MODE_ROTATE_180) {
-+              hflip = true;
-+              vflip = true;
-+      }
-+      if (rotation & DRM_MODE_REFLECT_X)
-+              hflip ^= true;
-+      if (rotation & DRM_MODE_REFLECT_Y)
-+              vflip ^= true;
-+
-       /* Allocate the LBM memory that the HVS will use for temporary
-        * storage due to our scaling/format conversion.
-        */
-@@ -609,6 +626,16 @@ static int vc4_plane_mode_set(struct drm
-       h_subsample = drm_format_horz_chroma_subsampling(format->drm);
-       v_subsample = drm_format_vert_chroma_subsampling(format->drm);
-+      if (!vflip)
-+              src_y = vc4_state->src_y;
-+      else
-+              /* When vflipped the image offset needs to be
-+               * the start of the last line of the image, and
-+               * the pitch will be subtracted from the offset.
-+               */
-+              src_y = vc4_state->src_y +
-+                      vc4_state->src_h[0] - 1;
-+
-       switch (base_format_mod) {
-       case DRM_FORMAT_MOD_LINEAR:
-               tiling = SCALER_CTL0_TILING_LINEAR;
-@@ -618,12 +645,13 @@ static int vc4_plane_mode_set(struct drm
-                * out.
-                */
-               for (i = 0; i < num_planes; i++) {
--                      vc4_state->offsets[i] += vc4_state->src_y /
-+                      vc4_state->offsets[i] += src_y /
-                                                (i ? v_subsample : 1) *
-                                                fb->pitches[i];
-+
-                       vc4_state->offsets[i] += vc4_state->src_x /
--                                               (i ? h_subsample : 1) *
--                                               fb->format->cpp[i];
-+                                              (i ? h_subsample : 1) *
-+                                              fb->format->cpp[i];
-               }
-               break;
-@@ -651,11 +679,11 @@ static int vc4_plane_mode_set(struct drm
-                * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
-                * base address).
-                */
--              u32 tile_y = (vc4_state->src_y >> 4) & 1;
--              u32 subtile_y = (vc4_state->src_y >> 2) & 3;
--              u32 utile_y = vc4_state->src_y & 3;
-+              u32 tile_y = (src_y >> 4) & 1;
-+              u32 subtile_y = (src_y >> 2) & 3;
-+              u32 utile_y = src_y & 3;
-               u32 x_off = vc4_state->src_x & tile_w_mask;
--              u32 y_off = vc4_state->src_y & tile_h_mask;
-+              u32 y_off = src_y & tile_h_mask;
-               tiling = SCALER_CTL0_TILING_256B_OR_T;
-               pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
-@@ -732,7 +760,7 @@ static int vc4_plane_mode_set(struct drm
-                */
-               for (i = 0; i < num_planes; i++) {
-                       vc4_state->offsets[i] += param * tile_w * tile;
--                      vc4_state->offsets[i] += vc4_state->src_y /
-+                      vc4_state->offsets[i] += src_y /
-                                                (i ? v_subsample : 1) *
-                                                tile_w;
-                       vc4_state->offsets[i] += x_off /
-@@ -759,7 +787,9 @@ static int vc4_plane_mode_set(struct drm
-                       VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
-                       (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
-                       VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
--                      VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
-+                      VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1) |
-+                      (vflip ? SCALER_CTL0_VFLIP : 0) |
-+                      (hflip ? SCALER_CTL0_HFLIP : 0));
-       /* Position Word 0: Image Positions and Alpha Value */
-       vc4_state->pos0_offset = vc4_state->dlist_count;
-@@ -1203,5 +1233,11 @@ struct drm_plane *vc4_plane_init(struct
-                                         DRM_COLOR_YCBCR_BT709,
-                                         DRM_COLOR_YCBCR_LIMITED_RANGE);
-+      drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
-+                                         DRM_MODE_ROTATE_0 |
-+                                         DRM_MODE_ROTATE_180 |
-+                                         DRM_MODE_REFLECT_X |
-+                                         DRM_MODE_REFLECT_Y);
-+
-       return plane;
- }
diff --git a/target/linux/brcm2708/patches-4.19/950-0734-overlays-Add-w5500-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0734-overlays-Add-w5500-overlay.patch
new file mode 100644 (file)
index 0000000..2641a5b
--- /dev/null
@@ -0,0 +1,113 @@
+From cb9a896a799393b3cb5947bef3c95eb5ffb44776 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 10 Oct 2019 09:08:47 +0100
+Subject: [PATCH] overlays: Add w5500 overlay
+
+Add an overlay to configure the Wiznet W5500 Ethernet controller on
+SPI0. The 'cs' parameter chooses the Chip Select (default 0).
+
+See: https://github.com/raspberrypi/linux/issues/3276
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile          |  1 +
+ arch/arm/boot/dts/overlays/README            | 10 ++++
+ arch/arm/boot/dts/overlays/w5500-overlay.dts | 63 ++++++++++++++++++++
+ 3 files changed, 74 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/w5500-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -183,6 +183,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       vga666.dtbo \
+       w1-gpio.dtbo \
+       w1-gpio-pullup.dtbo \
++      w5500.dtbo \
+       wittypi.dtbo
+ targets += dtbs dtbs_install
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2538,6 +2538,16 @@ Params: gpiopin                 GPIO for
+         pullup                  Now enabled by default (ignored)
++Name:   w5500
++Info:   Overlay for the Wiznet W5500 Ethernet Controller on SPI0
++Load:   dtoverlay=w5500,<param>=<val>
++Params: int_pin                 GPIO used for INT (default 25)
++
++        speed                   SPI bus speed (default 30000000)
++
++        cs                      SPI bus Chip Select (default 0)
++
++
+ Name:   wittypi
+ Info:   Configures the wittypi RTC module.
+ Load:   dtoverlay=wittypi,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/w5500-overlay.dts
+@@ -0,0 +1,63 @@
++// Overlay for the Wiznet w5500 Ethernet Controller
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@1 {
++              target = <&spidev1>;
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@2 {
++              target = <&spi0>;
++              __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      eth1: w5500@0{
++                              compatible = "wiznet,w5500";
++                              reg = <0>; /* CE0 */
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&eth1_pins>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <25 0x8>;
++                              spi-max-frequency = <30000000>;
++//                            local-mac-address = [aa bb cc dd ee ff];
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&gpio>;
++              __overlay__ {
++                      eth1_pins: eth1_pins {
++                              brcm,pins = <25>;
++                              brcm,function = <0>; /* in */
++                              brcm,pull = <0>; /* none */
++                      };
++              };
++      };
++
++      __overrides__ {
++              int_pin = <&eth1>, "interrupts:0",
++                        <&eth1_pins>, "brcm,pins:0";
++              speed   = <&eth1>, "spi-max-frequency:0";
++              cs      = <&eth1>, "reg:0",
++                        <0>, "!0=1";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0735-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch b/target/linux/brcm2708/patches-4.19/950-0735-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch
deleted file mode 100644 (file)
index d08b7f0..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-From e99a60f018524bf7b1ba382e3994c22ebcdbafe6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 18 Sep 2019 15:49:13 +0100
-Subject: [PATCH] drm/vc4: Correct handling of rotation parameter in
- fkms
-
-One bit within DRM_MODE_ROTATE_MASK will always be set to
-determine the base rotation 0/90/180/270, and then REFLECT_X
-and REFLECT_Y are on top.
-
-Correct the handling which was assuming that REFLECT_[X|Y]
-was instead of ROTATE_x.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 37 ++++++++++----------------
- 1 file changed, 14 insertions(+), 23 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -79,11 +79,6 @@ struct set_plane {
- #define TRANSFORM_FLIP_HRIZ   BIT(16)
- #define TRANSFORM_FLIP_VERT   BIT(17)
--#define SUPPORTED_ROTATIONS   (DRM_MODE_ROTATE_0 | \
--                               DRM_MODE_ROTATE_180 | \
--                               DRM_MODE_REFLECT_X | \
--                               DRM_MODE_REFLECT_Y)
--
- struct mailbox_set_plane {
-       struct rpi_firmware_property_tag_header tag;
-       struct set_plane plane;
-@@ -523,7 +518,7 @@ static int vc4_plane_to_mb(struct drm_pl
-       const struct vc_image_format *vc_fmt =
-                                       vc4_get_vc_image_fmt(drm_fmt->format);
-       int num_planes = fb->format->num_planes;
--      unsigned int rotation = SUPPORTED_ROTATIONS;
-+      unsigned int rotation;
-       mb->plane.vc_image_type = vc_fmt->vc_image;
-       mb->plane.width = fb->width;
-@@ -544,23 +539,16 @@ static int vc4_plane_to_mb(struct drm_pl
-       mb->plane.is_vu = vc_fmt->is_vu;
-       mb->plane.planes[0] = bo->paddr + fb->offsets[0];
--      rotation = drm_rotation_simplify(state->rotation, rotation);
--
--      switch (rotation) {
--      default:
--      case DRM_MODE_ROTATE_0:
--              mb->plane.transform = TRANSFORM_NO_ROTATE;
--              break;
--      case DRM_MODE_ROTATE_180:
--              mb->plane.transform = TRANSFORM_ROTATE_180;
--              break;
--      case DRM_MODE_REFLECT_X:
--              mb->plane.transform = TRANSFORM_FLIP_HRIZ;
--              break;
--      case DRM_MODE_REFLECT_Y:
--              mb->plane.transform = TRANSFORM_FLIP_VERT;
--              break;
--      }
-+      rotation = drm_rotation_simplify(state->rotation,
-+                                       DRM_MODE_ROTATE_0 |
-+                                       DRM_MODE_REFLECT_X |
-+                                       DRM_MODE_REFLECT_Y);
-+
-+      mb->plane.transform = TRANSFORM_NO_ROTATE;
-+      if (rotation & DRM_MODE_REFLECT_X)
-+              mb->plane.transform |= TRANSFORM_FLIP_HRIZ;
-+      if (rotation & DRM_MODE_REFLECT_Y)
-+              mb->plane.transform |= TRANSFORM_FLIP_VERT;
-       vc4_fkms_margins_adj(state, &mb->plane);
-@@ -772,7 +760,10 @@ static struct drm_plane *vc4_fkms_plane_
-       drm_plane_create_alpha_property(plane);
-       drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
--                                         SUPPORTED_ROTATIONS);
-+                                         DRM_MODE_ROTATE_0 |
-+                                         DRM_MODE_ROTATE_180 |
-+                                         DRM_MODE_REFLECT_X |
-+                                         DRM_MODE_REFLECT_Y);
-       drm_plane_create_color_properties(plane,
-                                         BIT(DRM_COLOR_YCBCR_BT601) |
-                                         BIT(DRM_COLOR_YCBCR_BT709) |
diff --git a/target/linux/brcm2708/patches-4.19/950-0735-media-bcm2835-unicam-Replace-hard-coded-loop-limit-w.patch b/target/linux/brcm2708/patches-4.19/950-0735-media-bcm2835-unicam-Replace-hard-coded-loop-limit-w.patch
new file mode 100644 (file)
index 0000000..cb9a82b
--- /dev/null
@@ -0,0 +1,44 @@
+From 1a013467030ffd6f1958b8a4db1b5312213fb9bd Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 17 Oct 2019 10:16:16 +0100
+Subject: [PATCH] media: bcm2835-unicam: Replace hard coded loop limit
+ with a define
+
+In order to protect against a dodgy sensor driver never returning
+an error from enum_mbus_code there was a hardcoded value of 128
+that aborted the loop.
+There is a need to call enum_mbus_code from elsewhere, so move that
+number to a define so it is common across calls.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -97,6 +97,11 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
+ #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 16.
+  */
+@@ -738,11 +743,7 @@ static int unicam_enum_fmt_vid_cap(struc
+       int ret = 0;
+       int i;
+-      /* Loop whilst the sensor driver says it has more formats, but add a
+-       * failsafe against a dodgy driver at 128 (more than any sensor will
+-       * ever sensibly advertise)
+-       */
+-      for (i = 0; !ret && i < 128 ; i++) {
++      for (i = 0; !ret && i < MAX_ENUM_MBUS_CODE; i++) {
+               memset(&mbus_code, 0, sizeof(mbus_code));
+               mbus_code.index = i;
diff --git a/target/linux/brcm2708/patches-4.19/950-0736-media-bcm2835-unicam-Fix-one-to-many-mapping-for-YUY.patch b/target/linux/brcm2708/patches-4.19/950-0736-media-bcm2835-unicam-Fix-one-to-many-mapping-for-YUY.patch
new file mode 100644 (file)
index 0000000..3c881a1
--- /dev/null
@@ -0,0 +1,144 @@
+From 94d77466473f3abcf799ac44b8038766ab32f27c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 16 Oct 2019 18:53:06 +0100
+Subject: [PATCH] media: bcm2835-unicam: Fix one-to-many mapping for
+ YUYV formats
+
+V4L2 format V4L2_PIX_FMT_YUYV maps to both MEDIA_BUS_FMT_YUYV8_2X8
+and MEDIA_BUS_FMT_YUYV8_1X16. The change to not cache the active
+formats also meant that we only ever found the first variant of
+the mediabus format when trying to setup the device.
+
+Flag the formats that have other representations, and ensure
+that the format conversion checks whether the found format
+matches one supported by the sensor before returning it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 45 ++++++++++++++++---
+ 1 file changed, 39 insertions(+), 6 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -136,6 +136,8 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
+  * @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;
+@@ -143,6 +145,7 @@ struct unicam_fmt {
+       u32     code;
+       u8      depth;
+       u8      csi_dt;
++      u8      check_variants;
+ };
+ static const struct unicam_fmt formats[] = {
+@@ -152,21 +155,25 @@ static const struct unicam_fmt formats[]
+               .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,
+@@ -489,14 +496,40 @@ static const struct unicam_fmt *find_for
+       return NULL;
+ }
+-static const struct unicam_fmt *find_format_by_pix(u32 pixelformat)
++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;
++
++              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 k;
+       for (k = 0; k < ARRAY_SIZE(formats); k++) {
+               if (formats[k].fourcc == pixelformat ||
+-                  formats[k].repacked_fourcc == pixelformat)
++                  formats[k].repacked_fourcc == pixelformat) {
++                      if (formats[k].check_variants &&
++                          !check_mbus_format(dev, &formats[k]))
++                              continue;
+                       return &formats[k];
++              }
+       }
+       return NULL;
+@@ -832,7 +865,7 @@ static int unicam_try_fmt_vid_cap(struct
+       struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
+       int ret;
+-      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
++      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.
+@@ -917,7 +950,7 @@ static int unicam_s_fmt_vid_cap(struct f
+       if (ret < 0)
+               return ret;
+-      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
++      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
+@@ -1540,7 +1573,7 @@ static int unicam_enum_framesizes(struct
+       int ret;
+       /* check for valid format */
+-      fmt = find_format_by_pix(fsize->pixel_format);
++      fmt = find_format_by_pix(dev, fsize->pixel_format);
+       if (!fmt) {
+               unicam_dbg(3, dev, "Invalid pixel code: %x\n",
+                          fsize->pixel_format);
+@@ -1579,7 +1612,7 @@ static int unicam_enum_frameintervals(st
+       };
+       int ret;
+-      fmt = find_format_by_pix(fival->pixel_format);
++      fmt = find_format_by_pix(dev, fival->pixel_format);
+       if (!fmt)
+               return -EINVAL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0736-overlays-Add-w5500-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0736-overlays-Add-w5500-overlay.patch
deleted file mode 100644 (file)
index 2641a5b..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-From cb9a896a799393b3cb5947bef3c95eb5ffb44776 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 10 Oct 2019 09:08:47 +0100
-Subject: [PATCH] overlays: Add w5500 overlay
-
-Add an overlay to configure the Wiznet W5500 Ethernet controller on
-SPI0. The 'cs' parameter chooses the Chip Select (default 0).
-
-See: https://github.com/raspberrypi/linux/issues/3276
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile          |  1 +
- arch/arm/boot/dts/overlays/README            | 10 ++++
- arch/arm/boot/dts/overlays/w5500-overlay.dts | 63 ++++++++++++++++++++
- 3 files changed, 74 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/w5500-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -183,6 +183,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       vga666.dtbo \
-       w1-gpio.dtbo \
-       w1-gpio-pullup.dtbo \
-+      w5500.dtbo \
-       wittypi.dtbo
- targets += dtbs dtbs_install
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2538,6 +2538,16 @@ Params: gpiopin                 GPIO for
-         pullup                  Now enabled by default (ignored)
-+Name:   w5500
-+Info:   Overlay for the Wiznet W5500 Ethernet Controller on SPI0
-+Load:   dtoverlay=w5500,<param>=<val>
-+Params: int_pin                 GPIO used for INT (default 25)
-+
-+        speed                   SPI bus speed (default 30000000)
-+
-+        cs                      SPI bus Chip Select (default 0)
-+
-+
- Name:   wittypi
- Info:   Configures the wittypi RTC module.
- Load:   dtoverlay=wittypi,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/w5500-overlay.dts
-@@ -0,0 +1,63 @@
-+// Overlay for the Wiznet w5500 Ethernet Controller
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&spidev0>;
-+              __overlay__ {
-+                      status = "disabled";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&spidev1>;
-+              __dormant__ {
-+                      status = "disabled";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&spi0>;
-+              __overlay__ {
-+                      /* needed to avoid dtc warning */
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      eth1: w5500@0{
-+                              compatible = "wiznet,w5500";
-+                              reg = <0>; /* CE0 */
-+                              pinctrl-names = "default";
-+                              pinctrl-0 = <&eth1_pins>;
-+                              interrupt-parent = <&gpio>;
-+                              interrupts = <25 0x8>;
-+                              spi-max-frequency = <30000000>;
-+//                            local-mac-address = [aa bb cc dd ee ff];
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&gpio>;
-+              __overlay__ {
-+                      eth1_pins: eth1_pins {
-+                              brcm,pins = <25>;
-+                              brcm,function = <0>; /* in */
-+                              brcm,pull = <0>; /* none */
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              int_pin = <&eth1>, "interrupts:0",
-+                        <&eth1_pins>, "brcm,pins:0";
-+              speed   = <&eth1>, "spi-max-frequency:0";
-+              cs      = <&eth1>, "reg:0",
-+                        <0>, "!0=1";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0737-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch b/target/linux/brcm2708/patches-4.19/950-0737-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch
new file mode 100644 (file)
index 0000000..4291f9f
--- /dev/null
@@ -0,0 +1,66 @@
+From b4f8b92cdfd8ad2e04cdd3f0a73aa4e95d172fb1 Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Thu, 10 Oct 2019 19:12:08 +0200
+Subject: [PATCH] dt-bindings: Add binding for the Infineon IRS1125
+ sensor
+
+Adds a binding for the Infineon IRS1125 time-of-flight depth
+sensor.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ .../devicetree/bindings/media/i2c/irs1125.txt | 48 +++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/media/i2c/irs1125.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/media/i2c/irs1125.txt
+@@ -0,0 +1,48 @@
++* Infineon irs1125 time of flight sensor
++
++The Infineon irs1125 is a time of flight digital image sensor with
++an active array size of 352H x 286V. It is programmable through I2C
++interface. The I2C address defaults to 0x3D, but can be reconfigured
++to address 0x3C or 0x41 via I2C commands. Image data is sent through
++MIPI CSI-2, which is configured as either 1 or 2 data lanes.
++
++Required Properties:
++- compatible: value should be "infineon,irs1125" for irs1125 sensor
++- reg: I2C bus address of the device
++- clocks: reference to the xclk input clock.
++- pwdn-gpios: reference to the GPIO connected to the reset pin.
++            This is an active low signal to the iirs1125.
++
++The irs1125 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.
++
++Endpoint node required properties for CSI-2 connection are:
++- remote-endpoint: a phandle to the bus receiver's endpoint node.
++- clock-lanes: should be set to <0> (clock lane on hardware lane 0)
++- data-lanes: should be set to <1> or <1 2> (one or two lane CSI-2
++  supported)
++
++Example:
++      sensor@10 {
++              compatible = "infineon,irs1125";
++              reg = <0x3D>;
++              #address-cells = <1>;
++              #size-cells = <0>;
++              clocks = <&irs1125_clk>;
++              pwdn-gpios = <&gpio 5 0>;
++
++              irs1125_clk: camera-clk {
++                      compatible = "fixed-clock";
++                      #clock-cells = <0>;
++                      clock-frequency = <26000000>;
++              };
++
++              port {
++                      sensor_out: endpoint {
++                              remote-endpoint = <&csiss_in>;
++                              clock-lanes = <0>;
++                              data-lanes = <1 2>;
++                      };
++              };
++      };
diff --git a/target/linux/brcm2708/patches-4.19/950-0737-media-bcm2835-unicam-Replace-hard-coded-loop-limit-w.patch b/target/linux/brcm2708/patches-4.19/950-0737-media-bcm2835-unicam-Replace-hard-coded-loop-limit-w.patch
deleted file mode 100644 (file)
index cb9a82b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 1a013467030ffd6f1958b8a4db1b5312213fb9bd Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 17 Oct 2019 10:16:16 +0100
-Subject: [PATCH] media: bcm2835-unicam: Replace hard coded loop limit
- with a define
-
-In order to protect against a dodgy sensor driver never returning
-an error from enum_mbus_code there was a hardcoded value of 128
-that aborted the loop.
-There is a need to call enum_mbus_code from elsewhere, so move that
-number to a define so it is common across calls.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/media/platform/bcm2835/bcm2835-unicam.c | 11 ++++++-----
- 1 file changed, 6 insertions(+), 5 deletions(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -97,6 +97,11 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
- #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 16.
-  */
-@@ -738,11 +743,7 @@ static int unicam_enum_fmt_vid_cap(struc
-       int ret = 0;
-       int i;
--      /* Loop whilst the sensor driver says it has more formats, but add a
--       * failsafe against a dodgy driver at 128 (more than any sensor will
--       * ever sensibly advertise)
--       */
--      for (i = 0; !ret && i < 128 ; i++) {
-+      for (i = 0; !ret && i < MAX_ENUM_MBUS_CODE; i++) {
-               memset(&mbus_code, 0, sizeof(mbus_code));
-               mbus_code.index = i;
diff --git a/target/linux/brcm2708/patches-4.19/950-0738-media-bcm2835-unicam-Fix-one-to-many-mapping-for-YUY.patch b/target/linux/brcm2708/patches-4.19/950-0738-media-bcm2835-unicam-Fix-one-to-many-mapping-for-YUY.patch
deleted file mode 100644 (file)
index 3c881a1..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-From 94d77466473f3abcf799ac44b8038766ab32f27c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 16 Oct 2019 18:53:06 +0100
-Subject: [PATCH] media: bcm2835-unicam: Fix one-to-many mapping for
- YUYV formats
-
-V4L2 format V4L2_PIX_FMT_YUYV maps to both MEDIA_BUS_FMT_YUYV8_2X8
-and MEDIA_BUS_FMT_YUYV8_1X16. The change to not cache the active
-formats also meant that we only ever found the first variant of
-the mediabus format when trying to setup the device.
-
-Flag the formats that have other representations, and ensure
-that the format conversion checks whether the found format
-matches one supported by the sensor before returning it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c   | 45 ++++++++++++++++---
- 1 file changed, 39 insertions(+), 6 deletions(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -136,6 +136,8 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
-  * @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;
-@@ -143,6 +145,7 @@ struct unicam_fmt {
-       u32     code;
-       u8      depth;
-       u8      csi_dt;
-+      u8      check_variants;
- };
- static const struct unicam_fmt formats[] = {
-@@ -152,21 +155,25 @@ static const struct unicam_fmt formats[]
-               .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,
-@@ -489,14 +496,40 @@ static const struct unicam_fmt *find_for
-       return NULL;
- }
--static const struct unicam_fmt *find_format_by_pix(u32 pixelformat)
-+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;
-+
-+              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 k;
-       for (k = 0; k < ARRAY_SIZE(formats); k++) {
-               if (formats[k].fourcc == pixelformat ||
--                  formats[k].repacked_fourcc == pixelformat)
-+                  formats[k].repacked_fourcc == pixelformat) {
-+                      if (formats[k].check_variants &&
-+                          !check_mbus_format(dev, &formats[k]))
-+                              continue;
-                       return &formats[k];
-+              }
-       }
-       return NULL;
-@@ -832,7 +865,7 @@ static int unicam_try_fmt_vid_cap(struct
-       struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
-       int ret;
--      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
-+      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.
-@@ -917,7 +950,7 @@ static int unicam_s_fmt_vid_cap(struct f
-       if (ret < 0)
-               return ret;
--      fmt = find_format_by_pix(f->fmt.pix.pixelformat);
-+      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
-@@ -1540,7 +1573,7 @@ static int unicam_enum_framesizes(struct
-       int ret;
-       /* check for valid format */
--      fmt = find_format_by_pix(fsize->pixel_format);
-+      fmt = find_format_by_pix(dev, fsize->pixel_format);
-       if (!fmt) {
-               unicam_dbg(3, dev, "Invalid pixel code: %x\n",
-                          fsize->pixel_format);
-@@ -1579,7 +1612,7 @@ static int unicam_enum_frameintervals(st
-       };
-       int ret;
--      fmt = find_format_by_pix(fival->pixel_format);
-+      fmt = find_format_by_pix(dev, fival->pixel_format);
-       if (!fmt)
-               return -EINVAL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0738-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch b/target/linux/brcm2708/patches-4.19/950-0738-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch
new file mode 100644 (file)
index 0000000..9b882fc
--- /dev/null
@@ -0,0 +1,1231 @@
+From c09b42cb057ddf8bd20d57c6b0ffd94f3e15ea7c Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Thu, 10 Oct 2019 19:12:36 +0200
+Subject: [PATCH] media: i2c: Add a driver for the Infineon IRS1125
+ depth sensor
+
+The Infineon IRS1125 is a time of flight depth sensor that
+has a CSI-2 interface.
+
+Add a V4L2 subdevice driver for this device.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ drivers/media/i2c/Kconfig   |   12 +
+ drivers/media/i2c/Makefile  |    1 +
+ drivers/media/i2c/irs1125.c | 1112 +++++++++++++++++++++++++++++++++++
+ drivers/media/i2c/irs1125.h |   61 ++
+ 4 files changed, 1186 insertions(+)
+ create mode 100644 drivers/media/i2c/irs1125.c
+ create mode 100644 drivers/media/i2c/irs1125.h
+
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -813,6 +813,18 @@ config VIDEO_OV13858
+         This is a Video4Linux2 sensor driver for the OmniVision
+         OV13858 camera.
++config VIDEO_IRS1125
++      tristate "Infineon IRS1125 sensor support"
++      depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
++      depends on MEDIA_CAMERA_SUPPORT
++      select V4L2_FWNODE
++      help
++        This is a Video4Linux2 sensor-level driver for the Infineon
++        IRS1125 camera.
++
++        To compile this driver as a module, choose M here: the
++        module will be called irs1125.
++
+ config VIDEO_VS6624
+       tristate "ST VS6624 sensor support"
+       depends on VIDEO_V4L2 && I2C
+--- a/drivers/media/i2c/Makefile
++++ b/drivers/media/i2c/Makefile
+@@ -80,6 +80,7 @@ obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
+ obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
+ obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
+ obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
++obj-$(CONFIG_VIDEO_IRS1125) += irs1125.o
+ obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
+ obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o
+ obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
+--- /dev/null
++++ b/drivers/media/i2c/irs1125.c
+@@ -0,0 +1,1112 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * A V4L2 driver for Infineon IRS1125 TOF cameras.
++ * Copyright (C) 2018, pieye GmbH
++ *
++ * Based on V4L2 OmniVision OV5647 Image Sensor driver
++ * Copyright (C) 2016 Ramiro Oliveira <roliveir@synopsys.com>
++ *
++ * DT / fwnode changes, and GPIO control taken from ov5640.c
++ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
++ * Copyright (C) 2014-2017 Mentor Graphics Inc.
++ *
++ */
++
++#include "irs1125.h"
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/gpio/consumer.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_graph.h>
++#include <linux/slab.h>
++#include <linux/videodev2.h>
++#include <linux/firmware.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))
++
++#define SENSOR_NAME "irs1125"
++
++#define RESET_ACTIVE_DELAY_MS  20
++
++#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_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_WIDTH_DEF      352
++
++struct regval_list {
++      u16 addr;
++      u16 data;
++};
++
++struct irs1125 {
++      struct v4l2_subdev sd;
++      struct media_pad pad;
++      /* the parsed DT endpoint info */
++      struct v4l2_fwnode_endpoint ep;
++
++      struct clk *xclk;
++      struct v4l2_ctrl_handler ctrl_handler;
++
++      /* To serialize asynchronus callbacks */
++      struct mutex lock;
++
++      /* image data layout */
++      unsigned int num_seq;
++
++      /* reset pin */
++      struct gpio_desc *reset;
++
++      /* V4l2 Controls to grab */
++      struct v4l2_ctrl *ctrl_modplls;
++      struct v4l2_ctrl *ctrl_numseq;
++
++      int power_count;
++};
++
++static inline struct irs1125 *to_state(struct v4l2_subdev *sd)
++{
++      return container_of(sd, struct irs1125, sd);
++}
++
++static struct regval_list irs1125_26MHz[] = {
++      {0xB017, 0x0413},
++      {0xB086, 0x3535},
++      {0xB0AE, 0xEF02},
++      {0xA000, 0x0004},
++      {0xFFFF, 100},
++
++      {0xB062, 0x6383},
++      {0xB063, 0x55A8},
++      {0xB068, 0x7628},
++      {0xB069, 0x03E2},
++
++      {0xFFFF, 100},
++      {0xB05A, 0x01C5},
++      {0xB05C, 0x0206},
++      {0xB05D, 0x01C5},
++      {0xB05F, 0x0206},
++      {0xB016, 0x1335},
++      {0xFFFF, 100},
++      {0xA893, 0x8261},
++      {0xA894, 0x89d8},
++      {0xA895, 0x131d},
++      {0xA896, 0x4251},
++      {0xA897, 0x9D8A},
++      {0xA898, 0x0BD8},
++      {0xA899, 0x2245},
++      {0xA89A, 0xAB9B},
++      {0xA89B, 0x03B9},
++      {0xA89C, 0x8041},
++      {0xA89D, 0xE07E},
++      {0xA89E, 0x0307},
++      {0xFFFF, 100},
++      {0xA88D, 0x0004},
++      {0xA800, 0x0E68},
++      {0xA801, 0x0000},
++      {0xA802, 0x000C},
++      {0xA803, 0x0000},
++      {0xA804, 0x0E68},
++      {0xA805, 0x0000},
++      {0xA806, 0x0440},
++      {0xA807, 0x0000},
++      {0xA808, 0x0E68},
++      {0xA809, 0x0000},
++      {0xA80A, 0x0884},
++      {0xA80B, 0x0000},
++      {0xA80C, 0x0E68},
++      {0xA80D, 0x0000},
++      {0xA80E, 0x0CC8},
++      {0xA80F, 0x0000},
++      {0xA810, 0x0E68},
++      {0xA811, 0x0000},
++      {0xA812, 0x2000},
++      {0xA813, 0x0000},
++      {0xA882, 0x0081},
++      {0xA88C, 0x403A},
++      {0xA88F, 0x031E},
++      {0xA892, 0x0351},
++      {0x9813, 0x13FF},
++      {0x981B, 0x7608},
++
++      {0xB008, 0x0000},
++      {0xB015, 0x1513},
++
++      {0xFFFF, 100}
++};
++
++static struct regval_list irs1125_seq_cfg[] = {
++      {0xC3A0, 0x823D},
++      {0xC3A1, 0xB13B},
++      {0xC3A2, 0x0313},
++      {0xC3A3, 0x4659},
++      {0xC3A4, 0xC4EC},
++      {0xC3A5, 0x03CE},
++      {0xC3A6, 0x4259},
++      {0xC3A7, 0xC4EC},
++      {0xC3A8, 0x03CE},
++      {0xC3A9, 0x8839},
++      {0xC3AA, 0x89D8},
++      {0xC3AB, 0x031D},
++
++      {0xC24C, 0x5529},
++      {0xC24D, 0x0000},
++      {0xC24E, 0x1200},
++      {0xC24F, 0x6CB2},
++      {0xC250, 0x0000},
++      {0xC251, 0x5529},
++      {0xC252, 0x42F4},
++      {0xC253, 0xD1AF},
++      {0xC254, 0x8A18},
++      {0xC255, 0x0002},
++      {0xC256, 0x5529},
++      {0xC257, 0x6276},
++      {0xC258, 0x11A7},
++      {0xC259, 0xD907},
++      {0xC25A, 0x0000},
++      {0xC25B, 0x5529},
++      {0xC25C, 0x07E0},
++      {0xC25D, 0x7BFE},
++      {0xC25E, 0x6402},
++      {0xC25F, 0x0019},
++
++      {0xC3AC, 0x0007},
++      {0xC3AD, 0xED88},
++      {0xC320, 0x003E},
++      {0xC321, 0x0000},
++      {0xC322, 0x2000},
++      {0xC323, 0x0000},
++      {0xC324, 0x0271},
++      {0xC325, 0x0000},
++      {0xC326, 0x000C},
++      {0xC327, 0x0000},
++      {0xC328, 0x0271},
++      {0xC329, 0x0000},
++      {0xC32A, 0x0440},
++      {0xC32B, 0x0000},
++      {0xC32C, 0x0271},
++      {0xC32D, 0x0000},
++      {0xC32E, 0x0884},
++      {0xC32F, 0x0000},
++      {0xC330, 0x0271},
++      {0xC331, 0x0000},
++      {0xC332, 0x0CC8},
++      {0xC333, 0x0000},
++      {0xA88D, 0x0004},
++
++      {0xA890, 0x0000},
++      {0xC219, 0x0002},
++      {0xC21A, 0x0000},
++      {0xC21B, 0x0000},
++      {0xC21C, 0x00CD},
++      {0xC21D, 0x0009},
++      {0xC21E, 0x00CD},
++      {0xC21F, 0x0009},
++
++      {0xA87C, 0x0000},
++      {0xC032, 0x0001},
++      {0xC034, 0x0000},
++      {0xC035, 0x0001},
++      {0xC039, 0x0000},
++      {0xC401, 0x0002},
++
++      {0xFFFF, 1},
++      {0xA87C, 0x0001}
++};
++
++static int irs1125_write(struct v4l2_subdev *sd, u16 reg, u16 val)
++{
++      int ret;
++      unsigned char data[4] = { reg >> 8, reg & 0xff, val >> 8, val & 0xff};
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++
++      ret = i2c_master_send(client, data, 4);
++      if (ret < 0)
++              dev_err(&client->dev, "%s: i2c write error, reg: %x\n",
++                      __func__, reg);
++
++      return ret;
++}
++
++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);
++
++      ret = i2c_master_send(client, data_w, 2);
++      if (ret < 0) {
++              dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
++                      __func__, reg);
++              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);
++
++      return ret;
++}
++
++static int irs1125_write_array(struct v4l2_subdev *sd,
++                             struct regval_list *regs, int array_size)
++{
++      int i, ret;
++
++      for (i = 0; i < array_size; i++) {
++              if (regs[i].addr == 0xFFFF) {
++                      msleep(regs[i].data);
++              } else {
++                      ret = irs1125_write(sd, regs[i].addr, regs[i].data);
++                      if (ret < 0)
++                              return ret;
++              }
++      }
++
++      return 0;
++}
++
++static int irs1125_stream_on(struct v4l2_subdev *sd)
++{
++      int ret;
++      struct irs1125 *irs1125 = to_state(sd);
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++
++      v4l2_ctrl_grab(irs1125->ctrl_numseq, 1);
++      v4l2_ctrl_grab(irs1125->ctrl_modplls, 1);
++
++      ret = irs1125_write(sd, 0xC400, 0x0001);
++      if (ret < 0) {
++              dev_err(&client->dev, "error enabling firmware: %d", ret);
++              return ret;
++      }
++
++      msleep(100);
++
++      return irs1125_write(sd, 0xA87C, 0x0001);
++}
++
++static int irs1125_stream_off(struct v4l2_subdev *sd)
++{
++      int ret;
++      struct irs1125 *irs1125 = to_state(sd);
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++
++      v4l2_ctrl_grab(irs1125->ctrl_numseq, 0);
++      v4l2_ctrl_grab(irs1125->ctrl_modplls, 0);
++
++      ret = irs1125_write(sd, 0xA87C, 0x0000);
++      if (ret < 0) {
++              dev_err(&client->dev, "error disabling trigger: %d", ret);
++              return ret;
++      }
++
++      msleep(100);
++
++      return irs1125_write(sd, 0xC400, 0x0002);
++}
++
++static int __sensor_init(struct v4l2_subdev *sd)
++{
++      unsigned int cnt, idx;
++      int ret;
++      u16 val;
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++      struct irs1125 *irs1125 = to_state(sd);
++      const struct firmware *fw;
++      struct regval_list *reg_data;
++
++      cnt = 0;
++      while (1) {
++              ret = irs1125_read(sd, 0xC40F, &val);
++              if (ret < 0) {
++                      dev_err(&client->dev, "read register 0xC40F failed\n");
++                      return ret;
++              }
++              if (CHECK_BIT(val, 14) == 0)
++                      break;
++
++              if (cnt >= 5) {
++                      dev_err(&client->dev, "timeout waiting for 0xC40F\n");
++                      return -EAGAIN;
++              }
++
++              cnt++;
++      }
++
++      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;
++      }
++
++      /* set CSI-2 number of data lanes */
++      if (irs1125->ep.bus.mipi_csi2.num_data_lanes == 1) {
++              val = 0x0001;
++      } else if (irs1125->ep.bus.mipi_csi2.num_data_lanes == 2) {
++              val = 0x0081;
++      } else {
++              dev_err(&client->dev, "invalid number of data lanes %d\n",
++                      irs1125->ep.bus.mipi_csi2.num_data_lanes);
++              return -EINVAL;
++      }
++
++      ret = irs1125_write(sd, IRS1125_REG_CSICFG, val);
++      if (ret < 0) {
++              dev_err(&client->dev, "write sensor csi2 config error\n");
++              return ret;
++      }
++
++      /* request the firmware, this will block and timeout */
++      ret = request_firmware(&fw, IRS1125_ALTERNATE_FW, &client->dev);
++      if (ret) {
++              dev_err(&client->dev,
++                      "did not find the firmware file '%s' (status %d)\n",
++                      IRS1125_ALTERNATE_FW, ret);
++              return ret;
++      }
++
++      if (fw->size % 4) {
++              dev_err(&client->dev, "firmware file '%s' invalid\n",
++                      IRS1125_ALTERNATE_FW);
++              release_firmware(fw);
++              return -EINVAL;
++      }
++
++      for (idx = 0; idx < fw->size; idx += 4) {
++              reg_data = (struct regval_list *)&fw->data[idx];
++              ret = irs1125_write(sd, reg_data->addr, reg_data->data);
++              if (ret < 0) {
++                      dev_err(&client->dev, "firmware write error\n");
++                      release_firmware(fw);
++                      return ret;
++              }
++      }
++      release_firmware(fw);
++
++      ret = irs1125_write_array(sd, irs1125_seq_cfg,
++                                ARRAY_SIZE(irs1125_seq_cfg));
++      if (ret < 0) {
++              dev_err(&client->dev, "write default sequence failed\n");
++              return ret;
++      }
++
++      return 0;
++}
++
++static int irs1125_sensor_power(struct v4l2_subdev *sd, int on)
++{
++      int ret = 0;
++      struct irs1125 *irs1125 = to_state(sd);
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++
++      mutex_lock(&irs1125->lock);
++
++      if (on && !irs1125->power_count) {
++              gpiod_set_value_cansleep(irs1125->reset, 1);
++              msleep(RESET_ACTIVE_DELAY_MS);
++
++              ret = clk_prepare_enable(irs1125->xclk);
++              if (ret < 0) {
++                      dev_err(&client->dev, "clk prepare enable failed\n");
++                      goto out;
++              }
++
++              ret = __sensor_init(sd);
++              if (ret < 0) {
++                      clk_disable_unprepare(irs1125->xclk);
++                      dev_err(&client->dev,
++                              "Camera not available, check Power\n");
++                      goto out;
++              }
++      } else if (!on && irs1125->power_count == 1) {
++              gpiod_set_value_cansleep(irs1125->reset, 0);
++      }
++
++      /* Update the power count. */
++      irs1125->power_count += on ? 1 : -1;
++      WARN_ON(irs1125->power_count < 0);
++
++out:
++      mutex_unlock(&irs1125->lock);
++
++      return ret;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int irs1125_sensor_get_register(struct v4l2_subdev *sd,
++                                     struct v4l2_dbg_register *reg)
++{
++      u16 val;
++      int ret;
++
++      ret = irs1125_read(sd, reg->reg & 0xffff, &val);
++      if (ret < 0)
++              return ret;
++
++      reg->val = val;
++      reg->size = 1;
++
++      return 0;
++}
++
++static int irs1125_sensor_set_register(struct v4l2_subdev *sd,
++                                     const struct v4l2_dbg_register *reg)
++{
++      return irs1125_write(sd, reg->reg & 0xffff, reg->val & 0xffff);
++}
++#endif
++
++static const struct v4l2_subdev_core_ops irs1125_subdev_core_ops = {
++      .s_power = irs1125_sensor_power,
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++      .g_register = irs1125_sensor_get_register,
++      .s_register = irs1125_sensor_set_register,
++#endif
++};
++
++static int irs1125_s_stream(struct v4l2_subdev *sd, int enable)
++{
++      if (enable)
++              return irs1125_stream_on(sd);
++      else
++              return irs1125_stream_off(sd);
++}
++
++static const struct v4l2_subdev_video_ops irs1125_subdev_video_ops = {
++      .s_stream = irs1125_s_stream,
++};
++
++static int irs1125_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_Y12_1X12;
++
++      return 0;
++}
++
++static int irs1125_set_get_fmt(struct v4l2_subdev *sd,
++                             struct v4l2_subdev_pad_config *cfg,
++                             struct v4l2_subdev_format *format)
++{
++      struct v4l2_mbus_framefmt *fmt = &format->format;
++      struct irs1125 *irs1125 = to_state(sd);
++
++      if (format->pad != 0)
++              return -EINVAL;
++
++      /* Only one format is supported, so return that */
++      memset(fmt, 0, sizeof(*fmt));
++      fmt->code = MEDIA_BUS_FMT_Y12_1X12;
++      fmt->colorspace = V4L2_COLORSPACE_RAW;
++      fmt->field = V4L2_FIELD_NONE;
++      fmt->width = IRS1125_WINDOW_WIDTH_DEF;
++      fmt->height = IRS1125_WINDOW_HEIGHT_DEF * irs1125->num_seq;
++
++      return 0;
++}
++
++static const struct v4l2_subdev_pad_ops irs1125_subdev_pad_ops = {
++      .enum_mbus_code = irs1125_enum_mbus_code,
++      .set_fmt = irs1125_set_get_fmt,
++      .get_fmt = irs1125_set_get_fmt,
++};
++
++static const struct v4l2_subdev_ops irs1125_subdev_ops = {
++      .core = &irs1125_subdev_core_ops,
++      .video = &irs1125_subdev_video_ops,
++      .pad = &irs1125_subdev_pad_ops,
++};
++
++static int irs1125_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++      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;
++
++      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;
++                      }
++              }
++              break;
++      }
++      case IRS1125_CID_MOD_PLL:
++              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;
++                      }
++              }
++              break;
++      case IRS1125_CID_SEQ_CONFIG:
++              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;
++                      }
++              }
++              break;
++      case IRS1125_CID_NUM_SEQS:
++              err = irs1125_write(&dev->sd, 0xA88D, ctrl->val - 1);
++              if (err >= 0)
++                      dev->num_seq = ctrl->val;
++              break;
++      case IRS1125_CID_CONTINUOUS_TRIG:
++              if (ctrl->val == 0)
++                      err = irs1125_write(&dev->sd, 0xA87C, 0);
++              else
++                      err = irs1125_write(&dev->sd, 0xA87C, 1);
++              break;
++      case IRS1125_CID_TRIGGER:
++              if (ctrl->val != 0) {
++                      err = irs1125_write(&dev->sd, 0xA87C, 1);
++                      if (err >= 0)
++                              err = irs1125_write(&dev->sd, 0xA87C, 0);
++              }
++              break;
++      case IRS1125_CID_RECONFIG:
++              if (ctrl->val != 0)
++                      err = irs1125_write(&dev->sd, 0xA87A, 1);
++              break;
++      case IRS1125_CID_ILLU_ON:
++              if (ctrl->val == 0)
++                      err = irs1125_write(&dev->sd, 0xA892, 0x377);
++              else
++                      err = irs1125_write(&dev->sd, 0xA892, 0x355);
++              break;
++      default:
++              break;
++      }
++
++      if (err < 0)
++              dev_err(&client->dev, "Error executing control ID: %d, val %d, err %d",
++                      ctrl->id, ctrl->val, err);
++      else
++              err = 0;
++
++      return err;
++}
++
++static const struct v4l2_ctrl_ops irs1125_ctrl_ops = {
++      .s_ctrl = irs1125_s_ctrl,
++};
++
++static const struct v4l2_ctrl_config irs1125_custom_ctrls[] = {
++      {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_NUM_SEQS,
++              .name = "Change number of sequences",
++              .type = V4L2_CTRL_TYPE_INTEGER,
++              .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
++              .min = 1,
++              .max = 20,
++              .step = 1,
++              .def = 5,
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_MOD_PLL,
++              .name = "Reconfigure modulation PLLs",
++              .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_mod_pll) / sizeof(u16),
++                      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,
++              .flags = V4L2_CTRL_FLAG_HAS_PAYLOAD,
++              .min = 0,
++              .max = U16_MAX,
++              .step = 1,
++              .def = 0,
++              .elem_size = sizeof(u16),
++              .dims = {sizeof(struct irs1125_seq_cfg) / sizeof(u16),
++                      IRS1125_NUM_SEQ_ENTRIES}
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_CONTINUOUS_TRIG,
++              .name = "Enable/disable continuous trigger",
++              .type = V4L2_CTRL_TYPE_BOOLEAN,
++              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
++              .min = 0,
++              .max = 1,
++              .step = 1,
++              .def = 0
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_TRIGGER,
++              .name = "Capture a single sequence",
++              .type = V4L2_CTRL_TYPE_BOOLEAN,
++              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
++              .min = 0,
++              .max = 1,
++              .step = 1,
++              .def = 0
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_RECONFIG,
++              .name = "Trigger imager reconfiguration",
++              .type = V4L2_CTRL_TYPE_BOOLEAN,
++              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
++              .min = 0,
++              .max = 1,
++              .step = 1,
++              .def = 0
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_ILLU_ON,
++              .name = "Turn illu on or off",
++              .type = V4L2_CTRL_TYPE_BOOLEAN,
++              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
++              .min = 0,
++              .max = 1,
++              .step = 1,
++              .def = 1
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_IDENT0,
++              .name = "Get ident 0 information",
++              .type = V4L2_CTRL_TYPE_INTEGER,
++              .flags = V4L2_CTRL_FLAG_READ_ONLY,
++              .min = S32_MIN,
++              .max = S32_MAX,
++              .step = 1,
++              .def = 0
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_IDENT1,
++              .name = "Get ident 1 information",
++              .type = V4L2_CTRL_TYPE_INTEGER,
++              .flags = V4L2_CTRL_FLAG_READ_ONLY,
++              .min = S32_MIN,
++              .max = S32_MAX,
++              .step = 1,
++              .def = 0
++      }, {
++              .ops = &irs1125_ctrl_ops,
++              .id = IRS1125_CID_IDENT2,
++              .name = "Get ident 2 information",
++              .type = V4L2_CTRL_TYPE_INTEGER,
++              .flags = V4L2_CTRL_FLAG_READ_ONLY,
++              .min = S32_MIN,
++              .max = S32_MAX,
++              .step = 1,
++              .def = 0
++      }
++};
++
++static int irs1125_detect(struct v4l2_subdev *sd)
++{
++      u16 read;
++      int ret;
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++
++      ret = irs1125_read(sd, IRS1125_REG_DESIGN_STEP, &read);
++      if (ret < 0) {
++              dev_err(&client->dev, "error reading from i2c\n");
++              return ret;
++      }
++
++      if (read != IRS1125_DESIGN_STEP_EXPECTED) {
++              dev_err(&client->dev, "Design step expected 0x%x got 0x%x",
++                      IRS1125_DESIGN_STEP_EXPECTED, read);
++              return -ENODEV;
++      }
++
++      return 0;
++}
++
++static int irs1125_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
++{
++      struct v4l2_mbus_framefmt *format =
++      v4l2_subdev_get_try_format(sd, fh->pad, 0);
++
++      format->code = MEDIA_BUS_FMT_Y12_1X12;
++      format->width = IRS1125_WINDOW_WIDTH_DEF;
++      format->height = IRS1125_WINDOW_HEIGHT_DEF;
++      format->field = V4L2_FIELD_NONE;
++      format->colorspace = V4L2_COLORSPACE_RAW;
++
++      return 0;
++}
++
++static const struct v4l2_subdev_internal_ops irs1125_subdev_internal_ops = {
++      .open = irs1125_open,
++};
++
++static int irs1125_ctrls_init(struct irs1125 *sensor, struct device *dev)
++{
++      struct v4l2_ctrl *ctrl;
++      int err, i;
++      struct v4l2_ctrl_handler *hdl;
++
++      hdl = &sensor->ctrl_handler;
++      v4l2_ctrl_handler_init(hdl, ARRAY_SIZE(irs1125_custom_ctrls));
++
++      for (i = 0; i < ARRAY_SIZE(irs1125_custom_ctrls); i++)  {
++              ctrl = v4l2_ctrl_new_custom(hdl, &irs1125_custom_ctrls[i],
++                                          NULL);
++              if (!ctrl)
++                      dev_err(dev, "Failed to init custom control %s\n",
++                              irs1125_custom_ctrls[i].name);
++              else if (irs1125_custom_ctrls[i].id == IRS1125_CID_NUM_SEQS)
++                      sensor->ctrl_numseq = ctrl;
++              else if (irs1125_custom_ctrls[i].id == IRS1125_CID_MOD_PLL)
++                      sensor->ctrl_modplls = ctrl;
++      }
++
++      if (hdl->error) {
++              dev_err(dev, "Error %d adding controls\n", hdl->error);
++              err = hdl->error;
++              goto error_ctrls;
++      }
++
++      sensor->sd.ctrl_handler = hdl;
++      return 0;
++
++error_ctrls:
++      v4l2_ctrl_handler_free(&sensor->ctrl_handler);
++      return -err;
++}
++
++static int irs1125_ident_setup(struct irs1125 *sensor, struct device *dev)
++{
++      int ret;
++      struct v4l2_ctrl *ctrl;
++      struct v4l2_subdev *sd;
++      u16 read;
++
++      sd = &sensor->sd;
++
++      ctrl = v4l2_ctrl_find(&sensor->ctrl_handler, IRS1125_CID_IDENT0);
++      if (!ctrl) {
++              dev_err(dev, "could not find device ctrl.\n");
++              return -EINVAL;
++      }
++
++      ret = irs1125_read(sd, IRS1125_REG_EFUSEVAL2, &read);
++      if (ret < 0) {
++              dev_err(dev, "error reading from i2c\n");
++              return -EIO;
++      }
++
++      v4l2_ctrl_s_ctrl(ctrl, read);
++
++      ctrl = v4l2_ctrl_find(&sensor->ctrl_handler, IRS1125_CID_IDENT1);
++      if (!ctrl) {
++              dev_err(dev, "could not find device ctrl.\n");
++              return -EINVAL;
++      }
++
++      ret = irs1125_read(sd, IRS1125_REG_EFUSEVAL3, &read);
++      if (ret < 0) {
++              dev_err(dev, "error reading from i2c\n");
++              return -EIO;
++      }
++
++      v4l2_ctrl_s_ctrl(ctrl, read);
++
++      ctrl = v4l2_ctrl_find(&sensor->ctrl_handler, IRS1125_CID_IDENT2);
++      if (!ctrl) {
++              dev_err(dev, "could not find device ctrl.\n");
++              return -EINVAL;
++      }
++
++      ret = irs1125_read(sd, IRS1125_REG_EFUSEVAL4, &read);
++      if (ret < 0) {
++              dev_err(dev, "error reading from i2c\n");
++              return -EIO;
++      }
++      v4l2_ctrl_s_ctrl(ctrl, read & 0xFFFC);
++
++      return 0;
++}
++
++static int irs1125_probe(struct i2c_client *client,
++                       const struct i2c_device_id *id)
++{
++      struct device *dev = &client->dev;
++      struct irs1125 *sensor;
++      int ret;
++      struct fwnode_handle *endpoint;
++      u32 xclk_freq;
++      int gpio_num;
++
++      sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
++      if (!sensor)
++              return -ENOMEM;
++
++      v4l2_i2c_subdev_init(&sensor->sd, client, &irs1125_subdev_ops);
++
++      /* Get CSI2 bus config */
++      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_parse(endpoint, &sensor->ep);
++      fwnode_handle_put(endpoint);
++      if (ret) {
++              dev_err(dev, "Could not parse endpoint\n");
++              return ret;
++      }
++
++      /* get system clock (xclk) */
++      sensor->xclk = devm_clk_get(dev, NULL);
++      if (IS_ERR(sensor->xclk)) {
++              dev_err(dev, "could not get xclk");
++              return PTR_ERR(sensor->xclk);
++      }
++
++      xclk_freq = clk_get_rate(sensor->xclk);
++      if (xclk_freq != 26000000) {
++              dev_err(dev, "Unsupported clock frequency: %u\n", xclk_freq);
++              return -EINVAL;
++      }
++
++      sensor->num_seq = 5;
++
++      /* Request the power down GPIO */
++      sensor->reset = devm_gpiod_get(&client->dev, "pwdn",
++                                     GPIOD_OUT_LOW);
++
++      if (IS_ERR(sensor->reset)) {
++              dev_err(dev, "could not get reset");
++              return PTR_ERR(sensor->reset);
++      }
++
++      gpio_num = desc_to_gpio(sensor->reset);
++
++      mutex_init(&sensor->lock);
++
++      ret = irs1125_ctrls_init(sensor, dev);
++      if (ret < 0)
++              goto mutex_remove;
++
++      sensor->sd.internal_ops = &irs1125_subdev_internal_ops;
++      sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
++      sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
++      sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
++      ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
++      if (ret < 0)
++              goto mutex_remove;
++
++      gpiod_set_value_cansleep(sensor->reset, 1);
++      msleep(RESET_ACTIVE_DELAY_MS);
++
++      ret = irs1125_detect(&sensor->sd);
++      if (ret < 0)
++              goto error;
++
++      ret = irs1125_ident_setup(sensor, dev);
++      if (ret < 0)
++              goto error;
++
++      gpiod_set_value_cansleep(sensor->reset, 0);
++
++      ret = v4l2_async_register_subdev(&sensor->sd);
++      if (ret < 0)
++              goto error;
++
++      dev_dbg(dev, "Infineon IRS1125 camera driver probed\n");
++
++      return 0;
++
++error:
++      media_entity_cleanup(&sensor->sd.entity);
++mutex_remove:
++      mutex_destroy(&sensor->lock);
++      return ret;
++}
++
++static int irs1125_remove(struct i2c_client *client)
++{
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct irs1125 *irs1125 = to_state(sd);
++
++      v4l2_async_unregister_subdev(&irs1125->sd);
++      media_entity_cleanup(&irs1125->sd.entity);
++      v4l2_device_unregister_subdev(sd);
++      mutex_destroy(&irs1125->lock);
++      v4l2_ctrl_handler_free(&irs1125->ctrl_handler);
++
++      return 0;
++}
++
++#if IS_ENABLED(CONFIG_OF)
++static const struct of_device_id irs1125_of_match[] = {
++      { .compatible = "infineon,irs1125" },
++      { /* sentinel */ },
++};
++MODULE_DEVICE_TABLE(of, irs1125_of_match);
++#endif
++
++static struct i2c_driver irs1125_driver = {
++      .driver = {
++              .of_match_table = of_match_ptr(irs1125_of_match),
++              .name    = SENSOR_NAME,
++      },
++      .probe          = irs1125_probe,
++      .remove         = irs1125_remove,
++};
++
++module_i2c_driver(irs1125_driver);
++
++MODULE_AUTHOR("Markus Proeller <markus.proeller@pieye.org>");
++MODULE_DESCRIPTION("Infineon irs1125 sensor driver");
++MODULE_LICENSE("GPL v2");
++
+--- /dev/null
++++ b/drivers/media/i2c/irs1125.h
+@@ -0,0 +1,61 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * A V4L2 driver for Infineon IRS1125 TOF cameras.
++ * Copyright (C) 2018, pieye GmbH
++ *
++ * Based on V4L2 OmniVision OV5647 Image Sensor driver
++ * Copyright (C) 2016 Ramiro Oliveira <roliveir@synopsys.com>
++ *
++ * DT / fwnode changes, and GPIO control taken from ov5640.c
++ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
++ * Copyright (C) 2014-2017 Mentor Graphics Inc.
++ *
++ */
++
++#ifndef IRS1125_H
++#define IRS1125_H
++
++#include <linux/v4l2-controls.h>
++#include <linux/types.h>
++
++#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)
++
++struct irs1125_seq_cfg {
++      __u16 exposure;
++      __u16 framerate;
++      __u16 ps;
++      __u16 pll;
++};
++
++struct irs1125_illu {
++      __u16 exposure;
++      __u16 framerate;
++};
++
++struct irs1125_mod_pll {
++      __u16 pllcfg1;
++      __u16 pllcfg2;
++      __u16 pllcfg3;
++      __u16 pllcfg4;
++      __u16 pllcfg5;
++      __u16 pllcfg6;
++      __u16 pllcfg7;
++      __u16 pllcfg8;
++};
++
++#endif /* IRS1125 */
++
diff --git a/target/linux/brcm2708/patches-4.19/950-0739-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch b/target/linux/brcm2708/patches-4.19/950-0739-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch
deleted file mode 100644 (file)
index 4291f9f..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-From b4f8b92cdfd8ad2e04cdd3f0a73aa4e95d172fb1 Mon Sep 17 00:00:00 2001
-From: Markus Proeller <markus.proeller@pieye.org>
-Date: Thu, 10 Oct 2019 19:12:08 +0200
-Subject: [PATCH] dt-bindings: Add binding for the Infineon IRS1125
- sensor
-
-Adds a binding for the Infineon IRS1125 time-of-flight depth
-sensor.
-
-Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
----
- .../devicetree/bindings/media/i2c/irs1125.txt | 48 +++++++++++++++++++
- 1 file changed, 48 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/media/i2c/irs1125.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/media/i2c/irs1125.txt
-@@ -0,0 +1,48 @@
-+* Infineon irs1125 time of flight sensor
-+
-+The Infineon irs1125 is a time of flight digital image sensor with
-+an active array size of 352H x 286V. It is programmable through I2C
-+interface. The I2C address defaults to 0x3D, but can be reconfigured
-+to address 0x3C or 0x41 via I2C commands. Image data is sent through
-+MIPI CSI-2, which is configured as either 1 or 2 data lanes.
-+
-+Required Properties:
-+- compatible: value should be "infineon,irs1125" for irs1125 sensor
-+- reg: I2C bus address of the device
-+- clocks: reference to the xclk input clock.
-+- pwdn-gpios: reference to the GPIO connected to the reset pin.
-+            This is an active low signal to the iirs1125.
-+
-+The irs1125 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.
-+
-+Endpoint node required properties for CSI-2 connection are:
-+- remote-endpoint: a phandle to the bus receiver's endpoint node.
-+- clock-lanes: should be set to <0> (clock lane on hardware lane 0)
-+- data-lanes: should be set to <1> or <1 2> (one or two lane CSI-2
-+  supported)
-+
-+Example:
-+      sensor@10 {
-+              compatible = "infineon,irs1125";
-+              reg = <0x3D>;
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              clocks = <&irs1125_clk>;
-+              pwdn-gpios = <&gpio 5 0>;
-+
-+              irs1125_clk: camera-clk {
-+                      compatible = "fixed-clock";
-+                      #clock-cells = <0>;
-+                      clock-frequency = <26000000>;
-+              };
-+
-+              port {
-+                      sensor_out: endpoint {
-+                              remote-endpoint = <&csiss_in>;
-+                              clock-lanes = <0>;
-+                              data-lanes = <1 2>;
-+                      };
-+              };
-+      };
diff --git a/target/linux/brcm2708/patches-4.19/950-0739-dtoverlays-Add-an-overlay-for-the-Infineon-IRS1125.patch b/target/linux/brcm2708/patches-4.19/950-0739-dtoverlays-Add-an-overlay-for-the-Infineon-IRS1125.patch
new file mode 100644 (file)
index 0000000..1202d10
--- /dev/null
@@ -0,0 +1,149 @@
+From 89af5d7df7f548744bd675d96295c0f45e24b31f Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Thu, 10 Oct 2019 19:13:02 +0200
+Subject: [PATCH] dtoverlays: Add an overlay for the Infineon IRS1125
+
+The Infineon IRS1125 is a CSI2 time of flight depth sensor
+which has a suitable V4L2 subdevice driver.
+
+Add an overlay for configuring it.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             | 12 +++
+ .../arm/boot/dts/overlays/irs1125-overlay.dts | 97 +++++++++++++++++++
+ 3 files changed, 110 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/irs1125-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -83,6 +83,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       iqaudio-dac.dtbo \
+       iqaudio-dacplus.dtbo \
+       iqaudio-digi-wm8804-audio.dtbo \
++      irs1125.dtbo \
+       jedec-spi-nor.dtbo \
+       justboom-dac.dtbo \
+       justboom-digi.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1347,6 +1347,18 @@ Params: card_name               Override
+                                 dai stream name.
++Name:   irs1125
++Info:   Infineon irs1125 TOF camera module.
++        Uses Unicam 1, which is the standard camera connector on most Pi
++        variants.
++Load:   dtoverlay=irs1125,<param>=<val>
++Params: i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
++                                Useful on Compute Modules.
++
++        i2c_pins_28_29          Use pins 28&29 for the I2C instead of 44&45.
++                                This is required for Pi B+, 2, 0, and 0W.
++
++
+ Name:   jedec-spi-nor
+ Info:   Adds support for JEDEC-compliant SPI NOR flash devices.  (Note: The
+         "jedec,spi-nor" kernel driver was formerly known as "m25p80".)
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/irs1125-overlay.dts
+@@ -0,0 +1,97 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Definitions for IRS1125 camera module on VC I2C bus
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c_vc>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      irs1125: irs1125@3D {
++                              compatible = "infineon,irs1125";
++                              reg = <0x3D>;
++                              status = "okay";
++
++                              pwdn-gpios = <&gpio 5 0>;
++                              clocks = <&irs1125_clk>;
++
++                              irs1125_clk: camera-clk {
++                                      compatible = "fixed-clock";
++                                      #clock-cells = <0>;
++                                      clock-frequency = <26000000>;
++                              };
++
++                              port {
++                                      irs1125_0: endpoint {
++                                              remote-endpoint = <&csi1_ep>;
++                                              clock-lanes = <0>;
++                                              data-lanes = <1 2>;
++                                              clock-noncontinuous;
++                                              link-frequencies =
++                                                      /bits/ 64 <297000000>;
++                                      };
++                              };
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&csi1>;
++              __overlay__ {
++                      status = "okay";
++
++                      port {
++                              csi1_ep: endpoint {
++                                      remote-endpoint = <&irs1125_0>;
++                              };
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c0_pins>;
++              __dormant__ {
++                      brcm,pins = <28 29>;
++                      brcm,function = <4>; /* alt0 */
++              };
++      };
++      fragment@3 {
++              target = <&i2c0_pins>;
++              __overlay__ {
++                      brcm,pins = <44 45>;
++                      brcm,function = <5>; /* alt1 */
++              };
++      };
++      fragment@4 {
++              target = <&i2c0_pins>;
++              __dormant__ {
++                      brcm,pins = <0 1>;
++                      brcm,function = <4>; /* alt0 */
++              };
++      };
++      fragment@5 {
++              target = <&i2c_vc>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@6 {
++              target-path="/__overrides__";
++              __overlay__ {
++                      cam0-pwdn-ctrl = <&irs1125>,"pwdn-gpios:0";
++                      cam0-pwdn      = <&irs1125>,"pwdn-gpios:4";
++              };
++      };
++
++      __overrides__ {
++              i2c_pins_0_1 = <0>,"-2-3+4";
++              i2c_pins_28_29 = <0>,"+2-3-4";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0740-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch b/target/linux/brcm2708/patches-4.19/950-0740-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch
deleted file mode 100644 (file)
index 9b882fc..0000000
+++ /dev/null
@@ -1,1231 +0,0 @@
-From c09b42cb057ddf8bd20d57c6b0ffd94f3e15ea7c Mon Sep 17 00:00:00 2001
-From: Markus Proeller <markus.proeller@pieye.org>
-Date: Thu, 10 Oct 2019 19:12:36 +0200
-Subject: [PATCH] media: i2c: Add a driver for the Infineon IRS1125
- depth sensor
-
-The Infineon IRS1125 is a time of flight depth sensor that
-has a CSI-2 interface.
-
-Add a V4L2 subdevice driver for this device.
-
-Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
----
- drivers/media/i2c/Kconfig   |   12 +
- drivers/media/i2c/Makefile  |    1 +
- drivers/media/i2c/irs1125.c | 1112 +++++++++++++++++++++++++++++++++++
- drivers/media/i2c/irs1125.h |   61 ++
- 4 files changed, 1186 insertions(+)
- create mode 100644 drivers/media/i2c/irs1125.c
- create mode 100644 drivers/media/i2c/irs1125.h
-
---- a/drivers/media/i2c/Kconfig
-+++ b/drivers/media/i2c/Kconfig
-@@ -813,6 +813,18 @@ config VIDEO_OV13858
-         This is a Video4Linux2 sensor driver for the OmniVision
-         OV13858 camera.
-+config VIDEO_IRS1125
-+      tristate "Infineon IRS1125 sensor support"
-+      depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-+      depends on MEDIA_CAMERA_SUPPORT
-+      select V4L2_FWNODE
-+      help
-+        This is a Video4Linux2 sensor-level driver for the Infineon
-+        IRS1125 camera.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called irs1125.
-+
- config VIDEO_VS6624
-       tristate "ST VS6624 sensor support"
-       depends on VIDEO_V4L2 && I2C
---- a/drivers/media/i2c/Makefile
-+++ b/drivers/media/i2c/Makefile
-@@ -80,6 +80,7 @@ obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
- obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
- obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
- obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
-+obj-$(CONFIG_VIDEO_IRS1125) += irs1125.o
- obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
- obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o
- obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
---- /dev/null
-+++ b/drivers/media/i2c/irs1125.c
-@@ -0,0 +1,1112 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * A V4L2 driver for Infineon IRS1125 TOF cameras.
-+ * Copyright (C) 2018, pieye GmbH
-+ *
-+ * Based on V4L2 OmniVision OV5647 Image Sensor driver
-+ * Copyright (C) 2016 Ramiro Oliveira <roliveir@synopsys.com>
-+ *
-+ * DT / fwnode changes, and GPIO control taken from ov5640.c
-+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
-+ * Copyright (C) 2014-2017 Mentor Graphics Inc.
-+ *
-+ */
-+
-+#include "irs1125.h"
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of_graph.h>
-+#include <linux/slab.h>
-+#include <linux/videodev2.h>
-+#include <linux/firmware.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))
-+
-+#define SENSOR_NAME "irs1125"
-+
-+#define RESET_ACTIVE_DELAY_MS  20
-+
-+#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_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_WIDTH_DEF      352
-+
-+struct regval_list {
-+      u16 addr;
-+      u16 data;
-+};
-+
-+struct irs1125 {
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+      /* the parsed DT endpoint info */
-+      struct v4l2_fwnode_endpoint ep;
-+
-+      struct clk *xclk;
-+      struct v4l2_ctrl_handler ctrl_handler;
-+
-+      /* To serialize asynchronus callbacks */
-+      struct mutex lock;
-+
-+      /* image data layout */
-+      unsigned int num_seq;
-+
-+      /* reset pin */
-+      struct gpio_desc *reset;
-+
-+      /* V4l2 Controls to grab */
-+      struct v4l2_ctrl *ctrl_modplls;
-+      struct v4l2_ctrl *ctrl_numseq;
-+
-+      int power_count;
-+};
-+
-+static inline struct irs1125 *to_state(struct v4l2_subdev *sd)
-+{
-+      return container_of(sd, struct irs1125, sd);
-+}
-+
-+static struct regval_list irs1125_26MHz[] = {
-+      {0xB017, 0x0413},
-+      {0xB086, 0x3535},
-+      {0xB0AE, 0xEF02},
-+      {0xA000, 0x0004},
-+      {0xFFFF, 100},
-+
-+      {0xB062, 0x6383},
-+      {0xB063, 0x55A8},
-+      {0xB068, 0x7628},
-+      {0xB069, 0x03E2},
-+
-+      {0xFFFF, 100},
-+      {0xB05A, 0x01C5},
-+      {0xB05C, 0x0206},
-+      {0xB05D, 0x01C5},
-+      {0xB05F, 0x0206},
-+      {0xB016, 0x1335},
-+      {0xFFFF, 100},
-+      {0xA893, 0x8261},
-+      {0xA894, 0x89d8},
-+      {0xA895, 0x131d},
-+      {0xA896, 0x4251},
-+      {0xA897, 0x9D8A},
-+      {0xA898, 0x0BD8},
-+      {0xA899, 0x2245},
-+      {0xA89A, 0xAB9B},
-+      {0xA89B, 0x03B9},
-+      {0xA89C, 0x8041},
-+      {0xA89D, 0xE07E},
-+      {0xA89E, 0x0307},
-+      {0xFFFF, 100},
-+      {0xA88D, 0x0004},
-+      {0xA800, 0x0E68},
-+      {0xA801, 0x0000},
-+      {0xA802, 0x000C},
-+      {0xA803, 0x0000},
-+      {0xA804, 0x0E68},
-+      {0xA805, 0x0000},
-+      {0xA806, 0x0440},
-+      {0xA807, 0x0000},
-+      {0xA808, 0x0E68},
-+      {0xA809, 0x0000},
-+      {0xA80A, 0x0884},
-+      {0xA80B, 0x0000},
-+      {0xA80C, 0x0E68},
-+      {0xA80D, 0x0000},
-+      {0xA80E, 0x0CC8},
-+      {0xA80F, 0x0000},
-+      {0xA810, 0x0E68},
-+      {0xA811, 0x0000},
-+      {0xA812, 0x2000},
-+      {0xA813, 0x0000},
-+      {0xA882, 0x0081},
-+      {0xA88C, 0x403A},
-+      {0xA88F, 0x031E},
-+      {0xA892, 0x0351},
-+      {0x9813, 0x13FF},
-+      {0x981B, 0x7608},
-+
-+      {0xB008, 0x0000},
-+      {0xB015, 0x1513},
-+
-+      {0xFFFF, 100}
-+};
-+
-+static struct regval_list irs1125_seq_cfg[] = {
-+      {0xC3A0, 0x823D},
-+      {0xC3A1, 0xB13B},
-+      {0xC3A2, 0x0313},
-+      {0xC3A3, 0x4659},
-+      {0xC3A4, 0xC4EC},
-+      {0xC3A5, 0x03CE},
-+      {0xC3A6, 0x4259},
-+      {0xC3A7, 0xC4EC},
-+      {0xC3A8, 0x03CE},
-+      {0xC3A9, 0x8839},
-+      {0xC3AA, 0x89D8},
-+      {0xC3AB, 0x031D},
-+
-+      {0xC24C, 0x5529},
-+      {0xC24D, 0x0000},
-+      {0xC24E, 0x1200},
-+      {0xC24F, 0x6CB2},
-+      {0xC250, 0x0000},
-+      {0xC251, 0x5529},
-+      {0xC252, 0x42F4},
-+      {0xC253, 0xD1AF},
-+      {0xC254, 0x8A18},
-+      {0xC255, 0x0002},
-+      {0xC256, 0x5529},
-+      {0xC257, 0x6276},
-+      {0xC258, 0x11A7},
-+      {0xC259, 0xD907},
-+      {0xC25A, 0x0000},
-+      {0xC25B, 0x5529},
-+      {0xC25C, 0x07E0},
-+      {0xC25D, 0x7BFE},
-+      {0xC25E, 0x6402},
-+      {0xC25F, 0x0019},
-+
-+      {0xC3AC, 0x0007},
-+      {0xC3AD, 0xED88},
-+      {0xC320, 0x003E},
-+      {0xC321, 0x0000},
-+      {0xC322, 0x2000},
-+      {0xC323, 0x0000},
-+      {0xC324, 0x0271},
-+      {0xC325, 0x0000},
-+      {0xC326, 0x000C},
-+      {0xC327, 0x0000},
-+      {0xC328, 0x0271},
-+      {0xC329, 0x0000},
-+      {0xC32A, 0x0440},
-+      {0xC32B, 0x0000},
-+      {0xC32C, 0x0271},
-+      {0xC32D, 0x0000},
-+      {0xC32E, 0x0884},
-+      {0xC32F, 0x0000},
-+      {0xC330, 0x0271},
-+      {0xC331, 0x0000},
-+      {0xC332, 0x0CC8},
-+      {0xC333, 0x0000},
-+      {0xA88D, 0x0004},
-+
-+      {0xA890, 0x0000},
-+      {0xC219, 0x0002},
-+      {0xC21A, 0x0000},
-+      {0xC21B, 0x0000},
-+      {0xC21C, 0x00CD},
-+      {0xC21D, 0x0009},
-+      {0xC21E, 0x00CD},
-+      {0xC21F, 0x0009},
-+
-+      {0xA87C, 0x0000},
-+      {0xC032, 0x0001},
-+      {0xC034, 0x0000},
-+      {0xC035, 0x0001},
-+      {0xC039, 0x0000},
-+      {0xC401, 0x0002},
-+
-+      {0xFFFF, 1},
-+      {0xA87C, 0x0001}
-+};
-+
-+static int irs1125_write(struct v4l2_subdev *sd, u16 reg, u16 val)
-+{
-+      int ret;
-+      unsigned char data[4] = { reg >> 8, reg & 0xff, val >> 8, val & 0xff};
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+
-+      ret = i2c_master_send(client, data, 4);
-+      if (ret < 0)
-+              dev_err(&client->dev, "%s: i2c write error, reg: %x\n",
-+                      __func__, reg);
-+
-+      return ret;
-+}
-+
-+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);
-+
-+      ret = i2c_master_send(client, data_w, 2);
-+      if (ret < 0) {
-+              dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
-+                      __func__, reg);
-+              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);
-+
-+      return ret;
-+}
-+
-+static int irs1125_write_array(struct v4l2_subdev *sd,
-+                             struct regval_list *regs, int array_size)
-+{
-+      int i, ret;
-+
-+      for (i = 0; i < array_size; i++) {
-+              if (regs[i].addr == 0xFFFF) {
-+                      msleep(regs[i].data);
-+              } else {
-+                      ret = irs1125_write(sd, regs[i].addr, regs[i].data);
-+                      if (ret < 0)
-+                              return ret;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int irs1125_stream_on(struct v4l2_subdev *sd)
-+{
-+      int ret;
-+      struct irs1125 *irs1125 = to_state(sd);
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+
-+      v4l2_ctrl_grab(irs1125->ctrl_numseq, 1);
-+      v4l2_ctrl_grab(irs1125->ctrl_modplls, 1);
-+
-+      ret = irs1125_write(sd, 0xC400, 0x0001);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "error enabling firmware: %d", ret);
-+              return ret;
-+      }
-+
-+      msleep(100);
-+
-+      return irs1125_write(sd, 0xA87C, 0x0001);
-+}
-+
-+static int irs1125_stream_off(struct v4l2_subdev *sd)
-+{
-+      int ret;
-+      struct irs1125 *irs1125 = to_state(sd);
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+
-+      v4l2_ctrl_grab(irs1125->ctrl_numseq, 0);
-+      v4l2_ctrl_grab(irs1125->ctrl_modplls, 0);
-+
-+      ret = irs1125_write(sd, 0xA87C, 0x0000);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "error disabling trigger: %d", ret);
-+              return ret;
-+      }
-+
-+      msleep(100);
-+
-+      return irs1125_write(sd, 0xC400, 0x0002);
-+}
-+
-+static int __sensor_init(struct v4l2_subdev *sd)
-+{
-+      unsigned int cnt, idx;
-+      int ret;
-+      u16 val;
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+      struct irs1125 *irs1125 = to_state(sd);
-+      const struct firmware *fw;
-+      struct regval_list *reg_data;
-+
-+      cnt = 0;
-+      while (1) {
-+              ret = irs1125_read(sd, 0xC40F, &val);
-+              if (ret < 0) {
-+                      dev_err(&client->dev, "read register 0xC40F failed\n");
-+                      return ret;
-+              }
-+              if (CHECK_BIT(val, 14) == 0)
-+                      break;
-+
-+              if (cnt >= 5) {
-+                      dev_err(&client->dev, "timeout waiting for 0xC40F\n");
-+                      return -EAGAIN;
-+              }
-+
-+              cnt++;
-+      }
-+
-+      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;
-+      }
-+
-+      /* set CSI-2 number of data lanes */
-+      if (irs1125->ep.bus.mipi_csi2.num_data_lanes == 1) {
-+              val = 0x0001;
-+      } else if (irs1125->ep.bus.mipi_csi2.num_data_lanes == 2) {
-+              val = 0x0081;
-+      } else {
-+              dev_err(&client->dev, "invalid number of data lanes %d\n",
-+                      irs1125->ep.bus.mipi_csi2.num_data_lanes);
-+              return -EINVAL;
-+      }
-+
-+      ret = irs1125_write(sd, IRS1125_REG_CSICFG, val);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "write sensor csi2 config error\n");
-+              return ret;
-+      }
-+
-+      /* request the firmware, this will block and timeout */
-+      ret = request_firmware(&fw, IRS1125_ALTERNATE_FW, &client->dev);
-+      if (ret) {
-+              dev_err(&client->dev,
-+                      "did not find the firmware file '%s' (status %d)\n",
-+                      IRS1125_ALTERNATE_FW, ret);
-+              return ret;
-+      }
-+
-+      if (fw->size % 4) {
-+              dev_err(&client->dev, "firmware file '%s' invalid\n",
-+                      IRS1125_ALTERNATE_FW);
-+              release_firmware(fw);
-+              return -EINVAL;
-+      }
-+
-+      for (idx = 0; idx < fw->size; idx += 4) {
-+              reg_data = (struct regval_list *)&fw->data[idx];
-+              ret = irs1125_write(sd, reg_data->addr, reg_data->data);
-+              if (ret < 0) {
-+                      dev_err(&client->dev, "firmware write error\n");
-+                      release_firmware(fw);
-+                      return ret;
-+              }
-+      }
-+      release_firmware(fw);
-+
-+      ret = irs1125_write_array(sd, irs1125_seq_cfg,
-+                                ARRAY_SIZE(irs1125_seq_cfg));
-+      if (ret < 0) {
-+              dev_err(&client->dev, "write default sequence failed\n");
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int irs1125_sensor_power(struct v4l2_subdev *sd, int on)
-+{
-+      int ret = 0;
-+      struct irs1125 *irs1125 = to_state(sd);
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+
-+      mutex_lock(&irs1125->lock);
-+
-+      if (on && !irs1125->power_count) {
-+              gpiod_set_value_cansleep(irs1125->reset, 1);
-+              msleep(RESET_ACTIVE_DELAY_MS);
-+
-+              ret = clk_prepare_enable(irs1125->xclk);
-+              if (ret < 0) {
-+                      dev_err(&client->dev, "clk prepare enable failed\n");
-+                      goto out;
-+              }
-+
-+              ret = __sensor_init(sd);
-+              if (ret < 0) {
-+                      clk_disable_unprepare(irs1125->xclk);
-+                      dev_err(&client->dev,
-+                              "Camera not available, check Power\n");
-+                      goto out;
-+              }
-+      } else if (!on && irs1125->power_count == 1) {
-+              gpiod_set_value_cansleep(irs1125->reset, 0);
-+      }
-+
-+      /* Update the power count. */
-+      irs1125->power_count += on ? 1 : -1;
-+      WARN_ON(irs1125->power_count < 0);
-+
-+out:
-+      mutex_unlock(&irs1125->lock);
-+
-+      return ret;
-+}
-+
-+#ifdef CONFIG_VIDEO_ADV_DEBUG
-+static int irs1125_sensor_get_register(struct v4l2_subdev *sd,
-+                                     struct v4l2_dbg_register *reg)
-+{
-+      u16 val;
-+      int ret;
-+
-+      ret = irs1125_read(sd, reg->reg & 0xffff, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      reg->val = val;
-+      reg->size = 1;
-+
-+      return 0;
-+}
-+
-+static int irs1125_sensor_set_register(struct v4l2_subdev *sd,
-+                                     const struct v4l2_dbg_register *reg)
-+{
-+      return irs1125_write(sd, reg->reg & 0xffff, reg->val & 0xffff);
-+}
-+#endif
-+
-+static const struct v4l2_subdev_core_ops irs1125_subdev_core_ops = {
-+      .s_power = irs1125_sensor_power,
-+#ifdef CONFIG_VIDEO_ADV_DEBUG
-+      .g_register = irs1125_sensor_get_register,
-+      .s_register = irs1125_sensor_set_register,
-+#endif
-+};
-+
-+static int irs1125_s_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      if (enable)
-+              return irs1125_stream_on(sd);
-+      else
-+              return irs1125_stream_off(sd);
-+}
-+
-+static const struct v4l2_subdev_video_ops irs1125_subdev_video_ops = {
-+      .s_stream = irs1125_s_stream,
-+};
-+
-+static int irs1125_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_Y12_1X12;
-+
-+      return 0;
-+}
-+
-+static int irs1125_set_get_fmt(struct v4l2_subdev *sd,
-+                             struct v4l2_subdev_pad_config *cfg,
-+                             struct v4l2_subdev_format *format)
-+{
-+      struct v4l2_mbus_framefmt *fmt = &format->format;
-+      struct irs1125 *irs1125 = to_state(sd);
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      /* Only one format is supported, so return that */
-+      memset(fmt, 0, sizeof(*fmt));
-+      fmt->code = MEDIA_BUS_FMT_Y12_1X12;
-+      fmt->colorspace = V4L2_COLORSPACE_RAW;
-+      fmt->field = V4L2_FIELD_NONE;
-+      fmt->width = IRS1125_WINDOW_WIDTH_DEF;
-+      fmt->height = IRS1125_WINDOW_HEIGHT_DEF * irs1125->num_seq;
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_pad_ops irs1125_subdev_pad_ops = {
-+      .enum_mbus_code = irs1125_enum_mbus_code,
-+      .set_fmt = irs1125_set_get_fmt,
-+      .get_fmt = irs1125_set_get_fmt,
-+};
-+
-+static const struct v4l2_subdev_ops irs1125_subdev_ops = {
-+      .core = &irs1125_subdev_core_ops,
-+      .video = &irs1125_subdev_video_ops,
-+      .pad = &irs1125_subdev_pad_ops,
-+};
-+
-+static int irs1125_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      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;
-+
-+      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;
-+                      }
-+              }
-+              break;
-+      }
-+      case IRS1125_CID_MOD_PLL:
-+              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;
-+                      }
-+              }
-+              break;
-+      case IRS1125_CID_SEQ_CONFIG:
-+              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;
-+                      }
-+              }
-+              break;
-+      case IRS1125_CID_NUM_SEQS:
-+              err = irs1125_write(&dev->sd, 0xA88D, ctrl->val - 1);
-+              if (err >= 0)
-+                      dev->num_seq = ctrl->val;
-+              break;
-+      case IRS1125_CID_CONTINUOUS_TRIG:
-+              if (ctrl->val == 0)
-+                      err = irs1125_write(&dev->sd, 0xA87C, 0);
-+              else
-+                      err = irs1125_write(&dev->sd, 0xA87C, 1);
-+              break;
-+      case IRS1125_CID_TRIGGER:
-+              if (ctrl->val != 0) {
-+                      err = irs1125_write(&dev->sd, 0xA87C, 1);
-+                      if (err >= 0)
-+                              err = irs1125_write(&dev->sd, 0xA87C, 0);
-+              }
-+              break;
-+      case IRS1125_CID_RECONFIG:
-+              if (ctrl->val != 0)
-+                      err = irs1125_write(&dev->sd, 0xA87A, 1);
-+              break;
-+      case IRS1125_CID_ILLU_ON:
-+              if (ctrl->val == 0)
-+                      err = irs1125_write(&dev->sd, 0xA892, 0x377);
-+              else
-+                      err = irs1125_write(&dev->sd, 0xA892, 0x355);
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      if (err < 0)
-+              dev_err(&client->dev, "Error executing control ID: %d, val %d, err %d",
-+                      ctrl->id, ctrl->val, err);
-+      else
-+              err = 0;
-+
-+      return err;
-+}
-+
-+static const struct v4l2_ctrl_ops irs1125_ctrl_ops = {
-+      .s_ctrl = irs1125_s_ctrl,
-+};
-+
-+static const struct v4l2_ctrl_config irs1125_custom_ctrls[] = {
-+      {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_NUM_SEQS,
-+              .name = "Change number of sequences",
-+              .type = V4L2_CTRL_TYPE_INTEGER,
-+              .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
-+              .min = 1,
-+              .max = 20,
-+              .step = 1,
-+              .def = 5,
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_MOD_PLL,
-+              .name = "Reconfigure modulation PLLs",
-+              .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_mod_pll) / sizeof(u16),
-+                      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,
-+              .flags = V4L2_CTRL_FLAG_HAS_PAYLOAD,
-+              .min = 0,
-+              .max = U16_MAX,
-+              .step = 1,
-+              .def = 0,
-+              .elem_size = sizeof(u16),
-+              .dims = {sizeof(struct irs1125_seq_cfg) / sizeof(u16),
-+                      IRS1125_NUM_SEQ_ENTRIES}
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_CONTINUOUS_TRIG,
-+              .name = "Enable/disable continuous trigger",
-+              .type = V4L2_CTRL_TYPE_BOOLEAN,
-+              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
-+              .min = 0,
-+              .max = 1,
-+              .step = 1,
-+              .def = 0
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_TRIGGER,
-+              .name = "Capture a single sequence",
-+              .type = V4L2_CTRL_TYPE_BOOLEAN,
-+              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
-+              .min = 0,
-+              .max = 1,
-+              .step = 1,
-+              .def = 0
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_RECONFIG,
-+              .name = "Trigger imager reconfiguration",
-+              .type = V4L2_CTRL_TYPE_BOOLEAN,
-+              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
-+              .min = 0,
-+              .max = 1,
-+              .step = 1,
-+              .def = 0
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_ILLU_ON,
-+              .name = "Turn illu on or off",
-+              .type = V4L2_CTRL_TYPE_BOOLEAN,
-+              .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
-+              .min = 0,
-+              .max = 1,
-+              .step = 1,
-+              .def = 1
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_IDENT0,
-+              .name = "Get ident 0 information",
-+              .type = V4L2_CTRL_TYPE_INTEGER,
-+              .flags = V4L2_CTRL_FLAG_READ_ONLY,
-+              .min = S32_MIN,
-+              .max = S32_MAX,
-+              .step = 1,
-+              .def = 0
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_IDENT1,
-+              .name = "Get ident 1 information",
-+              .type = V4L2_CTRL_TYPE_INTEGER,
-+              .flags = V4L2_CTRL_FLAG_READ_ONLY,
-+              .min = S32_MIN,
-+              .max = S32_MAX,
-+              .step = 1,
-+              .def = 0
-+      }, {
-+              .ops = &irs1125_ctrl_ops,
-+              .id = IRS1125_CID_IDENT2,
-+              .name = "Get ident 2 information",
-+              .type = V4L2_CTRL_TYPE_INTEGER,
-+              .flags = V4L2_CTRL_FLAG_READ_ONLY,
-+              .min = S32_MIN,
-+              .max = S32_MAX,
-+              .step = 1,
-+              .def = 0
-+      }
-+};
-+
-+static int irs1125_detect(struct v4l2_subdev *sd)
-+{
-+      u16 read;
-+      int ret;
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+
-+      ret = irs1125_read(sd, IRS1125_REG_DESIGN_STEP, &read);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "error reading from i2c\n");
-+              return ret;
-+      }
-+
-+      if (read != IRS1125_DESIGN_STEP_EXPECTED) {
-+              dev_err(&client->dev, "Design step expected 0x%x got 0x%x",
-+                      IRS1125_DESIGN_STEP_EXPECTED, read);
-+              return -ENODEV;
-+      }
-+
-+      return 0;
-+}
-+
-+static int irs1125_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-+{
-+      struct v4l2_mbus_framefmt *format =
-+      v4l2_subdev_get_try_format(sd, fh->pad, 0);
-+
-+      format->code = MEDIA_BUS_FMT_Y12_1X12;
-+      format->width = IRS1125_WINDOW_WIDTH_DEF;
-+      format->height = IRS1125_WINDOW_HEIGHT_DEF;
-+      format->field = V4L2_FIELD_NONE;
-+      format->colorspace = V4L2_COLORSPACE_RAW;
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_internal_ops irs1125_subdev_internal_ops = {
-+      .open = irs1125_open,
-+};
-+
-+static int irs1125_ctrls_init(struct irs1125 *sensor, struct device *dev)
-+{
-+      struct v4l2_ctrl *ctrl;
-+      int err, i;
-+      struct v4l2_ctrl_handler *hdl;
-+
-+      hdl = &sensor->ctrl_handler;
-+      v4l2_ctrl_handler_init(hdl, ARRAY_SIZE(irs1125_custom_ctrls));
-+
-+      for (i = 0; i < ARRAY_SIZE(irs1125_custom_ctrls); i++)  {
-+              ctrl = v4l2_ctrl_new_custom(hdl, &irs1125_custom_ctrls[i],
-+                                          NULL);
-+              if (!ctrl)
-+                      dev_err(dev, "Failed to init custom control %s\n",
-+                              irs1125_custom_ctrls[i].name);
-+              else if (irs1125_custom_ctrls[i].id == IRS1125_CID_NUM_SEQS)
-+                      sensor->ctrl_numseq = ctrl;
-+              else if (irs1125_custom_ctrls[i].id == IRS1125_CID_MOD_PLL)
-+                      sensor->ctrl_modplls = ctrl;
-+      }
-+
-+      if (hdl->error) {
-+              dev_err(dev, "Error %d adding controls\n", hdl->error);
-+              err = hdl->error;
-+              goto error_ctrls;
-+      }
-+
-+      sensor->sd.ctrl_handler = hdl;
-+      return 0;
-+
-+error_ctrls:
-+      v4l2_ctrl_handler_free(&sensor->ctrl_handler);
-+      return -err;
-+}
-+
-+static int irs1125_ident_setup(struct irs1125 *sensor, struct device *dev)
-+{
-+      int ret;
-+      struct v4l2_ctrl *ctrl;
-+      struct v4l2_subdev *sd;
-+      u16 read;
-+
-+      sd = &sensor->sd;
-+
-+      ctrl = v4l2_ctrl_find(&sensor->ctrl_handler, IRS1125_CID_IDENT0);
-+      if (!ctrl) {
-+              dev_err(dev, "could not find device ctrl.\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = irs1125_read(sd, IRS1125_REG_EFUSEVAL2, &read);
-+      if (ret < 0) {
-+              dev_err(dev, "error reading from i2c\n");
-+              return -EIO;
-+      }
-+
-+      v4l2_ctrl_s_ctrl(ctrl, read);
-+
-+      ctrl = v4l2_ctrl_find(&sensor->ctrl_handler, IRS1125_CID_IDENT1);
-+      if (!ctrl) {
-+              dev_err(dev, "could not find device ctrl.\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = irs1125_read(sd, IRS1125_REG_EFUSEVAL3, &read);
-+      if (ret < 0) {
-+              dev_err(dev, "error reading from i2c\n");
-+              return -EIO;
-+      }
-+
-+      v4l2_ctrl_s_ctrl(ctrl, read);
-+
-+      ctrl = v4l2_ctrl_find(&sensor->ctrl_handler, IRS1125_CID_IDENT2);
-+      if (!ctrl) {
-+              dev_err(dev, "could not find device ctrl.\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = irs1125_read(sd, IRS1125_REG_EFUSEVAL4, &read);
-+      if (ret < 0) {
-+              dev_err(dev, "error reading from i2c\n");
-+              return -EIO;
-+      }
-+      v4l2_ctrl_s_ctrl(ctrl, read & 0xFFFC);
-+
-+      return 0;
-+}
-+
-+static int irs1125_probe(struct i2c_client *client,
-+                       const struct i2c_device_id *id)
-+{
-+      struct device *dev = &client->dev;
-+      struct irs1125 *sensor;
-+      int ret;
-+      struct fwnode_handle *endpoint;
-+      u32 xclk_freq;
-+      int gpio_num;
-+
-+      sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
-+      if (!sensor)
-+              return -ENOMEM;
-+
-+      v4l2_i2c_subdev_init(&sensor->sd, client, &irs1125_subdev_ops);
-+
-+      /* Get CSI2 bus config */
-+      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_parse(endpoint, &sensor->ep);
-+      fwnode_handle_put(endpoint);
-+      if (ret) {
-+              dev_err(dev, "Could not parse endpoint\n");
-+              return ret;
-+      }
-+
-+      /* get system clock (xclk) */
-+      sensor->xclk = devm_clk_get(dev, NULL);
-+      if (IS_ERR(sensor->xclk)) {
-+              dev_err(dev, "could not get xclk");
-+              return PTR_ERR(sensor->xclk);
-+      }
-+
-+      xclk_freq = clk_get_rate(sensor->xclk);
-+      if (xclk_freq != 26000000) {
-+              dev_err(dev, "Unsupported clock frequency: %u\n", xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      sensor->num_seq = 5;
-+
-+      /* Request the power down GPIO */
-+      sensor->reset = devm_gpiod_get(&client->dev, "pwdn",
-+                                     GPIOD_OUT_LOW);
-+
-+      if (IS_ERR(sensor->reset)) {
-+              dev_err(dev, "could not get reset");
-+              return PTR_ERR(sensor->reset);
-+      }
-+
-+      gpio_num = desc_to_gpio(sensor->reset);
-+
-+      mutex_init(&sensor->lock);
-+
-+      ret = irs1125_ctrls_init(sensor, dev);
-+      if (ret < 0)
-+              goto mutex_remove;
-+
-+      sensor->sd.internal_ops = &irs1125_subdev_internal_ops;
-+      sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-+      sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+      sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
-+      ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
-+      if (ret < 0)
-+              goto mutex_remove;
-+
-+      gpiod_set_value_cansleep(sensor->reset, 1);
-+      msleep(RESET_ACTIVE_DELAY_MS);
-+
-+      ret = irs1125_detect(&sensor->sd);
-+      if (ret < 0)
-+              goto error;
-+
-+      ret = irs1125_ident_setup(sensor, dev);
-+      if (ret < 0)
-+              goto error;
-+
-+      gpiod_set_value_cansleep(sensor->reset, 0);
-+
-+      ret = v4l2_async_register_subdev(&sensor->sd);
-+      if (ret < 0)
-+              goto error;
-+
-+      dev_dbg(dev, "Infineon IRS1125 camera driver probed\n");
-+
-+      return 0;
-+
-+error:
-+      media_entity_cleanup(&sensor->sd.entity);
-+mutex_remove:
-+      mutex_destroy(&sensor->lock);
-+      return ret;
-+}
-+
-+static int irs1125_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct irs1125 *irs1125 = to_state(sd);
-+
-+      v4l2_async_unregister_subdev(&irs1125->sd);
-+      media_entity_cleanup(&irs1125->sd.entity);
-+      v4l2_device_unregister_subdev(sd);
-+      mutex_destroy(&irs1125->lock);
-+      v4l2_ctrl_handler_free(&irs1125->ctrl_handler);
-+
-+      return 0;
-+}
-+
-+#if IS_ENABLED(CONFIG_OF)
-+static const struct of_device_id irs1125_of_match[] = {
-+      { .compatible = "infineon,irs1125" },
-+      { /* sentinel */ },
-+};
-+MODULE_DEVICE_TABLE(of, irs1125_of_match);
-+#endif
-+
-+static struct i2c_driver irs1125_driver = {
-+      .driver = {
-+              .of_match_table = of_match_ptr(irs1125_of_match),
-+              .name    = SENSOR_NAME,
-+      },
-+      .probe          = irs1125_probe,
-+      .remove         = irs1125_remove,
-+};
-+
-+module_i2c_driver(irs1125_driver);
-+
-+MODULE_AUTHOR("Markus Proeller <markus.proeller@pieye.org>");
-+MODULE_DESCRIPTION("Infineon irs1125 sensor driver");
-+MODULE_LICENSE("GPL v2");
-+
---- /dev/null
-+++ b/drivers/media/i2c/irs1125.h
-@@ -0,0 +1,61 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * A V4L2 driver for Infineon IRS1125 TOF cameras.
-+ * Copyright (C) 2018, pieye GmbH
-+ *
-+ * Based on V4L2 OmniVision OV5647 Image Sensor driver
-+ * Copyright (C) 2016 Ramiro Oliveira <roliveir@synopsys.com>
-+ *
-+ * DT / fwnode changes, and GPIO control taken from ov5640.c
-+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
-+ * Copyright (C) 2014-2017 Mentor Graphics Inc.
-+ *
-+ */
-+
-+#ifndef IRS1125_H
-+#define IRS1125_H
-+
-+#include <linux/v4l2-controls.h>
-+#include <linux/types.h>
-+
-+#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)
-+
-+struct irs1125_seq_cfg {
-+      __u16 exposure;
-+      __u16 framerate;
-+      __u16 ps;
-+      __u16 pll;
-+};
-+
-+struct irs1125_illu {
-+      __u16 exposure;
-+      __u16 framerate;
-+};
-+
-+struct irs1125_mod_pll {
-+      __u16 pllcfg1;
-+      __u16 pllcfg2;
-+      __u16 pllcfg3;
-+      __u16 pllcfg4;
-+      __u16 pllcfg5;
-+      __u16 pllcfg6;
-+      __u16 pllcfg7;
-+      __u16 pllcfg8;
-+};
-+
-+#endif /* IRS1125 */
-+
diff --git a/target/linux/brcm2708/patches-4.19/950-0740-rpi-wm8804-soundcard-Fixed-MCLKDIV-for-Allo-Digione.patch b/target/linux/brcm2708/patches-4.19/950-0740-rpi-wm8804-soundcard-Fixed-MCLKDIV-for-Allo-Digione.patch
new file mode 100644 (file)
index 0000000..952e266
--- /dev/null
@@ -0,0 +1,42 @@
+From 09ad53f0267e4b5433c27c77b3945d584ac0a6ba Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 22 Oct 2019 08:47:29 +0100
+Subject: [PATCH] rpi-wm8804-soundcard: Fixed MCLKDIV for Allo Digione
+
+The Allo Digione board wants a fixed MCLKDIV of 256.
+
+See: https://github.com/raspberrypi/linux/issues/3296
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ sound/soc/bcm/rpi-wm8804-soundcard.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/sound/soc/bcm/rpi-wm8804-soundcard.c
++++ b/sound/soc/bcm/rpi-wm8804-soundcard.c
+@@ -66,6 +66,11 @@ static struct gpio_desc *snd_clk44gpio;
+ static struct gpio_desc *snd_clk48gpio;
+ static int wm8804_samplerate = 0;
++/* Forward declarations */
++static struct snd_soc_dai_link snd_allo_digione_dai[];
++static struct snd_soc_card snd_rpi_wm8804;
++
++
+ #define CLK_44EN_RATE 22579200UL
+ #define CLK_48EN_RATE 24576000UL
+@@ -90,11 +95,10 @@ static unsigned int snd_rpi_wm8804_enabl
+ static void snd_rpi_wm8804_clk_cfg(unsigned int samplerate,
+               struct wm8804_clk_cfg *clk_cfg)
+ {
+-      clk_cfg->mclk_freq = 0;
+-      clk_cfg->mclk_div = 1;
+       clk_cfg->sysclk_freq = 27000000;
+-      if (samplerate <= 96000) {
++      if (samplerate <= 96000 ||
++          snd_rpi_wm8804.dai_link == snd_allo_digione_dai) {
+               clk_cfg->mclk_freq = samplerate * 256;
+               clk_cfg->mclk_div = WM8804_MCLKDIV_256FS;
+       } else {
diff --git a/target/linux/brcm2708/patches-4.19/950-0741-dtoverlays-Add-an-overlay-for-the-Infineon-IRS1125.patch b/target/linux/brcm2708/patches-4.19/950-0741-dtoverlays-Add-an-overlay-for-the-Infineon-IRS1125.patch
deleted file mode 100644 (file)
index 1202d10..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-From 89af5d7df7f548744bd675d96295c0f45e24b31f Mon Sep 17 00:00:00 2001
-From: Markus Proeller <markus.proeller@pieye.org>
-Date: Thu, 10 Oct 2019 19:13:02 +0200
-Subject: [PATCH] dtoverlays: Add an overlay for the Infineon IRS1125
-
-The Infineon IRS1125 is a CSI2 time of flight depth sensor
-which has a suitable V4L2 subdevice driver.
-
-Add an overlay for configuring it.
-
-Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             | 12 +++
- .../arm/boot/dts/overlays/irs1125-overlay.dts | 97 +++++++++++++++++++
- 3 files changed, 110 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/irs1125-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -83,6 +83,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       iqaudio-dac.dtbo \
-       iqaudio-dacplus.dtbo \
-       iqaudio-digi-wm8804-audio.dtbo \
-+      irs1125.dtbo \
-       jedec-spi-nor.dtbo \
-       justboom-dac.dtbo \
-       justboom-digi.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1347,6 +1347,18 @@ Params: card_name               Override
-                                 dai stream name.
-+Name:   irs1125
-+Info:   Infineon irs1125 TOF camera module.
-+        Uses Unicam 1, which is the standard camera connector on most Pi
-+        variants.
-+Load:   dtoverlay=irs1125,<param>=<val>
-+Params: i2c_pins_0_1            Use pins 0&1 for the I2C instead of 44&45.
-+                                Useful on Compute Modules.
-+
-+        i2c_pins_28_29          Use pins 28&29 for the I2C instead of 44&45.
-+                                This is required for Pi B+, 2, 0, and 0W.
-+
-+
- Name:   jedec-spi-nor
- Info:   Adds support for JEDEC-compliant SPI NOR flash devices.  (Note: The
-         "jedec,spi-nor" kernel driver was formerly known as "m25p80".)
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/irs1125-overlay.dts
-@@ -0,0 +1,97 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+// Definitions for IRS1125 camera module on VC I2C bus
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&i2c_vc>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      irs1125: irs1125@3D {
-+                              compatible = "infineon,irs1125";
-+                              reg = <0x3D>;
-+                              status = "okay";
-+
-+                              pwdn-gpios = <&gpio 5 0>;
-+                              clocks = <&irs1125_clk>;
-+
-+                              irs1125_clk: camera-clk {
-+                                      compatible = "fixed-clock";
-+                                      #clock-cells = <0>;
-+                                      clock-frequency = <26000000>;
-+                              };
-+
-+                              port {
-+                                      irs1125_0: endpoint {
-+                                              remote-endpoint = <&csi1_ep>;
-+                                              clock-lanes = <0>;
-+                                              data-lanes = <1 2>;
-+                                              clock-noncontinuous;
-+                                              link-frequencies =
-+                                                      /bits/ 64 <297000000>;
-+                                      };
-+                              };
-+                      };
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&csi1>;
-+              __overlay__ {
-+                      status = "okay";
-+
-+                      port {
-+                              csi1_ep: endpoint {
-+                                      remote-endpoint = <&irs1125_0>;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&i2c0_pins>;
-+              __dormant__ {
-+                      brcm,pins = <28 29>;
-+                      brcm,function = <4>; /* alt0 */
-+              };
-+      };
-+      fragment@3 {
-+              target = <&i2c0_pins>;
-+              __overlay__ {
-+                      brcm,pins = <44 45>;
-+                      brcm,function = <5>; /* alt1 */
-+              };
-+      };
-+      fragment@4 {
-+              target = <&i2c0_pins>;
-+              __dormant__ {
-+                      brcm,pins = <0 1>;
-+                      brcm,function = <4>; /* alt0 */
-+              };
-+      };
-+      fragment@5 {
-+              target = <&i2c_vc>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@6 {
-+              target-path="/__overrides__";
-+              __overlay__ {
-+                      cam0-pwdn-ctrl = <&irs1125>,"pwdn-gpios:0";
-+                      cam0-pwdn      = <&irs1125>,"pwdn-gpios:4";
-+              };
-+      };
-+
-+      __overrides__ {
-+              i2c_pins_0_1 = <0>,"-2-3+4";
-+              i2c_pins_28_29 = <0>,"+2-3-4";
-+      };
-+};
diff --git a/target/linux/brcm2708/patches-4.19/950-0741-dts-bcm2838-Disable-DWC-OTG-block-by-default.patch b/target/linux/brcm2708/patches-4.19/950-0741-dts-bcm2838-Disable-DWC-OTG-block-by-default.patch
new file mode 100644 (file)
index 0000000..83cd339
--- /dev/null
@@ -0,0 +1,23 @@
+From 2e3db17d59143bfaf15423feb7eed68893e04f66 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 24 Oct 2019 14:31:00 +0100
+Subject: [PATCH] dts: bcm2838: Disable DWC OTG block by default
+
+Turning off the OTG USB block saves power. Since it requires the use of
+the dwc2 overlay to make use of it, we can disable it by default.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -647,6 +647,7 @@
+ &usb {
+       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
++      status = "disabled";
+ };
+ &hdmi {
diff --git a/target/linux/brcm2708/patches-4.19/950-0742-rpi-wm8804-soundcard-Fixed-MCLKDIV-for-Allo-Digione.patch b/target/linux/brcm2708/patches-4.19/950-0742-rpi-wm8804-soundcard-Fixed-MCLKDIV-for-Allo-Digione.patch
deleted file mode 100644 (file)
index 952e266..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 09ad53f0267e4b5433c27c77b3945d584ac0a6ba Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 22 Oct 2019 08:47:29 +0100
-Subject: [PATCH] rpi-wm8804-soundcard: Fixed MCLKDIV for Allo Digione
-
-The Allo Digione board wants a fixed MCLKDIV of 256.
-
-See: https://github.com/raspberrypi/linux/issues/3296
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- sound/soc/bcm/rpi-wm8804-soundcard.c | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
---- a/sound/soc/bcm/rpi-wm8804-soundcard.c
-+++ b/sound/soc/bcm/rpi-wm8804-soundcard.c
-@@ -66,6 +66,11 @@ static struct gpio_desc *snd_clk44gpio;
- static struct gpio_desc *snd_clk48gpio;
- static int wm8804_samplerate = 0;
-+/* Forward declarations */
-+static struct snd_soc_dai_link snd_allo_digione_dai[];
-+static struct snd_soc_card snd_rpi_wm8804;
-+
-+
- #define CLK_44EN_RATE 22579200UL
- #define CLK_48EN_RATE 24576000UL
-@@ -90,11 +95,10 @@ static unsigned int snd_rpi_wm8804_enabl
- static void snd_rpi_wm8804_clk_cfg(unsigned int samplerate,
-               struct wm8804_clk_cfg *clk_cfg)
- {
--      clk_cfg->mclk_freq = 0;
--      clk_cfg->mclk_div = 1;
-       clk_cfg->sysclk_freq = 27000000;
--      if (samplerate <= 96000) {
-+      if (samplerate <= 96000 ||
-+          snd_rpi_wm8804.dai_link == snd_allo_digione_dai) {
-               clk_cfg->mclk_freq = samplerate * 256;
-               clk_cfg->mclk_div = WM8804_MCLKDIV_256FS;
-       } else {
diff --git a/target/linux/brcm2708/patches-4.19/950-0742-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch b/target/linux/brcm2708/patches-4.19/950-0742-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch
new file mode 100644 (file)
index 0000000..9c9a0bf
--- /dev/null
@@ -0,0 +1,98 @@
+From 9894906ad424f266853b61a6996b2da8b119c6e6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 13 Sep 2019 17:19:33 +0100
+Subject: [PATCH] staging:bcm2835-codec: Add support for
+ ENUM_FRAMESIZES
+
+Required for compliance testing for the encoder.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 48 +++++++++++++++++--
+ 1 file changed, 44 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
+@@ -496,9 +496,10 @@ struct bcm2835_codec_fmt *get_default_fo
+       return &dev->supported_fmts[capture ? 1 : 0].list[0];
+ }
+-static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
+-                                           struct bcm2835_codec_dev *dev,
+-                                           bool capture)
++static
++struct bcm2835_codec_fmt *find_format_pix_fmt(u32 pix_fmt,
++                                            struct bcm2835_codec_dev *dev,
++                                            bool capture)
+ {
+       struct bcm2835_codec_fmt *fmt;
+       unsigned int k;
+@@ -507,7 +508,7 @@ static struct bcm2835_codec_fmt *find_fo
+       for (k = 0; k < fmts->num_entries; k++) {
+               fmt = &fmts->list[k];
+-              if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
++              if (fmt->fourcc == pix_fmt)
+                       break;
+       }
+       if (k == fmts->num_entries)
+@@ -516,6 +517,14 @@ static struct bcm2835_codec_fmt *find_fo
+       return &fmts->list[k];
+ }
++static inline
++struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
++                                    struct bcm2835_codec_dev *dev,
++                                    bool capture)
++{
++      return find_format_pix_fmt(f->fmt.pix_mp.pixelformat, dev, capture);
++}
++
+ static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
+ {
+       return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
+@@ -1792,6 +1801,36 @@ static int vidioc_encoder_cmd(struct fil
+       return 0;
+ }
++static int vidioc_enum_framesizes(struct file *file, void *fh,
++                                struct v4l2_frmsizeenum *fsize)
++{
++      struct bcm2835_codec_fmt *fmt;
++
++      fmt = find_format_pix_fmt(fsize->pixel_format, file2ctx(file)->dev,
++                                true);
++      if (!fmt)
++              fmt = find_format_pix_fmt(fsize->pixel_format,
++                                        file2ctx(file)->dev,
++                                        false);
++
++      if (!fmt)
++              return -EINVAL;
++
++      if (fsize->index)
++              return -EINVAL;
++
++      fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
++
++      fsize->stepwise.min_width = MIN_W;
++      fsize->stepwise.max_width = MAX_W;
++      fsize->stepwise.step_width = 1;
++      fsize->stepwise.min_height = MIN_H;
++      fsize->stepwise.max_height = MAX_H;
++      fsize->stepwise.step_height = 1;
++
++      return 0;
++}
++
+ static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+@@ -1829,6 +1868,7 @@ static const struct v4l2_ioctl_ops bcm28
+       .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
+       .vidioc_encoder_cmd = vidioc_encoder_cmd,
+       .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
++      .vidioc_enum_framesizes = vidioc_enum_framesizes,
+ };
+ static int bcm2835_codec_set_ctrls(struct bcm2835_codec_ctx *ctx)
diff --git a/target/linux/brcm2708/patches-4.19/950-0743-dts-bcm2838-Disable-DWC-OTG-block-by-default.patch b/target/linux/brcm2708/patches-4.19/950-0743-dts-bcm2838-Disable-DWC-OTG-block-by-default.patch
deleted file mode 100644 (file)
index 83cd339..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 2e3db17d59143bfaf15423feb7eed68893e04f66 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 24 Oct 2019 14:31:00 +0100
-Subject: [PATCH] dts: bcm2838: Disable DWC OTG block by default
-
-Turning off the OTG USB block saves power. Since it requires the use of
-the dwc2 overlay to make use of it, we can disable it by default.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2838.dtsi | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -647,6 +647,7 @@
- &usb {
-       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
-+      status = "disabled";
- };
- &hdmi {
diff --git a/target/linux/brcm2708/patches-4.19/950-0743-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch b/target/linux/brcm2708/patches-4.19/950-0743-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch
new file mode 100644 (file)
index 0000000..1049a4d
--- /dev/null
@@ -0,0 +1,25 @@
+From 9783756bf18033f321161393814dc1dd99c1704a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 13 Sep 2019 17:22:08 +0100
+Subject: [PATCH] staging: bcm2835-codec: Correct buffer type check on
+ G_PARM
+
+The output queue buffer type is now OUTPUT_MPLANE.
+
+Fixes: 5e484a3 staging: bcm2835-codec: switch to multi-planar API
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../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
+@@ -1438,7 +1438,7 @@ static int vidioc_g_parm(struct file *fi
+ {
+       struct bcm2835_codec_ctx *ctx = file2ctx(file);
+-      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return -EINVAL;
+       parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
diff --git a/target/linux/brcm2708/patches-4.19/950-0744-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch b/target/linux/brcm2708/patches-4.19/950-0744-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch
deleted file mode 100644 (file)
index 9c9a0bf..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-From 9894906ad424f266853b61a6996b2da8b119c6e6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 13 Sep 2019 17:19:33 +0100
-Subject: [PATCH] staging:bcm2835-codec: Add support for
- ENUM_FRAMESIZES
-
-Required for compliance testing for the encoder.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c        | 48 +++++++++++++++++--
- 1 file changed, 44 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
-@@ -496,9 +496,10 @@ struct bcm2835_codec_fmt *get_default_fo
-       return &dev->supported_fmts[capture ? 1 : 0].list[0];
- }
--static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
--                                           struct bcm2835_codec_dev *dev,
--                                           bool capture)
-+static
-+struct bcm2835_codec_fmt *find_format_pix_fmt(u32 pix_fmt,
-+                                            struct bcm2835_codec_dev *dev,
-+                                            bool capture)
- {
-       struct bcm2835_codec_fmt *fmt;
-       unsigned int k;
-@@ -507,7 +508,7 @@ static struct bcm2835_codec_fmt *find_fo
-       for (k = 0; k < fmts->num_entries; k++) {
-               fmt = &fmts->list[k];
--              if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
-+              if (fmt->fourcc == pix_fmt)
-                       break;
-       }
-       if (k == fmts->num_entries)
-@@ -516,6 +517,14 @@ static struct bcm2835_codec_fmt *find_fo
-       return &fmts->list[k];
- }
-+static inline
-+struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
-+                                    struct bcm2835_codec_dev *dev,
-+                                    bool capture)
-+{
-+      return find_format_pix_fmt(f->fmt.pix_mp.pixelformat, dev, capture);
-+}
-+
- static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
- {
-       return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
-@@ -1792,6 +1801,36 @@ static int vidioc_encoder_cmd(struct fil
-       return 0;
- }
-+static int vidioc_enum_framesizes(struct file *file, void *fh,
-+                                struct v4l2_frmsizeenum *fsize)
-+{
-+      struct bcm2835_codec_fmt *fmt;
-+
-+      fmt = find_format_pix_fmt(fsize->pixel_format, file2ctx(file)->dev,
-+                                true);
-+      if (!fmt)
-+              fmt = find_format_pix_fmt(fsize->pixel_format,
-+                                        file2ctx(file)->dev,
-+                                        false);
-+
-+      if (!fmt)
-+              return -EINVAL;
-+
-+      if (fsize->index)
-+              return -EINVAL;
-+
-+      fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
-+
-+      fsize->stepwise.min_width = MIN_W;
-+      fsize->stepwise.max_width = MAX_W;
-+      fsize->stepwise.step_width = 1;
-+      fsize->stepwise.min_height = MIN_H;
-+      fsize->stepwise.max_height = MAX_H;
-+      fsize->stepwise.step_height = 1;
-+
-+      return 0;
-+}
-+
- static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
-       .vidioc_querycap        = vidioc_querycap,
-@@ -1829,6 +1868,7 @@ static const struct v4l2_ioctl_ops bcm28
-       .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
-       .vidioc_encoder_cmd = vidioc_encoder_cmd,
-       .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
-+      .vidioc_enum_framesizes = vidioc_enum_framesizes,
- };
- static int bcm2835_codec_set_ctrls(struct bcm2835_codec_ctx *ctx)
diff --git a/target/linux/brcm2708/patches-4.19/950-0744-staging-bcm2835-codec-Set-default-and-error-check-ti.patch b/target/linux/brcm2708/patches-4.19/950-0744-staging-bcm2835-codec-Set-default-and-error-check-ti.patch
new file mode 100644 (file)
index 0000000..896149f
--- /dev/null
@@ -0,0 +1,37 @@
+From 4d6c40ebfe10dd2fdc64bd7607e51275d5524e47 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 13 Sep 2019 17:23:26 +0100
+Subject: [PATCH] staging: bcm2835-codec: Set default and error check
+ timeperframe
+
+G_PARM default was invalid as 0/0, and the driver didn't check
+the value set in S_PARM wasn't 0/0.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c       | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1423,6 +1423,10 @@ static int vidioc_s_parm(struct file *fi
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return -EINVAL;
++      if (!parm->parm.output.timeperframe.denominator ||
++          !parm->parm.output.timeperframe.numerator)
++              return -EINVAL;
++
+       ctx->framerate_num =
+                       parm->parm.output.timeperframe.denominator;
+       ctx->framerate_denom =
+@@ -2390,6 +2394,9 @@ static int bcm2835_codec_open(struct fil
+       ctx->colorspace = V4L2_COLORSPACE_REC709;
+       ctx->bitrate = 10 * 1000 * 1000;
++      ctx->framerate_num = 30;
++      ctx->framerate_denom = 1;
++
+       /* Initialise V4L2 contexts */
+       v4l2_fh_init(&ctx->fh, video_devdata(file));
+       file->private_data = &ctx->fh;
diff --git a/target/linux/brcm2708/patches-4.19/950-0745-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch b/target/linux/brcm2708/patches-4.19/950-0745-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch
deleted file mode 100644 (file)
index 1049a4d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 9783756bf18033f321161393814dc1dd99c1704a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 13 Sep 2019 17:22:08 +0100
-Subject: [PATCH] staging: bcm2835-codec: Correct buffer type check on
- G_PARM
-
-The output queue buffer type is now OUTPUT_MPLANE.
-
-Fixes: 5e484a3 staging: bcm2835-codec: switch to multi-planar API
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../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
-@@ -1438,7 +1438,7 @@ static int vidioc_g_parm(struct file *fi
- {
-       struct bcm2835_codec_ctx *ctx = file2ctx(file);
--      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+      if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return -EINVAL;
-       parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
diff --git a/target/linux/brcm2708/patches-4.19/950-0745-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch b/target/linux/brcm2708/patches-4.19/950-0745-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch
new file mode 100644 (file)
index 0000000..20550d4
--- /dev/null
@@ -0,0 +1,30 @@
+From 4542b5d7b4e00b11dd37d93986b624c58b198765 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 7 Oct 2019 14:02:57 +0100
+Subject: [PATCH] staging: bcm2835-codec: Fix imbalance in
+ dma_buf_get/dma_buf_put
+
+When represented with a dmabuf buffer that had previously been
+imported, there was a call to dma_buf_get without a matching
+dma_buf_put. This left dmabufs in limbo after all users had
+supposedly released them.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -2112,6 +2112,11 @@ static int bcm2835_codec_buf_prepare(str
+                       }
+                       buf->mmal.dma_buf = dma_buf;
++              } else {
++                      /* We already have a reference count on the dmabuf, so
++                       * release the one we acquired above.
++                       */
++                      dma_buf_put(dma_buf);
+               }
+               ret = 0;
+               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0746-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch b/target/linux/brcm2708/patches-4.19/950-0746-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch
new file mode 100644 (file)
index 0000000..fbfcd74
--- /dev/null
@@ -0,0 +1,87 @@
+From ebb8a4e93e242311d319098ea56e4ef4d92c4d19 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Wed, 16 Oct 2019 14:49:23 +0100
+Subject: [PATCH] drm:vc4 Added calls for firmware display
+ blank/unblank
+
+Requires new display power mailbox call to be present.
+
+Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 25 ++++++++++++++++++++++
+ include/soc/bcm2835/raspberrypi-firmware.h |  2 +-
+ 2 files changed, 26 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -91,6 +91,12 @@ struct mailbox_blank_display {
+       u32 blank;
+ };
++struct mailbox_display_pwr {
++      struct rpi_firmware_property_tag_header tag1;
++      u32 display;
++      u32 state;
++};
++
+ struct mailbox_get_edid {
+       struct rpi_firmware_property_tag_header tag1;
+       u32 block;
+@@ -272,6 +278,7 @@ struct vc4_fkms_encoder {
+       struct drm_encoder base;
+       bool hdmi_monitor;
+       bool rgb_range_selectable;
++      int display_num;
+ };
+ static inline struct vc4_fkms_encoder *
+@@ -1613,13 +1620,29 @@ static const struct drm_encoder_funcs vc
+       .destroy = vc4_fkms_encoder_destroy,
+ };
++static void vc4_fkms_display_power(struct drm_encoder *encoder, bool power)
++{
++      struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
++      struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
++
++      struct mailbox_display_pwr pwr = {
++              .tag1 = {RPI_FIRMWARE_SET_DISPLAY_POWER, 8, 0, },
++              .display = vc4_encoder->display_num,
++              .state = power ? 1 : 0,
++      };
++
++      rpi_firmware_property_list(vc4->firmware, &pwr, sizeof(pwr));
++}
++
+ static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
+ {
++      vc4_fkms_display_power(encoder, true);
+       DRM_DEBUG_KMS("Encoder_enable\n");
+ }
+ static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
+ {
++      vc4_fkms_display_power(encoder, false);
+       DRM_DEBUG_KMS("Encoder_disable\n");
+ }
+@@ -1695,6 +1718,8 @@ static int vc4_fkms_create_screen(struct
+       if (!vc4_encoder)
+               return -ENOMEM;
+       vc4_crtc->encoder = &vc4_encoder->base;
++
++      vc4_encoder->display_num = display_ref;
+       vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ;
+       drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs,
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -155,7 +155,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
+       RPI_FIRMWARE_SET_TIMING =                             0x00048017,
+       RPI_FIRMWARE_GET_DISPLAY_CFG =                        0x00040018,
+-
++      RPI_FIRMWARE_SET_DISPLAY_POWER =                      0x00048019,
+       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
+       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0746-staging-bcm2835-codec-Set-default-and-error-check-ti.patch b/target/linux/brcm2708/patches-4.19/950-0746-staging-bcm2835-codec-Set-default-and-error-check-ti.patch
deleted file mode 100644 (file)
index 896149f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 4d6c40ebfe10dd2fdc64bd7607e51275d5524e47 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 13 Sep 2019 17:23:26 +0100
-Subject: [PATCH] staging: bcm2835-codec: Set default and error check
- timeperframe
-
-G_PARM default was invalid as 0/0, and the driver didn't check
-the value set in S_PARM wasn't 0/0.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c       | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1423,6 +1423,10 @@ static int vidioc_s_parm(struct file *fi
-       if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return -EINVAL;
-+      if (!parm->parm.output.timeperframe.denominator ||
-+          !parm->parm.output.timeperframe.numerator)
-+              return -EINVAL;
-+
-       ctx->framerate_num =
-                       parm->parm.output.timeperframe.denominator;
-       ctx->framerate_denom =
-@@ -2390,6 +2394,9 @@ static int bcm2835_codec_open(struct fil
-       ctx->colorspace = V4L2_COLORSPACE_REC709;
-       ctx->bitrate = 10 * 1000 * 1000;
-+      ctx->framerate_num = 30;
-+      ctx->framerate_denom = 1;
-+
-       /* Initialise V4L2 contexts */
-       v4l2_fh_init(&ctx->fh, video_devdata(file));
-       file->private_data = &ctx->fh;
diff --git a/target/linux/brcm2708/patches-4.19/950-0747-rpi-poe-fan-fix-def_pwm1-writes.patch b/target/linux/brcm2708/patches-4.19/950-0747-rpi-poe-fan-fix-def_pwm1-writes.patch
new file mode 100644 (file)
index 0000000..bf5975e
--- /dev/null
@@ -0,0 +1,21 @@
+From 633c64173636b2f6acebfddb3d2b69c92bbbcd07 Mon Sep 17 00:00:00 2001
+From: Serge Schneider <serge@raspberrypi.org>
+Date: Thu, 31 Oct 2019 13:37:16 +0000
+Subject: [PATCH] rpi-poe-fan: fix def_pwm1 writes
+
+Signed-off-by: Serge Schneider <serge@raspberrypi.org>
+---
+ drivers/hwmon/rpi-poe-fan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/hwmon/rpi-poe-fan.c
++++ b/drivers/hwmon/rpi-poe-fan.c
+@@ -110,7 +110,7 @@ static int  __set_def_pwm(struct rpi_poe
+       if (ctx->def_pwm_value == def_pwm)
+               goto exit_set_def_pwm_err;
+-      ret = write_reg(ctx->fw, POE_CUR_PWM, &def_pwm);
++      ret = write_reg(ctx->fw, POE_DEF_PWM, &def_pwm);
+       if (!ret)
+               ctx->def_pwm_value = def_pwm;
+ exit_set_def_pwm_err:
diff --git a/target/linux/brcm2708/patches-4.19/950-0747-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch b/target/linux/brcm2708/patches-4.19/950-0747-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch
deleted file mode 100644 (file)
index 20550d4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 4542b5d7b4e00b11dd37d93986b624c58b198765 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 7 Oct 2019 14:02:57 +0100
-Subject: [PATCH] staging: bcm2835-codec: Fix imbalance in
- dma_buf_get/dma_buf_put
-
-When represented with a dmabuf buffer that had previously been
-imported, there was a call to dma_buf_get without a matching
-dma_buf_put. This left dmabufs in limbo after all users had
-supposedly released them.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -2112,6 +2112,11 @@ static int bcm2835_codec_buf_prepare(str
-                       }
-                       buf->mmal.dma_buf = dma_buf;
-+              } else {
-+                      /* We already have a reference count on the dmabuf, so
-+                       * release the one we acquired above.
-+                       */
-+                      dma_buf_put(dma_buf);
-               }
-               ret = 0;
-               break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0748-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch b/target/linux/brcm2708/patches-4.19/950-0748-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch
deleted file mode 100644 (file)
index fbfcd74..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-From ebb8a4e93e242311d319098ea56e4ef4d92c4d19 Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Wed, 16 Oct 2019 14:49:23 +0100
-Subject: [PATCH] drm:vc4 Added calls for firmware display
- blank/unblank
-
-Requires new display power mailbox call to be present.
-
-Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 25 ++++++++++++++++++++++
- include/soc/bcm2835/raspberrypi-firmware.h |  2 +-
- 2 files changed, 26 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -91,6 +91,12 @@ struct mailbox_blank_display {
-       u32 blank;
- };
-+struct mailbox_display_pwr {
-+      struct rpi_firmware_property_tag_header tag1;
-+      u32 display;
-+      u32 state;
-+};
-+
- struct mailbox_get_edid {
-       struct rpi_firmware_property_tag_header tag1;
-       u32 block;
-@@ -272,6 +278,7 @@ struct vc4_fkms_encoder {
-       struct drm_encoder base;
-       bool hdmi_monitor;
-       bool rgb_range_selectable;
-+      int display_num;
- };
- static inline struct vc4_fkms_encoder *
-@@ -1613,13 +1620,29 @@ static const struct drm_encoder_funcs vc
-       .destroy = vc4_fkms_encoder_destroy,
- };
-+static void vc4_fkms_display_power(struct drm_encoder *encoder, bool power)
-+{
-+      struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
-+      struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
-+
-+      struct mailbox_display_pwr pwr = {
-+              .tag1 = {RPI_FIRMWARE_SET_DISPLAY_POWER, 8, 0, },
-+              .display = vc4_encoder->display_num,
-+              .state = power ? 1 : 0,
-+      };
-+
-+      rpi_firmware_property_list(vc4->firmware, &pwr, sizeof(pwr));
-+}
-+
- static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
- {
-+      vc4_fkms_display_power(encoder, true);
-       DRM_DEBUG_KMS("Encoder_enable\n");
- }
- static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
- {
-+      vc4_fkms_display_power(encoder, false);
-       DRM_DEBUG_KMS("Encoder_disable\n");
- }
-@@ -1695,6 +1718,8 @@ static int vc4_fkms_create_screen(struct
-       if (!vc4_encoder)
-               return -ENOMEM;
-       vc4_crtc->encoder = &vc4_encoder->base;
-+
-+      vc4_encoder->display_num = display_ref;
-       vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ;
-       drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs,
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -155,7 +155,7 @@ enum rpi_firmware_property_tag {
-       RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
-       RPI_FIRMWARE_SET_TIMING =                             0x00048017,
-       RPI_FIRMWARE_GET_DISPLAY_CFG =                        0x00040018,
--
-+      RPI_FIRMWARE_SET_DISPLAY_POWER =                      0x00048019,
-       RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
-       RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0748-net-phy-bcm54xx-Encode-link-speed-and-activity-into-.patch b/target/linux/brcm2708/patches-4.19/950-0748-net-phy-bcm54xx-Encode-link-speed-and-activity-into-.patch
new file mode 100644 (file)
index 0000000..9a5e29c
--- /dev/null
@@ -0,0 +1,67 @@
+From b1e290ec968186530ec59479adfba89d2cfe21c8 Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <olteanv@gmail.com>
+Date: Sun, 24 Mar 2019 00:18:46 +0200
+Subject: [PATCH] net: phy: bcm54xx: Encode link speed and activity
+ into LEDs
+
+Previously the green and amber LEDs on this quad PHY were solid, to
+indicate an encoding of the link speed (10/100/1000).
+
+This keeps the LEDs always on just as before, but now they flash on
+Rx/Tx activity.
+
+Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/broadcom.c | 13 +++++++++++++
+ include/linux/brcmphy.h    | 16 ++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -345,6 +345,19 @@ static int bcm54xx_config_init(struct ph
+       bcm54xx_phydsp_config(phydev);
++      /* Encode link speed into LED1 and LED3 pair (green/amber).
++       * Also flash these two LEDs on activity. This means configuring
++       * them for MULTICOLOR and encoding link/activity into them.
++       */
++      val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
++              BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
++      bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
++
++      val = BCM_LED_MULTICOLOR_IN_PHASE |
++              BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
++              BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
++      bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
++
+       return 0;
+ }
+--- a/include/linux/brcmphy.h
++++ b/include/linux/brcmphy.h
+@@ -148,6 +148,22 @@
+ #define BCM_LED_SRC_OFF               0xe     /* Tied high */
+ #define BCM_LED_SRC_ON                0xf     /* Tied low */
++/*
++ * Broadcom Multicolor LED configurations (expansion register 4)
++ */
++#define BCM_EXP_MULTICOLOR            (MII_BCM54XX_EXP_SEL_ER + 0x04)
++#define BCM_LED_MULTICOLOR_IN_PHASE   BIT(8)
++#define BCM_LED_MULTICOLOR_LINK_ACT   0x0
++#define BCM_LED_MULTICOLOR_SPEED      0x1
++#define BCM_LED_MULTICOLOR_ACT_FLASH  0x2
++#define BCM_LED_MULTICOLOR_FDX                0x3
++#define BCM_LED_MULTICOLOR_OFF                0x4
++#define BCM_LED_MULTICOLOR_ON         0x5
++#define BCM_LED_MULTICOLOR_ALT                0x6
++#define BCM_LED_MULTICOLOR_FLASH      0x7
++#define BCM_LED_MULTICOLOR_LINK               0x8
++#define BCM_LED_MULTICOLOR_ACT                0x9
++#define BCM_LED_MULTICOLOR_PROGRAM    0xa
+ /*
+  * BCM5482: Shadow registers
diff --git a/target/linux/brcm2708/patches-4.19/950-0749-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch b/target/linux/brcm2708/patches-4.19/950-0749-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch
new file mode 100644 (file)
index 0000000..1b92242
--- /dev/null
@@ -0,0 +1,119 @@
+From 2679834327b5b8db8a7b0c90b632b81c35f9e271 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Thu, 31 Oct 2019 14:39:44 +0000
+Subject: [PATCH] net:phy:2711 Allow ethernet LED mode to be set via
+ device tree
+
+Add device tree entries and code to allow the specification of
+the lighting modes for the LED's on the ethernet connector.
+
+Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  3 +++
+ arch/arm/boot/dts/bcm2838.dtsi        |  1 +
+ arch/arm/boot/dts/overlays/README     | 28 +++++++++++++++++++--------
+ drivers/net/phy/broadcom.c            |  9 +++++++--
+ 4 files changed, 31 insertions(+), 10 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -334,5 +334,8 @@
+               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";
+       };
+ };
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -380,6 +380,7 @@
+                                       /* No interrupts - use PHY_POLL */
+                                       max-speed = <1000>;
+                                       reg = <0x1>;
++                                      led-modes = <0x02 0x02>;
+                               };
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -102,26 +102,38 @@ Params:
+         eee                     Enable Energy Efficient Ethernet support for
+                                 compatible devices (default "on"). See also
+-                                "tx_lpi_timer".
++                                "tx_lpi_timer". Pi3B+ only.
+         eth_downshift_after     Set the number of auto-negotiation failures
+                                 after which the 1000Mbps modes are disabled.
+                                 Legal values are 2, 3, 4, 5 and 0, where
+-                                0 means never downshift (default 2).
++                                0 means never downshift (default 2). Pi3B+ only.
+-        eth_led0                Set mode of LED0 (usually orange) (default
+-                                "1"). The legal values are:
+-                                0=link/activity          1=link1000/activity
++        eth_led0                Set mode of LED0 (usually orange). The legal 
++                                values are:
++
++                                Pi3B+
++
++                                0=link/activity    1=link1000/activity (default)
+                                 2=link100/activity       3=link10/activity
+                                 4=link100/1000/activity  5=link10/1000/activity
+                                 6=link10/100/activity    14=off    15=on
+-        eth_led1                Set mode of LED1 (usually green) (default
+-                                "6"). See eth_led0 for legal values.
++                                Pi4
++
++                                0=Speed/Activity (default)       1=Speed
++                                2=Speed/Flash activity   3=FDX
++                                4=Off                    5=On
++                                6=Alt                    7=Speed/Flash
++                                8=Link                   9=Activity
++
++        eth_led1                Set mode of LED1 (usually green) (Pi3B+ default
++                                "6", Pi4 default "0"). See eth_led0 for legal
++                                values.
+         eth_max_speed           Set the maximum speed a link is allowed
+                                 to negotiate. Legal values are 10, 100 and
+-                                1000 (default 1000).
++                                1000 (default 1000). Pi3B+ only.
+         i2c_arm                 Set to "on" to enable the ARM's i2c interface
+                                 (default "off")
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -292,6 +292,9 @@ static void bcm54xx_adjust_rxrefclk(stru
+ static int bcm54xx_config_init(struct phy_device *phydev)
+ {
+       int reg, err, val;
++      u32 led_modes[] = {BCM_LED_MULTICOLOR_LINK_ACT,
++                         BCM_LED_MULTICOLOR_LINK_ACT};
++      struct device_node *np = phydev->mdio.dev.of_node;
+       reg = phy_read(phydev, MII_BCM54XX_ECR);
+       if (reg < 0)
+@@ -345,6 +348,8 @@ static int bcm54xx_config_init(struct ph
+       bcm54xx_phydsp_config(phydev);
++      of_property_read_u32_array(np, "led-modes", led_modes, 2);
++
+       /* Encode link speed into LED1 and LED3 pair (green/amber).
+        * Also flash these two LEDs on activity. This means configuring
+        * them for MULTICOLOR and encoding link/activity into them.
+@@ -354,8 +359,8 @@ static int bcm54xx_config_init(struct ph
+       bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
+       val = BCM_LED_MULTICOLOR_IN_PHASE |
+-              BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
+-              BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
++              BCM5482_SHD_LEDS1_LED1(led_modes[0]) |
++              BCM5482_SHD_LEDS1_LED3(led_modes[1]);
+       bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0749-rpi-poe-fan-fix-def_pwm1-writes.patch b/target/linux/brcm2708/patches-4.19/950-0749-rpi-poe-fan-fix-def_pwm1-writes.patch
deleted file mode 100644 (file)
index bf5975e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-From 633c64173636b2f6acebfddb3d2b69c92bbbcd07 Mon Sep 17 00:00:00 2001
-From: Serge Schneider <serge@raspberrypi.org>
-Date: Thu, 31 Oct 2019 13:37:16 +0000
-Subject: [PATCH] rpi-poe-fan: fix def_pwm1 writes
-
-Signed-off-by: Serge Schneider <serge@raspberrypi.org>
----
- drivers/hwmon/rpi-poe-fan.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/hwmon/rpi-poe-fan.c
-+++ b/drivers/hwmon/rpi-poe-fan.c
-@@ -110,7 +110,7 @@ static int  __set_def_pwm(struct rpi_poe
-       if (ctx->def_pwm_value == def_pwm)
-               goto exit_set_def_pwm_err;
--      ret = write_reg(ctx->fw, POE_CUR_PWM, &def_pwm);
-+      ret = write_reg(ctx->fw, POE_DEF_PWM, &def_pwm);
-       if (!ret)
-               ctx->def_pwm_value = def_pwm;
- exit_set_def_pwm_err:
diff --git a/target/linux/brcm2708/patches-4.19/950-0750-net-phy-bcm54xx-Encode-link-speed-and-activity-into-.patch b/target/linux/brcm2708/patches-4.19/950-0750-net-phy-bcm54xx-Encode-link-speed-and-activity-into-.patch
deleted file mode 100644 (file)
index 9a5e29c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From b1e290ec968186530ec59479adfba89d2cfe21c8 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <olteanv@gmail.com>
-Date: Sun, 24 Mar 2019 00:18:46 +0200
-Subject: [PATCH] net: phy: bcm54xx: Encode link speed and activity
- into LEDs
-
-Previously the green and amber LEDs on this quad PHY were solid, to
-indicate an encoding of the link speed (10/100/1000).
-
-This keeps the LEDs always on just as before, but now they flash on
-Rx/Tx activity.
-
-Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/phy/broadcom.c | 13 +++++++++++++
- include/linux/brcmphy.h    | 16 ++++++++++++++++
- 2 files changed, 29 insertions(+)
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -345,6 +345,19 @@ static int bcm54xx_config_init(struct ph
-       bcm54xx_phydsp_config(phydev);
-+      /* Encode link speed into LED1 and LED3 pair (green/amber).
-+       * Also flash these two LEDs on activity. This means configuring
-+       * them for MULTICOLOR and encoding link/activity into them.
-+       */
-+      val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
-+              BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
-+      bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
-+
-+      val = BCM_LED_MULTICOLOR_IN_PHASE |
-+              BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
-+              BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
-+      bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
-+
-       return 0;
- }
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -148,6 +148,22 @@
- #define BCM_LED_SRC_OFF               0xe     /* Tied high */
- #define BCM_LED_SRC_ON                0xf     /* Tied low */
-+/*
-+ * Broadcom Multicolor LED configurations (expansion register 4)
-+ */
-+#define BCM_EXP_MULTICOLOR            (MII_BCM54XX_EXP_SEL_ER + 0x04)
-+#define BCM_LED_MULTICOLOR_IN_PHASE   BIT(8)
-+#define BCM_LED_MULTICOLOR_LINK_ACT   0x0
-+#define BCM_LED_MULTICOLOR_SPEED      0x1
-+#define BCM_LED_MULTICOLOR_ACT_FLASH  0x2
-+#define BCM_LED_MULTICOLOR_FDX                0x3
-+#define BCM_LED_MULTICOLOR_OFF                0x4
-+#define BCM_LED_MULTICOLOR_ON         0x5
-+#define BCM_LED_MULTICOLOR_ALT                0x6
-+#define BCM_LED_MULTICOLOR_FLASH      0x7
-+#define BCM_LED_MULTICOLOR_LINK               0x8
-+#define BCM_LED_MULTICOLOR_ACT                0x9
-+#define BCM_LED_MULTICOLOR_PROGRAM    0xa
- /*
-  * BCM5482: Shadow registers
diff --git a/target/linux/brcm2708/patches-4.19/950-0750-overlays-smi-fix-typo-in-comment-3320.patch b/target/linux/brcm2708/patches-4.19/950-0750-overlays-smi-fix-typo-in-comment-3320.patch
new file mode 100644 (file)
index 0000000..6b388e0
--- /dev/null
@@ -0,0 +1,23 @@
+From f12c4ba9fd01e17bd79b461b203674e92dd253e9 Mon Sep 17 00:00:00 2001
+From: Pierre-jean Texier <texier.pj2@gmail.com>
+Date: Wed, 6 Nov 2019 10:00:43 +0100
+Subject: [PATCH] overlays: smi: fix typo in comment (#3320)
+
+5 represent alt1 function not alt0.
+
+Signed-off-by: Pierre-Jean Texier <pjtexier@koncepto.io>
+---
+ arch/arm/boot/dts/overlays/smi-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/smi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/smi-overlay.dts
+@@ -24,7 +24,7 @@
+                                  these are already used as ID_SD and ID_SC */
+                               brcm,pins = <2 3 4 5 6 7 8 9 10 11 12 13 14 15
+                                            16 17 18 19 20 21 22 23 24 25>;
+-                              /* Alt 0: SMI */
++                              /* Alt 1: SMI */
+                               brcm,function = <5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+                                                5 5 5 5 5 5 5 5 5>;
+                               /* /CS, /WE and /OE are pulled high, as they are
diff --git a/target/linux/brcm2708/patches-4.19/950-0751-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch b/target/linux/brcm2708/patches-4.19/950-0751-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch
deleted file mode 100644 (file)
index 1b92242..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-From 2679834327b5b8db8a7b0c90b632b81c35f9e271 Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Thu, 31 Oct 2019 14:39:44 +0000
-Subject: [PATCH] net:phy:2711 Allow ethernet LED mode to be set via
- device tree
-
-Add device tree entries and code to allow the specification of
-the lighting modes for the LED's on the ethernet connector.
-
-Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  3 +++
- arch/arm/boot/dts/bcm2838.dtsi        |  1 +
- arch/arm/boot/dts/overlays/README     | 28 +++++++++++++++++++--------
- drivers/net/phy/broadcom.c            |  9 +++++++--
- 4 files changed, 31 insertions(+), 10 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -334,5 +334,8 @@
-               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";
-       };
- };
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -380,6 +380,7 @@
-                                       /* No interrupts - use PHY_POLL */
-                                       max-speed = <1000>;
-                                       reg = <0x1>;
-+                                      led-modes = <0x02 0x02>;
-                               };
-                       };
-               };
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -102,26 +102,38 @@ Params:
-         eee                     Enable Energy Efficient Ethernet support for
-                                 compatible devices (default "on"). See also
--                                "tx_lpi_timer".
-+                                "tx_lpi_timer". Pi3B+ only.
-         eth_downshift_after     Set the number of auto-negotiation failures
-                                 after which the 1000Mbps modes are disabled.
-                                 Legal values are 2, 3, 4, 5 and 0, where
--                                0 means never downshift (default 2).
-+                                0 means never downshift (default 2). Pi3B+ only.
--        eth_led0                Set mode of LED0 (usually orange) (default
--                                "1"). The legal values are:
--                                0=link/activity          1=link1000/activity
-+        eth_led0                Set mode of LED0 (usually orange). The legal 
-+                                values are:
-+
-+                                Pi3B+
-+
-+                                0=link/activity    1=link1000/activity (default)
-                                 2=link100/activity       3=link10/activity
-                                 4=link100/1000/activity  5=link10/1000/activity
-                                 6=link10/100/activity    14=off    15=on
--        eth_led1                Set mode of LED1 (usually green) (default
--                                "6"). See eth_led0 for legal values.
-+                                Pi4
-+
-+                                0=Speed/Activity (default)       1=Speed
-+                                2=Speed/Flash activity   3=FDX
-+                                4=Off                    5=On
-+                                6=Alt                    7=Speed/Flash
-+                                8=Link                   9=Activity
-+
-+        eth_led1                Set mode of LED1 (usually green) (Pi3B+ default
-+                                "6", Pi4 default "0"). See eth_led0 for legal
-+                                values.
-         eth_max_speed           Set the maximum speed a link is allowed
-                                 to negotiate. Legal values are 10, 100 and
--                                1000 (default 1000).
-+                                1000 (default 1000). Pi3B+ only.
-         i2c_arm                 Set to "on" to enable the ARM's i2c interface
-                                 (default "off")
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -292,6 +292,9 @@ static void bcm54xx_adjust_rxrefclk(stru
- static int bcm54xx_config_init(struct phy_device *phydev)
- {
-       int reg, err, val;
-+      u32 led_modes[] = {BCM_LED_MULTICOLOR_LINK_ACT,
-+                         BCM_LED_MULTICOLOR_LINK_ACT};
-+      struct device_node *np = phydev->mdio.dev.of_node;
-       reg = phy_read(phydev, MII_BCM54XX_ECR);
-       if (reg < 0)
-@@ -345,6 +348,8 @@ static int bcm54xx_config_init(struct ph
-       bcm54xx_phydsp_config(phydev);
-+      of_property_read_u32_array(np, "led-modes", led_modes, 2);
-+
-       /* Encode link speed into LED1 and LED3 pair (green/amber).
-        * Also flash these two LEDs on activity. This means configuring
-        * them for MULTICOLOR and encoding link/activity into them.
-@@ -354,8 +359,8 @@ static int bcm54xx_config_init(struct ph
-       bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
-       val = BCM_LED_MULTICOLOR_IN_PHASE |
--              BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
--              BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
-+              BCM5482_SHD_LEDS1_LED1(led_modes[0]) |
-+              BCM5482_SHD_LEDS1_LED3(led_modes[1]);
-       bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0751-net-phy-2711-Change-the-default-ethernet-LED-actions.patch b/target/linux/brcm2708/patches-4.19/950-0751-net-phy-2711-Change-the-default-ethernet-LED-actions.patch
new file mode 100644 (file)
index 0000000..b00afcc
--- /dev/null
@@ -0,0 +1,33 @@
+From 7d9c69b325c94d59de94cb699a8314ba2c83ab1d Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Thu, 7 Nov 2019 14:59:59 +0000
+Subject: [PATCH] net:phy:2711 Change the default ethernet LED actions
+
+This should return default behaviour back to that of previous
+releases.
+---
+ drivers/net/phy/broadcom.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -293,7 +293,7 @@ static int bcm54xx_config_init(struct ph
+ {
+       int reg, err, val;
+       u32 led_modes[] = {BCM_LED_MULTICOLOR_LINK_ACT,
+-                         BCM_LED_MULTICOLOR_LINK_ACT};
++                         BCM_LED_MULTICOLOR_LINK};
+       struct device_node *np = phydev->mdio.dev.of_node;
+       reg = phy_read(phydev, MII_BCM54XX_ECR);
+@@ -350,10 +350,6 @@ static int bcm54xx_config_init(struct ph
+       of_property_read_u32_array(np, "led-modes", led_modes, 2);
+-      /* Encode link speed into LED1 and LED3 pair (green/amber).
+-       * Also flash these two LEDs on activity. This means configuring
+-       * them for MULTICOLOR and encoding link/activity into them.
+-       */
+       val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
+               BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
+       bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
diff --git a/target/linux/brcm2708/patches-4.19/950-0752-overlays-README-Remove-trailing-whitespace.patch b/target/linux/brcm2708/patches-4.19/950-0752-overlays-README-Remove-trailing-whitespace.patch
new file mode 100644 (file)
index 0000000..099c444
--- /dev/null
@@ -0,0 +1,21 @@
+From f5505e5d9fbfd11921c39cd55a433877d6d0d6e4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <pelwell@users.noreply.github.com>
+Date: Thu, 7 Nov 2019 15:24:32 +0000
+Subject: [PATCH] overlays: README: Remove trailing whitespace
+
+A stray space slipped through the net.
+---
+ 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
+@@ -109,7 +109,7 @@ Params:
+                                 Legal values are 2, 3, 4, 5 and 0, where
+                                 0 means never downshift (default 2). Pi3B+ only.
+-        eth_led0                Set mode of LED0 (usually orange). The legal 
++        eth_led0                Set mode of LED0 (usually orange). The legal
+                                 values are:
+                                 Pi3B+
diff --git a/target/linux/brcm2708/patches-4.19/950-0752-overlays-smi-fix-typo-in-comment-3320.patch b/target/linux/brcm2708/patches-4.19/950-0752-overlays-smi-fix-typo-in-comment-3320.patch
deleted file mode 100644 (file)
index 6b388e0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From f12c4ba9fd01e17bd79b461b203674e92dd253e9 Mon Sep 17 00:00:00 2001
-From: Pierre-jean Texier <texier.pj2@gmail.com>
-Date: Wed, 6 Nov 2019 10:00:43 +0100
-Subject: [PATCH] overlays: smi: fix typo in comment (#3320)
-
-5 represent alt1 function not alt0.
-
-Signed-off-by: Pierre-Jean Texier <pjtexier@koncepto.io>
----
- arch/arm/boot/dts/overlays/smi-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/smi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/smi-overlay.dts
-@@ -24,7 +24,7 @@
-                                  these are already used as ID_SD and ID_SC */
-                               brcm,pins = <2 3 4 5 6 7 8 9 10 11 12 13 14 15
-                                            16 17 18 19 20 21 22 23 24 25>;
--                              /* Alt 0: SMI */
-+                              /* Alt 1: SMI */
-                               brcm,function = <5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
-                                                5 5 5 5 5 5 5 5 5>;
-                               /* /CS, /WE and /OE are pulled high, as they are
diff --git a/target/linux/brcm2708/patches-4.19/950-0753-net-phy-2711-Change-the-default-ethernet-LED-actions.patch b/target/linux/brcm2708/patches-4.19/950-0753-net-phy-2711-Change-the-default-ethernet-LED-actions.patch
deleted file mode 100644 (file)
index b00afcc..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 7d9c69b325c94d59de94cb699a8314ba2c83ab1d Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Thu, 7 Nov 2019 14:59:59 +0000
-Subject: [PATCH] net:phy:2711 Change the default ethernet LED actions
-
-This should return default behaviour back to that of previous
-releases.
----
- drivers/net/phy/broadcom.c | 6 +-----
- 1 file changed, 1 insertion(+), 5 deletions(-)
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -293,7 +293,7 @@ static int bcm54xx_config_init(struct ph
- {
-       int reg, err, val;
-       u32 led_modes[] = {BCM_LED_MULTICOLOR_LINK_ACT,
--                         BCM_LED_MULTICOLOR_LINK_ACT};
-+                         BCM_LED_MULTICOLOR_LINK};
-       struct device_node *np = phydev->mdio.dev.of_node;
-       reg = phy_read(phydev, MII_BCM54XX_ECR);
-@@ -350,10 +350,6 @@ static int bcm54xx_config_init(struct ph
-       of_property_read_u32_array(np, "led-modes", led_modes, 2);
--      /* Encode link speed into LED1 and LED3 pair (green/amber).
--       * Also flash these two LEDs on activity. This means configuring
--       * them for MULTICOLOR and encoding link/activity into them.
--       */
-       val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
-               BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
-       bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
diff --git a/target/linux/brcm2708/patches-4.19/950-0753-overlays-Add-apds9960-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0753-overlays-Add-apds9960-overlay.patch
new file mode 100644 (file)
index 0000000..0848a23
--- /dev/null
@@ -0,0 +1,103 @@
+From c1e8593fd7fc6a8e7745a6c82c1c19a8fceee70f Mon Sep 17 00:00:00 2001
+From: Michael Kaplan <m.kaplan@evva.com>
+Date: Fri, 8 Nov 2019 10:35:57 +0100
+Subject: [PATCH] overlays: Add apds9960 overlay
+
+Add an overlay for the AVAGO APDS9960 digital proximity, ambient light, rgb and gesture sensor.
+Also update overlay README and Makefile.
+
+Signed-off-by: Michael Kaplan <m.kaplan@evva.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  8 +++
+ .../boot/dts/overlays/apds9960-overlay.dts    | 57 +++++++++++++++++++
+ 3 files changed, 66 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/apds9960-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -15,6 +15,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       allo-katana-dac-audio.dtbo \
+       allo-piano-dac-pcm512x-audio.dtbo \
+       allo-piano-dac-plus-pcm512x-audio.dtbo \
++      apds9960.dtbo \
+       applepi-dac.dtbo \
+       at86rf233.dtbo \
+       audioinjector-addons.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -441,6 +441,14 @@ Params: 24db_digital_gain       Allow ga
+                                 better voice quality. (default Off)
++Name:   apds9960
++Info:   Configures the AVAGO APDS9960 digital proximity, ambient light, RGB and
++        gesture sensor
++Load:   dtoverlay=apds9960,<param>=<val>
++Params: gpiopin                 GPIO used for INT (default 4)
++        noints                  Disable the interrupt GPIO line.
++
++
+ Name:   applepi-dac
+ Info:   Configures the Orchard Audio ApplePi-DAC audio card
+ Load:   dtoverlay=applepi-dac
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/apds9960-overlay.dts
+@@ -0,0 +1,57 @@
++// Definitions for APDS-9960 ambient light and gesture sensor
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c1>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&gpio>;
++              __overlay__ {
++                      apds9960_pins: apds9960_pins@39 {
++                              brcm,pins = <4>;
++                              brcm,function = <0>;
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      apds9960: apds@39 {
++                              compatible = "avago,apds9960";
++                              reg = <0x39>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&i2c1>;
++              __overlay__ {
++                      apds9960_irq: apds@39 {
++                              #interrupt-cells=<2>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <4 1>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              gpiopin = <&apds9960_pins>,"brcm,pins:0",
++                              <&apds9960_irq>,"interrupts:0";
++              noints = <0>,"!1!3";
++      };
++};
++
diff --git a/target/linux/brcm2708/patches-4.19/950-0754-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch b/target/linux/brcm2708/patches-4.19/950-0754-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch
new file mode 100644 (file)
index 0000000..e80205b
--- /dev/null
@@ -0,0 +1,27 @@
+From 49a4a7e355452ce4372c99b2219d7ff8ff613f3f Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Sun, 17 Nov 2019 16:20:24 +0000
+Subject: [PATCH] arm: dts: overlays: pitft35-resistive: add upstream
+ compatible
+
+The upstream hx8357d driver uses "adafruit,yx350hv15" for the compatible
+string explicitly for this screen config and not a hx8357d generic for
+the controller so add that in as well so it will work with an unmodified
+upstream kernel driver. We leave the downstream as the priority.
+
+Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
+---
+ arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
+@@ -49,7 +49,7 @@
+                       #size-cells = <0>;
+                       pitft: pitft@0{
+-                              compatible = "himax,hx8357d";
++                              compatible = "himax,hx8357d", "adafruit,yx350hv15";
+                               reg = <0>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pitft_pins>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0754-overlays-README-Remove-trailing-whitespace.patch b/target/linux/brcm2708/patches-4.19/950-0754-overlays-README-Remove-trailing-whitespace.patch
deleted file mode 100644 (file)
index 099c444..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-From f5505e5d9fbfd11921c39cd55a433877d6d0d6e4 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <pelwell@users.noreply.github.com>
-Date: Thu, 7 Nov 2019 15:24:32 +0000
-Subject: [PATCH] overlays: README: Remove trailing whitespace
-
-A stray space slipped through the net.
----
- 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
-@@ -109,7 +109,7 @@ Params:
-                                 Legal values are 2, 3, 4, 5 and 0, where
-                                 0 means never downshift (default 2). Pi3B+ only.
--        eth_led0                Set mode of LED0 (usually orange). The legal 
-+        eth_led0                Set mode of LED0 (usually orange). The legal
-                                 values are:
-                                 Pi3B+
diff --git a/target/linux/brcm2708/patches-4.19/950-0755-clk-bcm2835-Avoid-null-pointer-exception.patch b/target/linux/brcm2708/patches-4.19/950-0755-clk-bcm2835-Avoid-null-pointer-exception.patch
new file mode 100644 (file)
index 0000000..a0939d7
--- /dev/null
@@ -0,0 +1,29 @@
+From 5b8a217fe818bc038592b8a5284ba0c18948fabf Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 6 Aug 2019 15:23:14 +0100
+Subject: [PATCH] clk-bcm2835: Avoid null pointer exception
+
+clk_desc_array[BCM2835_PLLB] doesn't exist so we dereference null when iterating
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -2288,9 +2288,11 @@ static bool bcm2835_clk_is_claimed(const
+       int i;
+       for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) {
+-              const char *clk_name = *(const char **)(clk_desc_array[i].data);
+-              if (!strcmp(name, clk_name))
+-                  return bcm2835_clk_claimed[i];
++              if (clk_desc_array[i].data) {
++                      const char *clk_name = *(const char **)(clk_desc_array[i].data);
++                      if (!strcmp(name, clk_name))
++                              return bcm2835_clk_claimed[i];
++              }
+       }
+       return false;
diff --git a/target/linux/brcm2708/patches-4.19/950-0755-overlays-Add-apds9960-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0755-overlays-Add-apds9960-overlay.patch
deleted file mode 100644 (file)
index 0848a23..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-From c1e8593fd7fc6a8e7745a6c82c1c19a8fceee70f Mon Sep 17 00:00:00 2001
-From: Michael Kaplan <m.kaplan@evva.com>
-Date: Fri, 8 Nov 2019 10:35:57 +0100
-Subject: [PATCH] overlays: Add apds9960 overlay
-
-Add an overlay for the AVAGO APDS9960 digital proximity, ambient light, rgb and gesture sensor.
-Also update overlay README and Makefile.
-
-Signed-off-by: Michael Kaplan <m.kaplan@evva.com>
----
- arch/arm/boot/dts/overlays/Makefile           |  1 +
- arch/arm/boot/dts/overlays/README             |  8 +++
- .../boot/dts/overlays/apds9960-overlay.dts    | 57 +++++++++++++++++++
- 3 files changed, 66 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/apds9960-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -15,6 +15,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       allo-katana-dac-audio.dtbo \
-       allo-piano-dac-pcm512x-audio.dtbo \
-       allo-piano-dac-plus-pcm512x-audio.dtbo \
-+      apds9960.dtbo \
-       applepi-dac.dtbo \
-       at86rf233.dtbo \
-       audioinjector-addons.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -441,6 +441,14 @@ Params: 24db_digital_gain       Allow ga
-                                 better voice quality. (default Off)
-+Name:   apds9960
-+Info:   Configures the AVAGO APDS9960 digital proximity, ambient light, RGB and
-+        gesture sensor
-+Load:   dtoverlay=apds9960,<param>=<val>
-+Params: gpiopin                 GPIO used for INT (default 4)
-+        noints                  Disable the interrupt GPIO line.
-+
-+
- Name:   applepi-dac
- Info:   Configures the Orchard Audio ApplePi-DAC audio card
- Load:   dtoverlay=applepi-dac
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/apds9960-overlay.dts
-@@ -0,0 +1,57 @@
-+// Definitions for APDS-9960 ambient light and gesture sensor
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&gpio>;
-+              __overlay__ {
-+                      apds9960_pins: apds9960_pins@39 {
-+                              brcm,pins = <4>;
-+                              brcm,function = <0>;
-+                      };
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      apds9960: apds@39 {
-+                              compatible = "avago,apds9960";
-+                              reg = <0x39>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      apds9960_irq: apds@39 {
-+                              #interrupt-cells=<2>;
-+                              interrupt-parent = <&gpio>;
-+                              interrupts = <4 1>;
-+                      };
-+              };
-+      };
-+
-+      __overrides__ {
-+              gpiopin = <&apds9960_pins>,"brcm,pins:0",
-+                              <&apds9960_irq>,"interrupts:0";
-+              noints = <0>,"!1!3";
-+      };
-+};
-+
diff --git a/target/linux/brcm2708/patches-4.19/950-0756-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch b/target/linux/brcm2708/patches-4.19/950-0756-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch
deleted file mode 100644 (file)
index e80205b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 49a4a7e355452ce4372c99b2219d7ff8ff613f3f Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Sun, 17 Nov 2019 16:20:24 +0000
-Subject: [PATCH] arm: dts: overlays: pitft35-resistive: add upstream
- compatible
-
-The upstream hx8357d driver uses "adafruit,yx350hv15" for the compatible
-string explicitly for this screen config and not a hx8357d generic for
-the controller so add that in as well so it will work with an unmodified
-upstream kernel driver. We leave the downstream as the priority.
-
-Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
----
- arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
-@@ -49,7 +49,7 @@
-                       #size-cells = <0>;
-                       pitft: pitft@0{
--                              compatible = "himax,hx8357d";
-+                              compatible = "himax,hx8357d", "adafruit,yx350hv15";
-                               reg = <0>;
-                               pinctrl-names = "default";
-                               pinctrl-0 = <&pitft_pins>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0756-v3d_drv-Handle-missing-clock-more-gracefully.patch b/target/linux/brcm2708/patches-4.19/950-0756-v3d_drv-Handle-missing-clock-more-gracefully.patch
new file mode 100644 (file)
index 0000000..292773f
--- /dev/null
@@ -0,0 +1,25 @@
+From 9048bbff0eca6d74d41fa58875f31560381b3ca3 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Fri, 23 Aug 2019 16:34:38 +0100
+Subject: [PATCH] v3d_drv: Handle missing clock more gracefully
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -301,9 +301,9 @@ static int v3d_platform_drm_probe(struct
+       }
+       v3d->clk = devm_clk_get(dev, NULL);
+-      if (IS_ERR(v3d->clk)) {
+-              if (ret != -EPROBE_DEFER)
+-                      dev_err(dev, "Failed to get clock\n");
++      if (IS_ERR_OR_NULL(v3d->clk)) {
++              if (PTR_ERR(v3d->clk) != -EPROBE_DEFER)
++                      dev_err(dev, "Failed to get clock (%ld)\n", PTR_ERR(v3d->clk));
+               goto dev_free;
+       }
+       v3d->clk_up_rate = clk_get_rate(v3d->clk);
diff --git a/target/linux/brcm2708/patches-4.19/950-0757-clk-bcm2835-Avoid-null-pointer-exception.patch b/target/linux/brcm2708/patches-4.19/950-0757-clk-bcm2835-Avoid-null-pointer-exception.patch
deleted file mode 100644 (file)
index a0939d7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 5b8a217fe818bc038592b8a5284ba0c18948fabf Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 6 Aug 2019 15:23:14 +0100
-Subject: [PATCH] clk-bcm2835: Avoid null pointer exception
-
-clk_desc_array[BCM2835_PLLB] doesn't exist so we dereference null when iterating
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/clk/bcm/clk-bcm2835.c | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -2288,9 +2288,11 @@ static bool bcm2835_clk_is_claimed(const
-       int i;
-       for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) {
--              const char *clk_name = *(const char **)(clk_desc_array[i].data);
--              if (!strcmp(name, clk_name))
--                  return bcm2835_clk_claimed[i];
-+              if (clk_desc_array[i].data) {
-+                      const char *clk_name = *(const char **)(clk_desc_array[i].data);
-+                      if (!strcmp(name, clk_name))
-+                              return bcm2835_clk_claimed[i];
-+              }
-       }
-       return false;
diff --git a/target/linux/brcm2708/patches-4.19/950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch b/target/linux/brcm2708/patches-4.19/950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch
new file mode 100644 (file)
index 0000000..acdb00f
--- /dev/null
@@ -0,0 +1,197 @@
+From 84a8cbf64731568c0750137ec38091a46b81d502 Mon Sep 17 00:00:00 2001
+From: Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 4 Jan 2019 15:14:33 +0530
+Subject: [PATCH] cpufreq: scpi/scmi: Fix freeing of dynamic OPPs
+
+Commit 1690d8bb91e370ab772062b79bd434ce815c4729 upstream
+
+Since the commit 2a4eb7358aba "OPP: Don't remove dynamic OPPs from
+_dev_pm_opp_remove_table()", dynamically created OPP aren't
+automatically removed anymore by dev_pm_opp_cpumask_remove_table(). This
+affects the scpi and scmi cpufreq drivers which no longer free OPPs on
+failures or on invocations of the policy->exit() callback.
+
+Create a generic OPP helper dev_pm_opp_remove_all_dynamic() which can be
+called from these drivers instead of dev_pm_opp_cpumask_remove_table().
+
+In dev_pm_opp_remove_all_dynamic(), we need to make sure that the
+opp_list isn't getting accessed simultaneously from other parts of the
+OPP core while the helper is freeing dynamic OPPs, i.e. we can't drop
+the opp_table->lock while traversing through the OPP list. And to
+accomplish that, this patch also creates _opp_kref_release_unlocked()
+which can be called from this new helper with the opp_table lock already
+held.
+
+Cc: 4.20 <stable@vger.kernel.org> # v4.20
+Reported-by: Valentin Schneider <valentin.schneider@arm.com>
+Fixes: 2a4eb7358aba "OPP: Don't remove dynamic OPPs from _dev_pm_opp_remove_table()"
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Tested-by: Valentin Schneider <valentin.schneider@arm.com>
+Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/cpufreq/scmi-cpufreq.c |  4 +--
+ drivers/cpufreq/scpi-cpufreq.c |  4 +--
+ drivers/opp/core.c             | 63 +++++++++++++++++++++++++++++++---
+ include/linux/pm_opp.h         |  5 +++
+ 4 files changed, 67 insertions(+), 9 deletions(-)
+
+--- a/drivers/cpufreq/scmi-cpufreq.c
++++ b/drivers/cpufreq/scmi-cpufreq.c
+@@ -176,7 +176,7 @@ static int scmi_cpufreq_init(struct cpuf
+ out_free_priv:
+       kfree(priv);
+ out_free_opp:
+-      dev_pm_opp_cpumask_remove_table(policy->cpus);
++      dev_pm_opp_remove_all_dynamic(cpu_dev);
+       return ret;
+ }
+@@ -188,7 +188,7 @@ static int scmi_cpufreq_exit(struct cpuf
+       cpufreq_cooling_unregister(priv->cdev);
+       dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
+       kfree(priv);
+-      dev_pm_opp_cpumask_remove_table(policy->related_cpus);
++      dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
+       return 0;
+ }
+--- a/drivers/cpufreq/scpi-cpufreq.c
++++ b/drivers/cpufreq/scpi-cpufreq.c
+@@ -177,7 +177,7 @@ out_free_cpufreq_table:
+ out_free_priv:
+       kfree(priv);
+ out_free_opp:
+-      dev_pm_opp_cpumask_remove_table(policy->cpus);
++      dev_pm_opp_remove_all_dynamic(cpu_dev);
+       return ret;
+ }
+@@ -190,7 +190,7 @@ static int scpi_cpufreq_exit(struct cpuf
+       clk_put(priv->clk);
+       dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
+       kfree(priv);
+-      dev_pm_opp_cpumask_remove_table(policy->related_cpus);
++      dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
+       return 0;
+ }
+--- a/drivers/opp/core.c
++++ b/drivers/opp/core.c
+@@ -884,11 +884,9 @@ void _opp_free(struct dev_pm_opp *opp)
+       kfree(opp);
+ }
+-static void _opp_kref_release(struct kref *kref)
++static void _opp_kref_release(struct dev_pm_opp *opp,
++                            struct opp_table *opp_table)
+ {
+-      struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
+-      struct opp_table *opp_table = opp->opp_table;
+-
+       /*
+        * Notify the changes in the availability of the operable
+        * frequency/voltage list.
+@@ -897,7 +895,22 @@ static void _opp_kref_release(struct kre
+       opp_debug_remove_one(opp);
+       list_del(&opp->node);
+       kfree(opp);
++}
++
++static void _opp_kref_release_unlocked(struct kref *kref)
++{
++      struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
++      struct opp_table *opp_table = opp->opp_table;
++
++      _opp_kref_release(opp, opp_table);
++}
++static void _opp_kref_release_locked(struct kref *kref)
++{
++      struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
++      struct opp_table *opp_table = opp->opp_table;
++
++      _opp_kref_release(opp, opp_table);
+       mutex_unlock(&opp_table->lock);
+       dev_pm_opp_put_opp_table(opp_table);
+ }
+@@ -909,10 +922,16 @@ void dev_pm_opp_get(struct dev_pm_opp *o
+ void dev_pm_opp_put(struct dev_pm_opp *opp)
+ {
+-      kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock);
++      kref_put_mutex(&opp->kref, _opp_kref_release_locked,
++                     &opp->opp_table->lock);
+ }
+ EXPORT_SYMBOL_GPL(dev_pm_opp_put);
++static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp)
++{
++      kref_put(&opp->kref, _opp_kref_release_unlocked);
++}
++
+ /**
+  * dev_pm_opp_remove()  - Remove an OPP from OPP table
+  * @dev:      device for which we do this operation
+@@ -952,6 +971,40 @@ void dev_pm_opp_remove(struct device *de
+ }
+ EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
++/**
++ * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
++ * @dev:      device for which we do this operation
++ *
++ * This function removes all dynamically created OPPs from the opp table.
++ */
++void dev_pm_opp_remove_all_dynamic(struct device *dev)
++{
++      struct opp_table *opp_table;
++      struct dev_pm_opp *opp, *temp;
++      int count = 0;
++
++      opp_table = _find_opp_table(dev);
++      if (IS_ERR(opp_table))
++              return;
++
++      mutex_lock(&opp_table->lock);
++      list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) {
++              if (opp->dynamic) {
++                      dev_pm_opp_put_unlocked(opp);
++                      count++;
++              }
++      }
++      mutex_unlock(&opp_table->lock);
++
++      /* Drop the references taken by dev_pm_opp_add() */
++      while (count--)
++              dev_pm_opp_put_opp_table(opp_table);
++
++      /* Drop the reference taken by _find_opp_table() */
++      dev_pm_opp_put_opp_table(opp_table);
++}
++EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic);
++
+ struct dev_pm_opp *_opp_allocate(struct opp_table *table)
+ {
+       struct dev_pm_opp *opp;
+--- a/include/linux/pm_opp.h
++++ b/include/linux/pm_opp.h
+@@ -107,6 +107,7 @@ void dev_pm_opp_put(struct dev_pm_opp *o
+ int dev_pm_opp_add(struct device *dev, unsigned long freq,
+                  unsigned long u_volt);
+ void dev_pm_opp_remove(struct device *dev, unsigned long freq);
++void dev_pm_opp_remove_all_dynamic(struct device *dev);
+ int dev_pm_opp_enable(struct device *dev, unsigned long freq);
+@@ -208,6 +209,10 @@ static inline void dev_pm_opp_remove(str
+ {
+ }
++static inline void dev_pm_opp_remove_all_dynamic(struct device *dev)
++{
++}
++
+ static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
+ {
+       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0758-clk-bcm283x-add-driver-interfacing-with-Raspberry-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0758-clk-bcm283x-add-driver-interfacing-with-Raspberry-Pi.patch
new file mode 100644 (file)
index 0000000..53428fc
--- /dev/null
@@ -0,0 +1,349 @@
+From 35306211392a8c17ba6cde2a6b5d1beb61ca7d54 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 12 Jun 2019 20:24:54 +0200
+Subject: [PATCH] clk: bcm283x: add driver interfacing with Raspberry
+ Pi's firmware
+
+Commit 4e85e535e6cc6e8a96350e8ee684d0f22eb8629e upstream.
+
+Raspberry Pi's firmware offers an interface though which update it's
+clock's frequencies. This is specially useful in order to change the CPU
+clock (pllb_arm) which is 'owned' by the firmware and we're unable to
+scale using the register interface provided by clk-bcm2835.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/bcm/Kconfig           |   7 +
+ drivers/clk/bcm/Makefile          |   1 +
+ drivers/clk/bcm/clk-raspberrypi.c | 300 ++++++++++++++++++++++++++++++
+ 3 files changed, 308 insertions(+)
+ create mode 100644 drivers/clk/bcm/clk-raspberrypi.c
+
+--- a/drivers/clk/bcm/Kconfig
++++ b/drivers/clk/bcm/Kconfig
+@@ -63,3 +63,10 @@ config CLK_BCM_SR
+       default ARCH_BCM_IPROC
+       help
+         Enable common clock framework support for the Broadcom Stingray SoC
++
++config CLK_RASPBERRYPI
++      tristate "Raspberry Pi firmware based clock support"
++      depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
++      help
++        Enable common clock framework support for Raspberry Pi's firmware
++        dependent clocks
+--- a/drivers/clk/bcm/Makefile
++++ b/drivers/clk/bcm/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_CLK_BCM_KONA)     += clk-bcm216
+ obj-$(CONFIG_COMMON_CLK_IPROC)        += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
+ obj-$(CONFIG_ARCH_BCM2835)    += clk-bcm2835.o
+ obj-$(CONFIG_ARCH_BCM2835)    += clk-bcm2835-aux.o
++obj-$(CONFIG_CLK_RASPBERRYPI) += clk-raspberrypi.o
+ obj-$(CONFIG_ARCH_BCM_53573)  += clk-bcm53573-ilp.o
+ obj-$(CONFIG_CLK_BCM_CYGNUS)  += clk-cygnus.o
+ obj-$(CONFIG_CLK_BCM_HR2)     += clk-hr2.o
+--- /dev/null
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -0,0 +1,300 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Raspberry Pi driver for firmware controlled clocks
++ *
++ * Even though clk-bcm2835 provides an interface to the hardware registers for
++ * the system clocks we've had to factor out 'pllb' as the firmware 'owns' it.
++ * We're not allowed to change it directly as we might race with the
++ * over-temperature and under-voltage protections provided by the firmware.
++ *
++ * Copyright (C) 2019 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
++ */
++
++#include <linux/clkdev.h>
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <soc/bcm2835/raspberrypi-firmware.h>
++
++#define RPI_FIRMWARE_ARM_CLK_ID               0x00000003
++
++#define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
++#define RPI_FIRMWARE_STATE_WAIT_BIT   BIT(1)
++
++/*
++ * Even though the firmware interface alters 'pllb' the frequencies are
++ * provided as per 'pllb_arm'. We need to scale before passing them trough.
++ */
++#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE        2
++
++#define A2W_PLL_FRAC_BITS             20
++
++struct raspberrypi_clk {
++      struct device *dev;
++      struct rpi_firmware *firmware;
++
++      unsigned long min_rate;
++      unsigned long max_rate;
++
++      struct clk_hw pllb;
++      struct clk_hw *pllb_arm;
++      struct clk_lookup *pllb_arm_lookup;
++};
++
++/*
++ * Structure of the message passed to Raspberry Pi's firmware in order to
++ * change clock rates. The 'disable_turbo' option is only available to the ARM
++ * clock (pllb) which we enable by default as turbo mode will alter multiple
++ * clocks at once.
++ *
++ * Even though we're able to access the clock registers directly we're bound to
++ * use the firmware interface as the firmware ultimately takes care of
++ * mitigating overheating/undervoltage situations and we would be changing
++ * frequencies behind his back.
++ *
++ * For more information on the firmware interface check:
++ * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
++ */
++struct raspberrypi_firmware_prop {
++      __le32 id;
++      __le32 val;
++      __le32 disable_turbo;
++} __packed;
++
++static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
++                                    u32 clk, u32 *val)
++{
++      struct raspberrypi_firmware_prop msg = {
++              .id = cpu_to_le32(clk),
++              .val = cpu_to_le32(*val),
++              .disable_turbo = cpu_to_le32(1),
++      };
++      int ret;
++
++      ret = rpi_firmware_property(firmware, tag, &msg, sizeof(msg));
++      if (ret)
++              return ret;
++
++      *val = le32_to_cpu(msg.val);
++
++      return 0;
++}
++
++static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
++{
++      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
++                                                 pllb);
++      u32 val = 0;
++      int ret;
++
++      ret = raspberrypi_clock_property(rpi->firmware,
++                                       RPI_FIRMWARE_GET_CLOCK_STATE,
++                                       RPI_FIRMWARE_ARM_CLK_ID, &val);
++      if (ret)
++              return 0;
++
++      return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
++}
++
++
++static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
++                                               unsigned long parent_rate)
++{
++      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
++                                                 pllb);
++      u32 val = 0;
++      int ret;
++
++      ret = raspberrypi_clock_property(rpi->firmware,
++                                       RPI_FIRMWARE_GET_CLOCK_RATE,
++                                       RPI_FIRMWARE_ARM_CLK_ID,
++                                       &val);
++      if (ret)
++              return ret;
++
++      return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
++}
++
++static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
++                                     unsigned long parent_rate)
++{
++      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
++                                                 pllb);
++      u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
++      int ret;
++
++      ret = raspberrypi_clock_property(rpi->firmware,
++                                       RPI_FIRMWARE_SET_CLOCK_RATE,
++                                       RPI_FIRMWARE_ARM_CLK_ID,
++                                       &new_rate);
++      if (ret)
++              dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
++                                  clk_hw_get_name(hw), ret);
++
++      return ret;
++}
++
++/*
++ * 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)
++{
++      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
++                                                 pllb);
++      u64 div, final_rate;
++      u32 ndiv, fdiv;
++
++      /* We can't use req->rate directly as it would overflow */
++      final_rate = clamp(req->rate, rpi->min_rate, rpi->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_pll_is_on,
++      .recalc_rate = raspberrypi_fw_pll_get_rate,
++      .set_rate = raspberrypi_fw_pll_set_rate,
++      .determine_rate = raspberrypi_pll_determine_rate,
++};
++
++static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
++{
++      u32 min_rate = 0, max_rate = 0;
++      struct clk_init_data init;
++      int ret;
++
++      memset(&init, 0, sizeof(init));
++
++      /* 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,
++                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
++                                       RPI_FIRMWARE_ARM_CLK_ID,
++                                       &min_rate);
++      if (ret) {
++              dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
++                      init.name, ret);
++              return ret;
++      }
++
++      ret = raspberrypi_clock_property(rpi->firmware,
++                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
++                                       RPI_FIRMWARE_ARM_CLK_ID,
++                                       &max_rate);
++      if (ret) {
++              dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
++                      init.name, ret);
++              return ret;
++      }
++
++      if (!min_rate || !max_rate) {
++              dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
++                      min_rate, max_rate);
++              return -EINVAL;
++      }
++
++      dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
++               min_rate, max_rate);
++
++      rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
++      rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
++
++      rpi->pllb.init = &init;
++
++      return devm_clk_hw_register(rpi->dev, &rpi->pllb);
++}
++
++static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
++{
++      rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev,
++                              "pllb_arm", "pllb",
++                              CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
++                              1, 2);
++      if (IS_ERR(rpi->pllb_arm)) {
++              dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
++              return PTR_ERR(rpi->pllb_arm);
++      }
++
++      rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0");
++      if (!rpi->pllb_arm_lookup) {
++              dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
++              clk_hw_unregister_fixed_factor(rpi->pllb_arm);
++              return -ENOMEM;
++      }
++
++      return 0;
++}
++
++static int raspberrypi_clk_probe(struct platform_device *pdev)
++{
++      struct device_node *firmware_node;
++      struct device *dev = &pdev->dev;
++      struct rpi_firmware *firmware;
++      struct raspberrypi_clk *rpi;
++      int ret;
++
++      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;
++
++      rpi = devm_kzalloc(dev, sizeof(*rpi), GFP_KERNEL);
++      if (!rpi)
++              return -ENOMEM;
++
++      rpi->dev = dev;
++      rpi->firmware = firmware;
++
++      ret = raspberrypi_register_pllb(rpi);
++      if (ret) {
++              dev_err(dev, "Failed to initialize pllb, %d\n", ret);
++              return ret;
++      }
++
++      ret = raspberrypi_register_pllb_arm(rpi);
++      if (ret)
++              return ret;
++
++      return 0;
++}
++
++static struct platform_driver raspberrypi_clk_driver = {
++      .driver = {
++              .name = "raspberrypi-clk",
++      },
++      .probe          = raspberrypi_clk_probe,
++};
++module_platform_driver(raspberrypi_clk_driver);
++
++MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
++MODULE_DESCRIPTION("Raspberry Pi firmware clock driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:raspberrypi-clk");
diff --git a/target/linux/brcm2708/patches-4.19/950-0758-v3d_drv-Handle-missing-clock-more-gracefully.patch b/target/linux/brcm2708/patches-4.19/950-0758-v3d_drv-Handle-missing-clock-more-gracefully.patch
deleted file mode 100644 (file)
index 292773f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 9048bbff0eca6d74d41fa58875f31560381b3ca3 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Fri, 23 Aug 2019 16:34:38 +0100
-Subject: [PATCH] v3d_drv: Handle missing clock more gracefully
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -301,9 +301,9 @@ static int v3d_platform_drm_probe(struct
-       }
-       v3d->clk = devm_clk_get(dev, NULL);
--      if (IS_ERR(v3d->clk)) {
--              if (ret != -EPROBE_DEFER)
--                      dev_err(dev, "Failed to get clock\n");
-+      if (IS_ERR_OR_NULL(v3d->clk)) {
-+              if (PTR_ERR(v3d->clk) != -EPROBE_DEFER)
-+                      dev_err(dev, "Failed to get clock (%ld)\n", PTR_ERR(v3d->clk));
-               goto dev_free;
-       }
-       v3d->clk_up_rate = clk_get_rate(v3d->clk);
diff --git a/target/linux/brcm2708/patches-4.19/950-0759-cpufreq-add-driver-for-Raspberry-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0759-cpufreq-add-driver-for-Raspberry-Pi.patch
new file mode 100644 (file)
index 0000000..7785caf
--- /dev/null
@@ -0,0 +1,161 @@
+From 1c0d3626312369837bc18051ed6c9611323fce87 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 12 Jun 2019 20:24:56 +0200
+Subject: [PATCH] cpufreq: add driver for Raspberry Pi
+
+Commit d3df18a97e586702920337056540267807b23f8e upstream.
+
+Raspberry Pi's firmware offers and interface though which update it's
+performance requirements. It allows us to request for specific runtime
+frequencies, which the firmware might or might not respect, depending on
+the firmware configuration and thermals.
+
+As the maximum and minimum frequencies are configurable in the firmware
+there is no way to know in advance their values. So the Raspberry Pi
+cpufreq driver queries them, builds an opp frequency table to then
+launch cpufreq-dt.
+
+Also, as the firmware interface might be configured as a module, making
+the cpu clock unavailable during init, this implements a full fledged
+driver, as opposed to most drivers registering cpufreq-dt, which only
+make use of an init routine.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Stephen Boyd <sboyd@kernel.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+---
+ drivers/cpufreq/Kconfig.arm           |  8 +++
+ drivers/cpufreq/Makefile              |  1 +
+ drivers/cpufreq/raspberrypi-cpufreq.c | 97 +++++++++++++++++++++++++++
+ 3 files changed, 106 insertions(+)
+ create mode 100644 drivers/cpufreq/raspberrypi-cpufreq.c
+
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -121,6 +121,14 @@ config ARM_QCOM_CPUFREQ_KRYO
+         If in doubt, say N.
++config ARM_RASPBERRYPI_CPUFREQ
++      tristate "Raspberry Pi cpufreq support"
++      depends on CLK_RASPBERRYPI || COMPILE_TEST
++      help
++        This adds the CPUFreq driver for Raspberry Pi
++
++        If in doubt, say N.
++
+ config ARM_S3C_CPUFREQ
+       bool
+       help
+--- a/drivers/cpufreq/Makefile
++++ b/drivers/cpufreq/Makefile
+@@ -65,6 +65,7 @@ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)  += o
+ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)      += pxa2xx-cpufreq.o
+ obj-$(CONFIG_PXA3xx)                  += pxa3xx-cpufreq.o
+ obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)   += qcom-cpufreq-kryo.o
++obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ)         += raspberrypi-cpufreq.o
+ obj-$(CONFIG_ARM_S3C2410_CPUFREQ)     += s3c2410-cpufreq.o
+ obj-$(CONFIG_ARM_S3C2412_CPUFREQ)     += s3c2412-cpufreq.o
+ obj-$(CONFIG_ARM_S3C2416_CPUFREQ)     += s3c2416-cpufreq.o
+--- /dev/null
++++ b/drivers/cpufreq/raspberrypi-cpufreq.c
+@@ -0,0 +1,97 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Raspberry Pi cpufreq driver
++ *
++ * Copyright (C) 2019, Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
++ */
++
++#include <linux/clk.h>
++#include <linux/cpu.h>
++#include <linux/cpufreq.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm_opp.h>
++
++#define RASPBERRYPI_FREQ_INTERVAL     100000000
++
++static struct platform_device *cpufreq_dt;
++
++static int raspberrypi_cpufreq_probe(struct platform_device *pdev)
++{
++      struct device *cpu_dev;
++      unsigned long min, max;
++      unsigned long rate;
++      struct clk *clk;
++      int ret;
++
++      cpu_dev = get_cpu_device(0);
++      if (!cpu_dev) {
++              pr_err("Cannot get CPU for cpufreq driver\n");
++              return -ENODEV;
++      }
++
++      clk = clk_get(cpu_dev, NULL);
++      if (IS_ERR(clk)) {
++              dev_err(cpu_dev, "Cannot get clock for CPU0\n");
++              return PTR_ERR(clk);
++      }
++
++      /*
++       * The max and min frequencies are configurable in the Raspberry Pi
++       * firmware, so we query them at runtime.
++       */
++      min = roundup(clk_round_rate(clk, 0), RASPBERRYPI_FREQ_INTERVAL);
++      max = roundup(clk_round_rate(clk, ULONG_MAX), RASPBERRYPI_FREQ_INTERVAL);
++      clk_put(clk);
++
++      for (rate = min; rate <= max; rate += RASPBERRYPI_FREQ_INTERVAL) {
++              ret = dev_pm_opp_add(cpu_dev, rate, 0);
++              if (ret)
++                      goto remove_opp;
++      }
++
++      cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
++      ret = PTR_ERR_OR_ZERO(cpufreq_dt);
++      if (ret) {
++              dev_err(cpu_dev, "Failed to create platform device, %d\n", ret);
++              goto remove_opp;
++      }
++
++      return 0;
++
++remove_opp:
++      dev_pm_opp_remove_all_dynamic(cpu_dev);
++
++      return ret;
++}
++
++static int raspberrypi_cpufreq_remove(struct platform_device *pdev)
++{
++      struct device *cpu_dev;
++
++      cpu_dev = get_cpu_device(0);
++      if (cpu_dev)
++              dev_pm_opp_remove_all_dynamic(cpu_dev);
++
++      platform_device_unregister(cpufreq_dt);
++
++      return 0;
++}
++
++/*
++ * Since the driver depends on clk-raspberrypi, which may return EPROBE_DEFER,
++ * all the activity is performed in the probe, which may be defered as well.
++ */
++static struct platform_driver raspberrypi_cpufreq_driver = {
++      .driver = {
++              .name = "raspberrypi-cpufreq",
++      },
++      .probe          = raspberrypi_cpufreq_probe,
++      .remove         = raspberrypi_cpufreq_remove,
++};
++module_platform_driver(raspberrypi_cpufreq_driver);
++
++MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de");
++MODULE_DESCRIPTION("Raspberry Pi cpufreq driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:raspberrypi-cpufreq");
diff --git a/target/linux/brcm2708/patches-4.19/950-0759-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch b/target/linux/brcm2708/patches-4.19/950-0759-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch
deleted file mode 100644 (file)
index acdb00f..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-From 84a8cbf64731568c0750137ec38091a46b81d502 Mon Sep 17 00:00:00 2001
-From: Viresh Kumar <viresh.kumar@linaro.org>
-Date: Fri, 4 Jan 2019 15:14:33 +0530
-Subject: [PATCH] cpufreq: scpi/scmi: Fix freeing of dynamic OPPs
-
-Commit 1690d8bb91e370ab772062b79bd434ce815c4729 upstream
-
-Since the commit 2a4eb7358aba "OPP: Don't remove dynamic OPPs from
-_dev_pm_opp_remove_table()", dynamically created OPP aren't
-automatically removed anymore by dev_pm_opp_cpumask_remove_table(). This
-affects the scpi and scmi cpufreq drivers which no longer free OPPs on
-failures or on invocations of the policy->exit() callback.
-
-Create a generic OPP helper dev_pm_opp_remove_all_dynamic() which can be
-called from these drivers instead of dev_pm_opp_cpumask_remove_table().
-
-In dev_pm_opp_remove_all_dynamic(), we need to make sure that the
-opp_list isn't getting accessed simultaneously from other parts of the
-OPP core while the helper is freeing dynamic OPPs, i.e. we can't drop
-the opp_table->lock while traversing through the OPP list. And to
-accomplish that, this patch also creates _opp_kref_release_unlocked()
-which can be called from this new helper with the opp_table lock already
-held.
-
-Cc: 4.20 <stable@vger.kernel.org> # v4.20
-Reported-by: Valentin Schneider <valentin.schneider@arm.com>
-Fixes: 2a4eb7358aba "OPP: Don't remove dynamic OPPs from _dev_pm_opp_remove_table()"
-Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-Tested-by: Valentin Schneider <valentin.schneider@arm.com>
-Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
-Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
----
- drivers/cpufreq/scmi-cpufreq.c |  4 +--
- drivers/cpufreq/scpi-cpufreq.c |  4 +--
- drivers/opp/core.c             | 63 +++++++++++++++++++++++++++++++---
- include/linux/pm_opp.h         |  5 +++
- 4 files changed, 67 insertions(+), 9 deletions(-)
-
---- a/drivers/cpufreq/scmi-cpufreq.c
-+++ b/drivers/cpufreq/scmi-cpufreq.c
-@@ -176,7 +176,7 @@ static int scmi_cpufreq_init(struct cpuf
- out_free_priv:
-       kfree(priv);
- out_free_opp:
--      dev_pm_opp_cpumask_remove_table(policy->cpus);
-+      dev_pm_opp_remove_all_dynamic(cpu_dev);
-       return ret;
- }
-@@ -188,7 +188,7 @@ static int scmi_cpufreq_exit(struct cpuf
-       cpufreq_cooling_unregister(priv->cdev);
-       dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-       kfree(priv);
--      dev_pm_opp_cpumask_remove_table(policy->related_cpus);
-+      dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
-       return 0;
- }
---- a/drivers/cpufreq/scpi-cpufreq.c
-+++ b/drivers/cpufreq/scpi-cpufreq.c
-@@ -177,7 +177,7 @@ out_free_cpufreq_table:
- out_free_priv:
-       kfree(priv);
- out_free_opp:
--      dev_pm_opp_cpumask_remove_table(policy->cpus);
-+      dev_pm_opp_remove_all_dynamic(cpu_dev);
-       return ret;
- }
-@@ -190,7 +190,7 @@ static int scpi_cpufreq_exit(struct cpuf
-       clk_put(priv->clk);
-       dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-       kfree(priv);
--      dev_pm_opp_cpumask_remove_table(policy->related_cpus);
-+      dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
-       return 0;
- }
---- a/drivers/opp/core.c
-+++ b/drivers/opp/core.c
-@@ -884,11 +884,9 @@ void _opp_free(struct dev_pm_opp *opp)
-       kfree(opp);
- }
--static void _opp_kref_release(struct kref *kref)
-+static void _opp_kref_release(struct dev_pm_opp *opp,
-+                            struct opp_table *opp_table)
- {
--      struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
--      struct opp_table *opp_table = opp->opp_table;
--
-       /*
-        * Notify the changes in the availability of the operable
-        * frequency/voltage list.
-@@ -897,7 +895,22 @@ static void _opp_kref_release(struct kre
-       opp_debug_remove_one(opp);
-       list_del(&opp->node);
-       kfree(opp);
-+}
-+
-+static void _opp_kref_release_unlocked(struct kref *kref)
-+{
-+      struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
-+      struct opp_table *opp_table = opp->opp_table;
-+
-+      _opp_kref_release(opp, opp_table);
-+}
-+static void _opp_kref_release_locked(struct kref *kref)
-+{
-+      struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
-+      struct opp_table *opp_table = opp->opp_table;
-+
-+      _opp_kref_release(opp, opp_table);
-       mutex_unlock(&opp_table->lock);
-       dev_pm_opp_put_opp_table(opp_table);
- }
-@@ -909,10 +922,16 @@ void dev_pm_opp_get(struct dev_pm_opp *o
- void dev_pm_opp_put(struct dev_pm_opp *opp)
- {
--      kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock);
-+      kref_put_mutex(&opp->kref, _opp_kref_release_locked,
-+                     &opp->opp_table->lock);
- }
- EXPORT_SYMBOL_GPL(dev_pm_opp_put);
-+static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp)
-+{
-+      kref_put(&opp->kref, _opp_kref_release_unlocked);
-+}
-+
- /**
-  * dev_pm_opp_remove()  - Remove an OPP from OPP table
-  * @dev:      device for which we do this operation
-@@ -952,6 +971,40 @@ void dev_pm_opp_remove(struct device *de
- }
- EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
-+/**
-+ * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
-+ * @dev:      device for which we do this operation
-+ *
-+ * This function removes all dynamically created OPPs from the opp table.
-+ */
-+void dev_pm_opp_remove_all_dynamic(struct device *dev)
-+{
-+      struct opp_table *opp_table;
-+      struct dev_pm_opp *opp, *temp;
-+      int count = 0;
-+
-+      opp_table = _find_opp_table(dev);
-+      if (IS_ERR(opp_table))
-+              return;
-+
-+      mutex_lock(&opp_table->lock);
-+      list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) {
-+              if (opp->dynamic) {
-+                      dev_pm_opp_put_unlocked(opp);
-+                      count++;
-+              }
-+      }
-+      mutex_unlock(&opp_table->lock);
-+
-+      /* Drop the references taken by dev_pm_opp_add() */
-+      while (count--)
-+              dev_pm_opp_put_opp_table(opp_table);
-+
-+      /* Drop the reference taken by _find_opp_table() */
-+      dev_pm_opp_put_opp_table(opp_table);
-+}
-+EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic);
-+
- struct dev_pm_opp *_opp_allocate(struct opp_table *table)
- {
-       struct dev_pm_opp *opp;
---- a/include/linux/pm_opp.h
-+++ b/include/linux/pm_opp.h
-@@ -107,6 +107,7 @@ void dev_pm_opp_put(struct dev_pm_opp *o
- int dev_pm_opp_add(struct device *dev, unsigned long freq,
-                  unsigned long u_volt);
- void dev_pm_opp_remove(struct device *dev, unsigned long freq);
-+void dev_pm_opp_remove_all_dynamic(struct device *dev);
- int dev_pm_opp_enable(struct device *dev, unsigned long freq);
-@@ -208,6 +209,10 @@ static inline void dev_pm_opp_remove(str
- {
- }
-+static inline void dev_pm_opp_remove_all_dynamic(struct device *dev)
-+{
-+}
-+
- static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
- {
-       return 0;
diff --git a/target/linux/brcm2708/patches-4.19/950-0760-clk-bcm283x-add-driver-interfacing-with-Raspberry-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0760-clk-bcm283x-add-driver-interfacing-with-Raspberry-Pi.patch
deleted file mode 100644 (file)
index 53428fc..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-From 35306211392a8c17ba6cde2a6b5d1beb61ca7d54 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 12 Jun 2019 20:24:54 +0200
-Subject: [PATCH] clk: bcm283x: add driver interfacing with Raspberry
- Pi's firmware
-
-Commit 4e85e535e6cc6e8a96350e8ee684d0f22eb8629e upstream.
-
-Raspberry Pi's firmware offers an interface though which update it's
-clock's frequencies. This is specially useful in order to change the CPU
-clock (pllb_arm) which is 'owned' by the firmware and we're unable to
-scale using the register interface provided by clk-bcm2835.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Stephen Boyd <sboyd@kernel.org>
----
- drivers/clk/bcm/Kconfig           |   7 +
- drivers/clk/bcm/Makefile          |   1 +
- drivers/clk/bcm/clk-raspberrypi.c | 300 ++++++++++++++++++++++++++++++
- 3 files changed, 308 insertions(+)
- create mode 100644 drivers/clk/bcm/clk-raspberrypi.c
-
---- a/drivers/clk/bcm/Kconfig
-+++ b/drivers/clk/bcm/Kconfig
-@@ -63,3 +63,10 @@ config CLK_BCM_SR
-       default ARCH_BCM_IPROC
-       help
-         Enable common clock framework support for the Broadcom Stingray SoC
-+
-+config CLK_RASPBERRYPI
-+      tristate "Raspberry Pi firmware based clock support"
-+      depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
-+      help
-+        Enable common clock framework support for Raspberry Pi's firmware
-+        dependent clocks
---- a/drivers/clk/bcm/Makefile
-+++ b/drivers/clk/bcm/Makefile
-@@ -7,6 +7,7 @@ obj-$(CONFIG_CLK_BCM_KONA)     += clk-bcm216
- obj-$(CONFIG_COMMON_CLK_IPROC)        += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
- obj-$(CONFIG_ARCH_BCM2835)    += clk-bcm2835.o
- obj-$(CONFIG_ARCH_BCM2835)    += clk-bcm2835-aux.o
-+obj-$(CONFIG_CLK_RASPBERRYPI) += clk-raspberrypi.o
- obj-$(CONFIG_ARCH_BCM_53573)  += clk-bcm53573-ilp.o
- obj-$(CONFIG_CLK_BCM_CYGNUS)  += clk-cygnus.o
- obj-$(CONFIG_CLK_BCM_HR2)     += clk-hr2.o
---- /dev/null
-+++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -0,0 +1,300 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * Raspberry Pi driver for firmware controlled clocks
-+ *
-+ * Even though clk-bcm2835 provides an interface to the hardware registers for
-+ * the system clocks we've had to factor out 'pllb' as the firmware 'owns' it.
-+ * We're not allowed to change it directly as we might race with the
-+ * over-temperature and under-voltage protections provided by the firmware.
-+ *
-+ * Copyright (C) 2019 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-+ */
-+
-+#include <linux/clkdev.h>
-+#include <linux/clk-provider.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+
-+#include <soc/bcm2835/raspberrypi-firmware.h>
-+
-+#define RPI_FIRMWARE_ARM_CLK_ID               0x00000003
-+
-+#define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
-+#define RPI_FIRMWARE_STATE_WAIT_BIT   BIT(1)
-+
-+/*
-+ * Even though the firmware interface alters 'pllb' the frequencies are
-+ * provided as per 'pllb_arm'. We need to scale before passing them trough.
-+ */
-+#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE        2
-+
-+#define A2W_PLL_FRAC_BITS             20
-+
-+struct raspberrypi_clk {
-+      struct device *dev;
-+      struct rpi_firmware *firmware;
-+
-+      unsigned long min_rate;
-+      unsigned long max_rate;
-+
-+      struct clk_hw pllb;
-+      struct clk_hw *pllb_arm;
-+      struct clk_lookup *pllb_arm_lookup;
-+};
-+
-+/*
-+ * Structure of the message passed to Raspberry Pi's firmware in order to
-+ * change clock rates. The 'disable_turbo' option is only available to the ARM
-+ * clock (pllb) which we enable by default as turbo mode will alter multiple
-+ * clocks at once.
-+ *
-+ * Even though we're able to access the clock registers directly we're bound to
-+ * use the firmware interface as the firmware ultimately takes care of
-+ * mitigating overheating/undervoltage situations and we would be changing
-+ * frequencies behind his back.
-+ *
-+ * For more information on the firmware interface check:
-+ * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
-+ */
-+struct raspberrypi_firmware_prop {
-+      __le32 id;
-+      __le32 val;
-+      __le32 disable_turbo;
-+} __packed;
-+
-+static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
-+                                    u32 clk, u32 *val)
-+{
-+      struct raspberrypi_firmware_prop msg = {
-+              .id = cpu_to_le32(clk),
-+              .val = cpu_to_le32(*val),
-+              .disable_turbo = cpu_to_le32(1),
-+      };
-+      int ret;
-+
-+      ret = rpi_firmware_property(firmware, tag, &msg, sizeof(msg));
-+      if (ret)
-+              return ret;
-+
-+      *val = le32_to_cpu(msg.val);
-+
-+      return 0;
-+}
-+
-+static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
-+{
-+      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-+                                                 pllb);
-+      u32 val = 0;
-+      int ret;
-+
-+      ret = raspberrypi_clock_property(rpi->firmware,
-+                                       RPI_FIRMWARE_GET_CLOCK_STATE,
-+                                       RPI_FIRMWARE_ARM_CLK_ID, &val);
-+      if (ret)
-+              return 0;
-+
-+      return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
-+}
-+
-+
-+static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
-+                                               unsigned long parent_rate)
-+{
-+      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-+                                                 pllb);
-+      u32 val = 0;
-+      int ret;
-+
-+      ret = raspberrypi_clock_property(rpi->firmware,
-+                                       RPI_FIRMWARE_GET_CLOCK_RATE,
-+                                       RPI_FIRMWARE_ARM_CLK_ID,
-+                                       &val);
-+      if (ret)
-+              return ret;
-+
-+      return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+}
-+
-+static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
-+                                     unsigned long parent_rate)
-+{
-+      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-+                                                 pllb);
-+      u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+      int ret;
-+
-+      ret = raspberrypi_clock_property(rpi->firmware,
-+                                       RPI_FIRMWARE_SET_CLOCK_RATE,
-+                                       RPI_FIRMWARE_ARM_CLK_ID,
-+                                       &new_rate);
-+      if (ret)
-+              dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
-+                                  clk_hw_get_name(hw), ret);
-+
-+      return ret;
-+}
-+
-+/*
-+ * 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)
-+{
-+      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-+                                                 pllb);
-+      u64 div, final_rate;
-+      u32 ndiv, fdiv;
-+
-+      /* We can't use req->rate directly as it would overflow */
-+      final_rate = clamp(req->rate, rpi->min_rate, rpi->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_pll_is_on,
-+      .recalc_rate = raspberrypi_fw_pll_get_rate,
-+      .set_rate = raspberrypi_fw_pll_set_rate,
-+      .determine_rate = raspberrypi_pll_determine_rate,
-+};
-+
-+static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
-+{
-+      u32 min_rate = 0, max_rate = 0;
-+      struct clk_init_data init;
-+      int ret;
-+
-+      memset(&init, 0, sizeof(init));
-+
-+      /* 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,
-+                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
-+                                       RPI_FIRMWARE_ARM_CLK_ID,
-+                                       &min_rate);
-+      if (ret) {
-+              dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
-+                      init.name, ret);
-+              return ret;
-+      }
-+
-+      ret = raspberrypi_clock_property(rpi->firmware,
-+                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
-+                                       RPI_FIRMWARE_ARM_CLK_ID,
-+                                       &max_rate);
-+      if (ret) {
-+              dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
-+                      init.name, ret);
-+              return ret;
-+      }
-+
-+      if (!min_rate || !max_rate) {
-+              dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
-+                      min_rate, max_rate);
-+              return -EINVAL;
-+      }
-+
-+      dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
-+               min_rate, max_rate);
-+
-+      rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+      rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+
-+      rpi->pllb.init = &init;
-+
-+      return devm_clk_hw_register(rpi->dev, &rpi->pllb);
-+}
-+
-+static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
-+{
-+      rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev,
-+                              "pllb_arm", "pllb",
-+                              CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
-+                              1, 2);
-+      if (IS_ERR(rpi->pllb_arm)) {
-+              dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
-+              return PTR_ERR(rpi->pllb_arm);
-+      }
-+
-+      rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0");
-+      if (!rpi->pllb_arm_lookup) {
-+              dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
-+              clk_hw_unregister_fixed_factor(rpi->pllb_arm);
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+
-+static int raspberrypi_clk_probe(struct platform_device *pdev)
-+{
-+      struct device_node *firmware_node;
-+      struct device *dev = &pdev->dev;
-+      struct rpi_firmware *firmware;
-+      struct raspberrypi_clk *rpi;
-+      int ret;
-+
-+      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;
-+
-+      rpi = devm_kzalloc(dev, sizeof(*rpi), GFP_KERNEL);
-+      if (!rpi)
-+              return -ENOMEM;
-+
-+      rpi->dev = dev;
-+      rpi->firmware = firmware;
-+
-+      ret = raspberrypi_register_pllb(rpi);
-+      if (ret) {
-+              dev_err(dev, "Failed to initialize pllb, %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = raspberrypi_register_pllb_arm(rpi);
-+      if (ret)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static struct platform_driver raspberrypi_clk_driver = {
-+      .driver = {
-+              .name = "raspberrypi-clk",
-+      },
-+      .probe          = raspberrypi_clk_probe,
-+};
-+module_platform_driver(raspberrypi_clk_driver);
-+
-+MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
-+MODULE_DESCRIPTION("Raspberry Pi firmware clock driver");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:raspberrypi-clk");
diff --git a/target/linux/brcm2708/patches-4.19/950-0760-firmware-raspberrypi-register-clk-device.patch b/target/linux/brcm2708/patches-4.19/950-0760-firmware-raspberrypi-register-clk-device.patch
new file mode 100644 (file)
index 0000000..2886ab1
--- /dev/null
@@ -0,0 +1,57 @@
+From e7f2fcf4bf0b0a227f564fcdde46f3bdd326c1b2 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 12 Jun 2019 20:24:55 +0200
+Subject: [PATCH] firmware: raspberrypi: register clk device
+
+Commit 91f2cf4a6b2131016b1ae9c9500245f0572112c7 upstream.
+
+Since clk-raspberrypi is tied to the VC4 firmware instead of particular
+hardware it's registration should be performed by the firmware driver.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/firmware/raspberrypi.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -24,6 +24,7 @@
+ #define MBOX_CHAN_PROPERTY            8
+ static struct platform_device *rpi_hwmon;
++static struct platform_device *rpi_clk;
+ struct rpi_firmware {
+       struct mbox_client cl;
+@@ -297,6 +298,12 @@ rpi_register_hwmon_driver(struct device
+       }
+ }
++static void rpi_register_clk_driver(struct device *dev)
++{
++      rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
++                                              -1, NULL, 0);
++}
++
+ static int rpi_firmware_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -326,6 +333,7 @@ static int rpi_firmware_probe(struct pla
+       rpi_firmware_print_firmware_revision(fw);
+       rpi_firmware_print_firmware_hash(fw);
+       rpi_register_hwmon_driver(dev, fw);
++      rpi_register_clk_driver(dev);
+       return 0;
+ }
+@@ -336,6 +344,8 @@ static int rpi_firmware_remove(struct pl
+       platform_device_unregister(rpi_hwmon);
+       rpi_hwmon = NULL;
++      platform_device_unregister(rpi_clk);
++      rpi_clk = NULL;
+       mbox_free_channel(fw->chan);
+       g_pdev = NULL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0761-clk-raspberrypi-register-platform-device-for-raspber.patch b/target/linux/brcm2708/patches-4.19/950-0761-clk-raspberrypi-register-platform-device-for-raspber.patch
new file mode 100644 (file)
index 0000000..be4d834
--- /dev/null
@@ -0,0 +1,65 @@
+From b39d5caa499559be6c309b9fd8f8b2f992504e18 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 12 Jun 2019 20:24:57 +0200
+Subject: [PATCH] clk: raspberrypi: register platform device for
+ raspberrypi-cpufreq
+
+Commit e2bb18347c8e5c4187831f3700c380e3c759601a upstream.
+
+As 'clk-raspberrypi' depends on RPi's firmware interface, which might be
+configured as a module, the cpu clock might not be available for the
+cpufreq driver during it's init process. So we register the
+'raspberrypi-cpufreq' platform device after the probe sequence succeeds.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -34,6 +34,7 @@
+ struct raspberrypi_clk {
+       struct device *dev;
+       struct rpi_firmware *firmware;
++      struct platform_device *cpufreq;
+       unsigned long min_rate;
+       unsigned long max_rate;
+@@ -272,6 +273,7 @@ static int raspberrypi_clk_probe(struct
+       rpi->dev = dev;
+       rpi->firmware = firmware;
++      platform_set_drvdata(pdev, rpi);
+       ret = raspberrypi_register_pllb(rpi);
+       if (ret) {
+@@ -283,6 +285,18 @@ static int raspberrypi_clk_probe(struct
+       if (ret)
+               return ret;
++      rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq",
++                                                   -1, NULL, 0);
++
++      return 0;
++}
++
++static int raspberrypi_clk_remove(struct platform_device *pdev)
++{
++      struct raspberrypi_clk *rpi = platform_get_drvdata(pdev);
++
++      platform_device_unregister(rpi->cpufreq);
++
+       return 0;
+ }
+@@ -291,6 +305,7 @@ static struct platform_driver raspberryp
+               .name = "raspberrypi-clk",
+       },
+       .probe          = raspberrypi_clk_probe,
++      .remove         = raspberrypi_clk_remove,
+ };
+ module_platform_driver(raspberrypi_clk_driver);
diff --git a/target/linux/brcm2708/patches-4.19/950-0761-cpufreq-add-driver-for-Raspberry-Pi.patch b/target/linux/brcm2708/patches-4.19/950-0761-cpufreq-add-driver-for-Raspberry-Pi.patch
deleted file mode 100644 (file)
index 7785caf..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-From 1c0d3626312369837bc18051ed6c9611323fce87 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 12 Jun 2019 20:24:56 +0200
-Subject: [PATCH] cpufreq: add driver for Raspberry Pi
-
-Commit d3df18a97e586702920337056540267807b23f8e upstream.
-
-Raspberry Pi's firmware offers and interface though which update it's
-performance requirements. It allows us to request for specific runtime
-frequencies, which the firmware might or might not respect, depending on
-the firmware configuration and thermals.
-
-As the maximum and minimum frequencies are configurable in the firmware
-there is no way to know in advance their values. So the Raspberry Pi
-cpufreq driver queries them, builds an opp frequency table to then
-launch cpufreq-dt.
-
-Also, as the firmware interface might be configured as a module, making
-the cpu clock unavailable during init, this implements a full fledged
-driver, as opposed to most drivers registering cpufreq-dt, which only
-make use of an init routine.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Stephen Boyd <sboyd@kernel.org>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
----
- drivers/cpufreq/Kconfig.arm           |  8 +++
- drivers/cpufreq/Makefile              |  1 +
- drivers/cpufreq/raspberrypi-cpufreq.c | 97 +++++++++++++++++++++++++++
- 3 files changed, 106 insertions(+)
- create mode 100644 drivers/cpufreq/raspberrypi-cpufreq.c
-
---- a/drivers/cpufreq/Kconfig.arm
-+++ b/drivers/cpufreq/Kconfig.arm
-@@ -121,6 +121,14 @@ config ARM_QCOM_CPUFREQ_KRYO
-         If in doubt, say N.
-+config ARM_RASPBERRYPI_CPUFREQ
-+      tristate "Raspberry Pi cpufreq support"
-+      depends on CLK_RASPBERRYPI || COMPILE_TEST
-+      help
-+        This adds the CPUFreq driver for Raspberry Pi
-+
-+        If in doubt, say N.
-+
- config ARM_S3C_CPUFREQ
-       bool
-       help
---- a/drivers/cpufreq/Makefile
-+++ b/drivers/cpufreq/Makefile
-@@ -65,6 +65,7 @@ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)  += o
- obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)      += pxa2xx-cpufreq.o
- obj-$(CONFIG_PXA3xx)                  += pxa3xx-cpufreq.o
- obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)   += qcom-cpufreq-kryo.o
-+obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ)         += raspberrypi-cpufreq.o
- obj-$(CONFIG_ARM_S3C2410_CPUFREQ)     += s3c2410-cpufreq.o
- obj-$(CONFIG_ARM_S3C2412_CPUFREQ)     += s3c2412-cpufreq.o
- obj-$(CONFIG_ARM_S3C2416_CPUFREQ)     += s3c2416-cpufreq.o
---- /dev/null
-+++ b/drivers/cpufreq/raspberrypi-cpufreq.c
-@@ -0,0 +1,97 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Raspberry Pi cpufreq driver
-+ *
-+ * Copyright (C) 2019, Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/cpu.h>
-+#include <linux/cpufreq.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_opp.h>
-+
-+#define RASPBERRYPI_FREQ_INTERVAL     100000000
-+
-+static struct platform_device *cpufreq_dt;
-+
-+static int raspberrypi_cpufreq_probe(struct platform_device *pdev)
-+{
-+      struct device *cpu_dev;
-+      unsigned long min, max;
-+      unsigned long rate;
-+      struct clk *clk;
-+      int ret;
-+
-+      cpu_dev = get_cpu_device(0);
-+      if (!cpu_dev) {
-+              pr_err("Cannot get CPU for cpufreq driver\n");
-+              return -ENODEV;
-+      }
-+
-+      clk = clk_get(cpu_dev, NULL);
-+      if (IS_ERR(clk)) {
-+              dev_err(cpu_dev, "Cannot get clock for CPU0\n");
-+              return PTR_ERR(clk);
-+      }
-+
-+      /*
-+       * The max and min frequencies are configurable in the Raspberry Pi
-+       * firmware, so we query them at runtime.
-+       */
-+      min = roundup(clk_round_rate(clk, 0), RASPBERRYPI_FREQ_INTERVAL);
-+      max = roundup(clk_round_rate(clk, ULONG_MAX), RASPBERRYPI_FREQ_INTERVAL);
-+      clk_put(clk);
-+
-+      for (rate = min; rate <= max; rate += RASPBERRYPI_FREQ_INTERVAL) {
-+              ret = dev_pm_opp_add(cpu_dev, rate, 0);
-+              if (ret)
-+                      goto remove_opp;
-+      }
-+
-+      cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
-+      ret = PTR_ERR_OR_ZERO(cpufreq_dt);
-+      if (ret) {
-+              dev_err(cpu_dev, "Failed to create platform device, %d\n", ret);
-+              goto remove_opp;
-+      }
-+
-+      return 0;
-+
-+remove_opp:
-+      dev_pm_opp_remove_all_dynamic(cpu_dev);
-+
-+      return ret;
-+}
-+
-+static int raspberrypi_cpufreq_remove(struct platform_device *pdev)
-+{
-+      struct device *cpu_dev;
-+
-+      cpu_dev = get_cpu_device(0);
-+      if (cpu_dev)
-+              dev_pm_opp_remove_all_dynamic(cpu_dev);
-+
-+      platform_device_unregister(cpufreq_dt);
-+
-+      return 0;
-+}
-+
-+/*
-+ * Since the driver depends on clk-raspberrypi, which may return EPROBE_DEFER,
-+ * all the activity is performed in the probe, which may be defered as well.
-+ */
-+static struct platform_driver raspberrypi_cpufreq_driver = {
-+      .driver = {
-+              .name = "raspberrypi-cpufreq",
-+      },
-+      .probe          = raspberrypi_cpufreq_probe,
-+      .remove         = raspberrypi_cpufreq_remove,
-+};
-+module_platform_driver(raspberrypi_cpufreq_driver);
-+
-+MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de");
-+MODULE_DESCRIPTION("Raspberry Pi cpufreq driver");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:raspberrypi-cpufreq");
diff --git a/target/linux/brcm2708/patches-4.19/950-0762-clk-bcm2835-remove-pllb.patch b/target/linux/brcm2708/patches-4.19/950-0762-clk-bcm2835-remove-pllb.patch
new file mode 100644 (file)
index 0000000..af9dde3
--- /dev/null
@@ -0,0 +1,56 @@
+From 04ebfc3e25eaa3dd77544b4b950497990b1a327e Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 12 Jun 2019 20:24:53 +0200
+Subject: [PATCH] clk: bcm2835: remove pllb
+
+Commit 2256d89333bd17b8b56b42734a7e1046d52f7fc3 upstream.
+
+Raspberry Pi's firmware controls this pll, we should use the firmware
+interface to access it.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 30 ++++--------------------------
+ 1 file changed, 4 insertions(+), 26 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1755,32 +1755,10 @@ static const struct bcm2835_clk_desc clk
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+-      /* PLLB is used for the ARM's clock. */
+-      [BCM2835_PLLB]          = REGISTER_PLL(
+-              SOC_ALL,
+-              .name = "pllb",
+-              .cm_ctrl_reg = CM_PLLB,
+-              .a2w_ctrl_reg = A2W_PLLB_CTRL,
+-              .frac_reg = A2W_PLLB_FRAC,
+-              .ana_reg_base = A2W_PLLB_ANA0,
+-              .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
+-              .lock_mask = CM_LOCK_FLOCKB,
+-
+-              .ana = &bcm2835_ana_default,
+-
+-              .min_rate = 600000000u,
+-              .max_rate = 3000000000u,
+-              .max_fb_rate = BCM2835_MAX_FB_RATE),
+-      [BCM2835_PLLB_ARM]      = REGISTER_PLL_DIV(
+-              SOC_ALL,
+-              .name = "pllb_arm",
+-              .source_pll = "pllb",
+-              .cm_reg = CM_PLLB,
+-              .a2w_reg = A2W_PLLB_ARM,
+-              .load_mask = CM_PLLB_LOADARM,
+-              .hold_mask = CM_PLLB_HOLDARM,
+-              .fixed_divider = 1,
+-              .flags = CLK_SET_RATE_PARENT),
++      /*
++       * PLLB is used for the ARM's clock. Controlled by firmware, see
++       * clk-raspberrypi.c.
++       */
+       /*
+        * PLLC is the core PLL, used to drive the core VPU clock.
diff --git a/target/linux/brcm2708/patches-4.19/950-0762-firmware-raspberrypi-register-clk-device.patch b/target/linux/brcm2708/patches-4.19/950-0762-firmware-raspberrypi-register-clk-device.patch
deleted file mode 100644 (file)
index 2886ab1..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From e7f2fcf4bf0b0a227f564fcdde46f3bdd326c1b2 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 12 Jun 2019 20:24:55 +0200
-Subject: [PATCH] firmware: raspberrypi: register clk device
-
-Commit 91f2cf4a6b2131016b1ae9c9500245f0572112c7 upstream.
-
-Since clk-raspberrypi is tied to the VC4 firmware instead of particular
-hardware it's registration should be performed by the firmware driver.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Stephen Boyd <sboyd@kernel.org>
----
- drivers/firmware/raspberrypi.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/firmware/raspberrypi.c
-+++ b/drivers/firmware/raspberrypi.c
-@@ -24,6 +24,7 @@
- #define MBOX_CHAN_PROPERTY            8
- static struct platform_device *rpi_hwmon;
-+static struct platform_device *rpi_clk;
- struct rpi_firmware {
-       struct mbox_client cl;
-@@ -297,6 +298,12 @@ rpi_register_hwmon_driver(struct device
-       }
- }
-+static void rpi_register_clk_driver(struct device *dev)
-+{
-+      rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
-+                                              -1, NULL, 0);
-+}
-+
- static int rpi_firmware_probe(struct platform_device *pdev)
- {
-       struct device *dev = &pdev->dev;
-@@ -326,6 +333,7 @@ static int rpi_firmware_probe(struct pla
-       rpi_firmware_print_firmware_revision(fw);
-       rpi_firmware_print_firmware_hash(fw);
-       rpi_register_hwmon_driver(dev, fw);
-+      rpi_register_clk_driver(dev);
-       return 0;
- }
-@@ -336,6 +344,8 @@ static int rpi_firmware_remove(struct pl
-       platform_device_unregister(rpi_hwmon);
-       rpi_hwmon = NULL;
-+      platform_device_unregister(rpi_clk);
-+      rpi_clk = NULL;
-       mbox_free_channel(fw->chan);
-       g_pdev = NULL;
diff --git a/target/linux/brcm2708/patches-4.19/950-0763-clk-raspberrypi-register-platform-device-for-raspber.patch b/target/linux/brcm2708/patches-4.19/950-0763-clk-raspberrypi-register-platform-device-for-raspber.patch
deleted file mode 100644 (file)
index be4d834..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-From b39d5caa499559be6c309b9fd8f8b2f992504e18 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 12 Jun 2019 20:24:57 +0200
-Subject: [PATCH] clk: raspberrypi: register platform device for
- raspberrypi-cpufreq
-
-Commit e2bb18347c8e5c4187831f3700c380e3c759601a upstream.
-
-As 'clk-raspberrypi' depends on RPi's firmware interface, which might be
-configured as a module, the cpu clock might not be available for the
-cpufreq driver during it's init process. So we register the
-'raspberrypi-cpufreq' platform device after the probe sequence succeeds.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Stephen Boyd <sboyd@kernel.org>
----
- drivers/clk/bcm/clk-raspberrypi.c | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
---- a/drivers/clk/bcm/clk-raspberrypi.c
-+++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -34,6 +34,7 @@
- struct raspberrypi_clk {
-       struct device *dev;
-       struct rpi_firmware *firmware;
-+      struct platform_device *cpufreq;
-       unsigned long min_rate;
-       unsigned long max_rate;
-@@ -272,6 +273,7 @@ static int raspberrypi_clk_probe(struct
-       rpi->dev = dev;
-       rpi->firmware = firmware;
-+      platform_set_drvdata(pdev, rpi);
-       ret = raspberrypi_register_pllb(rpi);
-       if (ret) {
-@@ -283,6 +285,18 @@ static int raspberrypi_clk_probe(struct
-       if (ret)
-               return ret;
-+      rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq",
-+                                                   -1, NULL, 0);
-+
-+      return 0;
-+}
-+
-+static int raspberrypi_clk_remove(struct platform_device *pdev)
-+{
-+      struct raspberrypi_clk *rpi = platform_get_drvdata(pdev);
-+
-+      platform_device_unregister(rpi->cpufreq);
-+
-       return 0;
- }
-@@ -291,6 +305,7 @@ static struct platform_driver raspberryp
-               .name = "raspberrypi-clk",
-       },
-       .probe          = raspberrypi_clk_probe,
-+      .remove         = raspberrypi_clk_remove,
- };
- module_platform_driver(raspberrypi_clk_driver);
diff --git a/target/linux/brcm2708/patches-4.19/950-0763-v3d_drv-Allow-clock-retrieval-by-name.patch b/target/linux/brcm2708/patches-4.19/950-0763-v3d_drv-Allow-clock-retrieval-by-name.patch
new file mode 100644 (file)
index 0000000..b5ce5bd
--- /dev/null
@@ -0,0 +1,23 @@
+From 2b08d751023fcdf3c37317dc769ce199ba361415 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 9 Sep 2019 23:50:44 +0100
+Subject: [PATCH] v3d_drv: Allow clock retrieval by name
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -300,7 +300,9 @@ static int v3d_platform_drm_probe(struct
+               }
+       }
+-      v3d->clk = devm_clk_get(dev, NULL);
++      v3d->clk = devm_clk_get(dev, "v3d");
++      if (!v3d->clk)
++              v3d->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR_OR_NULL(v3d->clk)) {
+               if (PTR_ERR(v3d->clk) != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get clock (%ld)\n", PTR_ERR(v3d->clk));
diff --git a/target/linux/brcm2708/patches-4.19/950-0764-clk-bcm2835-remove-pllb.patch b/target/linux/brcm2708/patches-4.19/950-0764-clk-bcm2835-remove-pllb.patch
deleted file mode 100644 (file)
index af9dde3..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 04ebfc3e25eaa3dd77544b4b950497990b1a327e Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 12 Jun 2019 20:24:53 +0200
-Subject: [PATCH] clk: bcm2835: remove pllb
-
-Commit 2256d89333bd17b8b56b42734a7e1046d52f7fc3 upstream.
-
-Raspberry Pi's firmware controls this pll, we should use the firmware
-interface to access it.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Stephen Boyd <sboyd@kernel.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 30 ++++--------------------------
- 1 file changed, 4 insertions(+), 26 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1755,32 +1755,10 @@ static const struct bcm2835_clk_desc clk
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
--      /* PLLB is used for the ARM's clock. */
--      [BCM2835_PLLB]          = REGISTER_PLL(
--              SOC_ALL,
--              .name = "pllb",
--              .cm_ctrl_reg = CM_PLLB,
--              .a2w_ctrl_reg = A2W_PLLB_CTRL,
--              .frac_reg = A2W_PLLB_FRAC,
--              .ana_reg_base = A2W_PLLB_ANA0,
--              .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
--              .lock_mask = CM_LOCK_FLOCKB,
--
--              .ana = &bcm2835_ana_default,
--
--              .min_rate = 600000000u,
--              .max_rate = 3000000000u,
--              .max_fb_rate = BCM2835_MAX_FB_RATE),
--      [BCM2835_PLLB_ARM]      = REGISTER_PLL_DIV(
--              SOC_ALL,
--              .name = "pllb_arm",
--              .source_pll = "pllb",
--              .cm_reg = CM_PLLB,
--              .a2w_reg = A2W_PLLB_ARM,
--              .load_mask = CM_PLLB_LOADARM,
--              .hold_mask = CM_PLLB_HOLDARM,
--              .fixed_divider = 1,
--              .flags = CLK_SET_RATE_PARENT),
-+      /*
-+       * PLLB is used for the ARM's clock. Controlled by firmware, see
-+       * clk-raspberrypi.c.
-+       */
-       /*
-        * PLLC is the core PLL, used to drive the core VPU clock.
diff --git a/target/linux/brcm2708/patches-4.19/950-0764-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch b/target/linux/brcm2708/patches-4.19/950-0764-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch
new file mode 100644 (file)
index 0000000..f10e246
--- /dev/null
@@ -0,0 +1,27 @@
+From ccf2b80332ba86e5a69f7e3a0f097d9558ad5c95 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 5 Sep 2019 17:59:14 +0100
+Subject: [PATCH] v3d_gem: Kick the clock so firmware knows we are
+ using firmware clock interface
+
+Setting the v3d clock to low value allows firmware to handle dvfs in case
+where v3d hardware is not being actively used (e.g. console use).
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -1050,6 +1050,10 @@ v3d_gem_init(struct drm_device *dev)
+       mutex_init(&v3d->clk_lock);
+       INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
++      /* kick the clock so firmware knows we are using firmware clock interface */
++      v3d_clock_up_get(v3d);
++      v3d_clock_up_put(v3d);
++
+       /* Note: We don't allocate address 0.  Various bits of HW
+        * treat 0 as special, such as the occlusion query counters
+        * where 0 means "disabled".
diff --git a/target/linux/brcm2708/patches-4.19/950-0765-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch b/target/linux/brcm2708/patches-4.19/950-0765-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch
new file mode 100644 (file)
index 0000000..419902a
--- /dev/null
@@ -0,0 +1,25 @@
+From 801156c2f2d2d074a1d966f59fc63d8056b3cef9 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 9 Sep 2019 15:49:56 +0100
+Subject: [PATCH] clk-raspberrypi: Allow cpufreq driver to also adjust
+ gpu clocks
+
+For performance/power it is beneficial to adjust gpu clocks with arm clock.
+This is how the downstream cpufreq driver works
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -70,7 +70,7 @@ static int raspberrypi_clock_property(st
+       struct raspberrypi_firmware_prop msg = {
+               .id = cpu_to_le32(clk),
+               .val = cpu_to_le32(*val),
+-              .disable_turbo = cpu_to_le32(1),
++              .disable_turbo = cpu_to_le32(0),
+       };
+       int ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0765-v3d_drv-Allow-clock-retrieval-by-name.patch b/target/linux/brcm2708/patches-4.19/950-0765-v3d_drv-Allow-clock-retrieval-by-name.patch
deleted file mode 100644 (file)
index b5ce5bd..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 2b08d751023fcdf3c37317dc769ce199ba361415 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 9 Sep 2019 23:50:44 +0100
-Subject: [PATCH] v3d_drv: Allow clock retrieval by name
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -300,7 +300,9 @@ static int v3d_platform_drm_probe(struct
-               }
-       }
--      v3d->clk = devm_clk_get(dev, NULL);
-+      v3d->clk = devm_clk_get(dev, "v3d");
-+      if (!v3d->clk)
-+              v3d->clk = devm_clk_get(dev, NULL);
-       if (IS_ERR_OR_NULL(v3d->clk)) {
-               if (PTR_ERR(v3d->clk) != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to get clock (%ld)\n", PTR_ERR(v3d->clk));
diff --git a/target/linux/brcm2708/patches-4.19/950-0766-clk-raspberrypi-Also-support-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0766-clk-raspberrypi-Also-support-v3d-clock.patch
new file mode 100644 (file)
index 0000000..c145f2f
--- /dev/null
@@ -0,0 +1,640 @@
+From 679f68410271a32f200e48b501027f68bd114d5c Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Wed, 21 Aug 2019 14:55:56 +0100
+Subject: [PATCH] clk-raspberrypi: Also support v3d clock
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 497 ++++++++++++++++++++++++------
+ 1 file changed, 408 insertions(+), 89 deletions(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -15,33 +15,103 @@
+ #include <linux/io.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+-
++#include <dt-bindings/clock/bcm2835.h>
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+ #define RPI_FIRMWARE_ARM_CLK_ID               0x00000003
++#define RPI_FIRMWARE_V3D_CLK_ID               0x00000005
+ #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
+ #define RPI_FIRMWARE_STATE_WAIT_BIT   BIT(1)
+-/*
+- * Even though the firmware interface alters 'pllb' the frequencies are
+- * provided as per 'pllb_arm'. We need to scale before passing them trough.
+- */
+-#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE        2
+-
+ #define A2W_PLL_FRAC_BITS             20
++#define SOC_BCM2835           BIT(0)
++#define SOC_BCM2711           BIT(1)
++#define SOC_ALL                       (SOC_BCM2835 | SOC_BCM2711)
++
+ struct raspberrypi_clk {
+       struct device *dev;
+       struct rpi_firmware *firmware;
+       struct platform_device *cpufreq;
++};
++
++typedef int (*raspberrypi_clk_register)(struct raspberrypi_clk *rpi,
++                                            const void *data);
++
++
++/* assignment helper macros for different clock types */
++#define _REGISTER(f, s, ...) { .clk_register = (raspberrypi_clk_register)f, \
++                             .supported = s,                          \
++                             .data = __VA_ARGS__ }
++#define REGISTER_PLL(s, ...)  _REGISTER(&raspberrypi_register_pll,    \
++                                        s,                            \
++                                        &(struct raspberrypi_pll_data)        \
++                                        {__VA_ARGS__})
++#define REGISTER_PLL_DIV(s, ...) _REGISTER(&raspberrypi_register_pll_divider, \
++                                         s,                             \
++                                         &(struct raspberrypi_pll_divider_data) \
++                                         {__VA_ARGS__})
++#define REGISTER_CLK(s, ...)  _REGISTER(&raspberrypi_register_clock,  \
++                                        s,                            \
++                                        &(struct raspberrypi_clock_data)      \
++                                        {__VA_ARGS__})
++
++
++struct raspberrypi_pll_data {
++      const char *name;
++      const char *const *parents;
++      int num_parents;
++      u32 clock_id;
++};
++
++struct raspberrypi_clock_data {
++      const char *name;
++      const char *const *parents;
++      int num_parents;
++      u32 flags;
++      u32 clock_id;
++};
++
++struct raspberrypi_pll_divider_data {
++      const char *name;
++      const char *divider_name;
++      const char *lookup;
++      const char *source_pll;
++
++      u32 fixed_divider;
++      u32 flags;
++      u32 clock_id;
++};
+-      unsigned long min_rate;
+-      unsigned long max_rate;
++struct raspberrypi_clk_desc {
++      raspberrypi_clk_register clk_register;
++      unsigned int supported;
++      const void *data;
++};
+-      struct clk_hw pllb;
+-      struct clk_hw *pllb_arm;
+-      struct clk_lookup *pllb_arm_lookup;
++struct raspberrypi_clock {
++      struct clk_hw hw;
++      struct raspberrypi_clk *rpi;
++      u32 min_rate;
++      u32 max_rate;
++      const struct raspberrypi_clock_data *data;
++};
++
++struct raspberrypi_pll {
++      struct clk_hw hw;
++      struct raspberrypi_clk *rpi;
++      u32 min_rate;
++      u32 max_rate;
++      const struct raspberrypi_pll_data *data;
++};
++
++struct raspberrypi_pll_divider {
++      struct clk_divider div;
++      struct raspberrypi_clk *rpi;
++      u32 min_rate;
++      u32 max_rate;
++      const struct raspberrypi_pll_divider_data *data;
+ };
+ /*
+@@ -83,56 +153,49 @@ static int raspberrypi_clock_property(st
+       return 0;
+ }
+-static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
++static int raspberrypi_fw_is_on(struct raspberrypi_clk *rpi, u32 clock_id, const char *name)
+ {
+-      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
+-                                                 pllb);
+       u32 val = 0;
+       int ret;
+       ret = raspberrypi_clock_property(rpi->firmware,
+                                        RPI_FIRMWARE_GET_CLOCK_STATE,
+-                                       RPI_FIRMWARE_ARM_CLK_ID, &val);
++                                       clock_id, &val);
+       if (ret)
+               return 0;
+       return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
+ }
+-
+-static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
+-                                               unsigned long parent_rate)
++static unsigned long raspberrypi_fw_get_rate(struct raspberrypi_clk *rpi,
++                                               u32 clock_id, const char *name, unsigned long parent_rate)
+ {
+-      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
+-                                                 pllb);
+       u32 val = 0;
+       int ret;
+       ret = raspberrypi_clock_property(rpi->firmware,
+                                        RPI_FIRMWARE_GET_CLOCK_RATE,
+-                                       RPI_FIRMWARE_ARM_CLK_ID,
++                                       clock_id,
+                                        &val);
+       if (ret)
+-              return ret;
+-
+-      return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
++              dev_err_ratelimited(rpi->dev, "Failed to get %s frequency: %d",
++                                  name, ret);
++      return val;
+ }
+-static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+-                                     unsigned long parent_rate)
++static int raspberrypi_fw_set_rate(struct raspberrypi_clk *rpi,
++                                 u32 clock_id, const char *name, u32 rate,
++                                 unsigned long parent_rate)
+ {
+-      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
+-                                                 pllb);
+-      u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
+       int ret;
+       ret = raspberrypi_clock_property(rpi->firmware,
+                                        RPI_FIRMWARE_SET_CLOCK_RATE,
+-                                       RPI_FIRMWARE_ARM_CLK_ID,
+-                                       &new_rate);
++                                       clock_id,
++                                       &rate);
+       if (ret)
+               dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
+-                                  clk_hw_get_name(hw), ret);
++                                  name, ret);
+       return ret;
+ }
+@@ -141,16 +204,15 @@ static int raspberrypi_fw_pll_set_rate(s
+  * Sadly there is no firmware rate rounding interface. We borrowed it from
+  * clk-bcm2835.
+  */
+-static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
++static int raspberrypi_determine_rate(struct raspberrypi_clk *rpi,
++                                        u32 clock_id, const char *name, unsigned long min_rate, unsigned long max_rate,
+                                         struct clk_rate_request *req)
+ {
+-      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
+-                                                 pllb);
+       u64 div, final_rate;
+       u32 ndiv, fdiv;
+       /* We can't use req->rate directly as it would overflow */
+-      final_rate = clamp(req->rate, rpi->min_rate, rpi->max_rate);
++      final_rate = clamp(req->rate, min_rate, max_rate);
+       div = (u64)final_rate << A2W_PLL_FRAC_BITS;
+       do_div(div, req->best_parent_rate);
+@@ -166,6 +228,125 @@ static int raspberrypi_pll_determine_rat
+       return 0;
+ }
++static int raspberrypi_fw_clock_is_on(struct clk_hw *hw)
++{
++      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_clock_data *data = pll->data;
++
++      return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
++}
++
++static unsigned long raspberrypi_fw_clock_get_rate(struct clk_hw *hw,
++                                               unsigned long parent_rate)
++{
++      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_clock_data *data = pll->data;
++
++      return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
++}
++
++static int raspberrypi_fw_clock_set_rate(struct clk_hw *hw, unsigned long rate,
++                                     unsigned long parent_rate)
++{
++      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_clock_data *data = pll->data;
++
++      return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
++}
++
++static int raspberrypi_clock_determine_rate(struct clk_hw *hw,
++                                        struct clk_rate_request *req)
++{
++      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_clock_data *data = pll->data;
++
++      return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
++}
++
++static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
++{
++      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_data *data = pll->data;
++
++      return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
++}
++
++static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
++                                               unsigned long parent_rate)
++{
++      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_data *data = pll->data;
++
++      return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
++}
++
++static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
++                                     unsigned long parent_rate)
++{
++      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_data *data = pll->data;
++
++      return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
++}
++
++static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
++                                        struct clk_rate_request *req)
++{
++      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_data *data = pll->data;
++
++      return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
++}
++
++
++static int raspberrypi_fw_pll_div_is_on(struct clk_hw *hw)
++{
++      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_divider_data *data = pll->data;
++
++      return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
++}
++
++static unsigned long raspberrypi_fw_pll_div_get_rate(struct clk_hw *hw,
++                                               unsigned long parent_rate)
++{
++      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_divider_data *data = pll->data;
++
++      return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
++}
++
++static int raspberrypi_fw_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
++                                     unsigned long parent_rate)
++{
++      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_divider_data *data = pll->data;
++
++      return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
++}
++
++static int raspberrypi_pll_div_determine_rate(struct clk_hw *hw,
++                                        struct clk_rate_request *req)
++{
++      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
++      struct raspberrypi_clk *rpi = pll->rpi;
++      const struct raspberrypi_pll_divider_data *data = pll->data;
++
++      return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
++}
++
++
+ static const struct clk_ops raspberrypi_firmware_pll_clk_ops = {
+       .is_prepared = raspberrypi_fw_pll_is_on,
+       .recalc_rate = raspberrypi_fw_pll_get_rate,
+@@ -173,87 +354,225 @@ static const struct clk_ops raspberrypi_
+       .determine_rate = raspberrypi_pll_determine_rate,
+ };
+-static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
++static const struct clk_ops raspberrypi_firmware_pll_divider_clk_ops = {
++      .is_prepared = raspberrypi_fw_pll_div_is_on,
++      .recalc_rate = raspberrypi_fw_pll_div_get_rate,
++      .set_rate = raspberrypi_fw_pll_div_set_rate,
++      .determine_rate = raspberrypi_pll_div_determine_rate,
++};
++
++static const struct clk_ops raspberrypi_firmware_clk_ops = {
++      .is_prepared = raspberrypi_fw_clock_is_on,
++      .recalc_rate = raspberrypi_fw_clock_get_rate,
++      .set_rate = raspberrypi_fw_clock_set_rate,
++      .determine_rate = raspberrypi_clock_determine_rate,
++};
++
++
++static int raspberrypi_get_clock_range(struct raspberrypi_clk *rpi, u32 clock_id, u32 *min_rate, u32 *max_rate)
+ {
+-      u32 min_rate = 0, max_rate = 0;
++      int ret;
++
++      /* Get min & max rates set by the firmware */
++      ret = raspberrypi_clock_property(rpi->firmware,
++                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
++                                       clock_id,
++                                       min_rate);
++      if (ret) {
++              dev_err(rpi->dev, "Failed to get clock %d min freq: %d (%d)\n",
++                      clock_id, *min_rate, ret);
++              return ret;
++      }
++
++      ret = raspberrypi_clock_property(rpi->firmware,
++                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
++                                       clock_id,
++                                       max_rate);
++      if (ret) {
++              dev_err(rpi->dev, "Failed to get clock %d max freq: %d (%d)\n",
++                      clock_id, *max_rate, ret);
++              return ret;
++      }
++      return 0;
++}
++
++
++static int raspberrypi_register_pll(struct raspberrypi_clk *rpi,
++                                         const struct raspberrypi_pll_data *data)
++{
++      struct raspberrypi_pll *pll;
+       struct clk_init_data init;
+       int ret;
+       memset(&init, 0, sizeof(init));
+       /* All of the PLLs derive from the external oscillator. */
+-      init.parent_names = (const char *[]){ "osc" };
+-      init.num_parents = 1;
+-      init.name = "pllb";
++      init.parent_names = data->parents;
++      init.num_parents = data->num_parents;
++      init.name = data->name;
+       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,
+-                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
+-                                       RPI_FIRMWARE_ARM_CLK_ID,
+-                                       &min_rate);
++      pll = kzalloc(sizeof(*pll), GFP_KERNEL);
++      if (!pll)
++              return -ENOMEM;
++      pll->rpi = rpi;
++      pll->data = data;
++      pll->hw.init = &init;
++
++      ret = raspberrypi_get_clock_range(rpi, data->clock_id, &pll->min_rate, &pll->max_rate);
+       if (ret) {
+-              dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
+-                      init.name, ret);
++              dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
+               return ret;
+       }
+-      ret = raspberrypi_clock_property(rpi->firmware,
+-                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+-                                       RPI_FIRMWARE_ARM_CLK_ID,
+-                                       &max_rate);
++      ret = devm_clk_hw_register(rpi->dev, &pll->hw);
+       if (ret) {
+-              dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
+-                      init.name, ret);
++              dev_err(rpi->dev, "%s: devm_clk_hw_register(%s) failed: %d\n", __func__, init.name, ret);
+               return ret;
+       }
++      return 0;
++}
+-      if (!min_rate || !max_rate) {
+-              dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
+-                      min_rate, max_rate);
+-              return -EINVAL;
+-      }
++static int
++raspberrypi_register_pll_divider(struct raspberrypi_clk *rpi,
++                           const struct raspberrypi_pll_divider_data *data)
++{
++      struct raspberrypi_pll_divider *divider;
++      struct clk_init_data init;
++      int ret;
++
++      memset(&init, 0, sizeof(init));
++
++      init.parent_names = &data->source_pll;
++      init.num_parents = 1;
++      init.name = data->name;
++      init.ops = &raspberrypi_firmware_pll_divider_clk_ops;
++      init.flags = data->flags | CLK_IGNORE_UNUSED;
+-      dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
+-               min_rate, max_rate);
++      divider = devm_kzalloc(rpi->dev, sizeof(*divider), GFP_KERNEL);
++      if (!divider)
++              return -ENOMEM;
++
++      divider->div.hw.init = &init;
++      divider->rpi = rpi;
++      divider->data = data;
++
++      ret = raspberrypi_get_clock_range(rpi, data->clock_id, &divider->min_rate, &divider->max_rate);
++      if (ret) {
++              dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
++              return ret;
++      }
+-      rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
+-      rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
++      ret = devm_clk_hw_register(rpi->dev, &divider->div.hw);
++      if (ret) {
++              dev_err(rpi->dev, "%s: devm_clk_hw_register(%s) failed: %d\n", __func__, init.name, ret);
++              return ret;
++      }
+-      rpi->pllb.init = &init;
++      /*
++       * PLLH's channels have a fixed divide by 10 afterwards, which
++       * is what our consumers are actually using.
++       */
++      if (data->fixed_divider != 1) {
++              struct clk_lookup *lookup;
++              struct clk_hw *clk = clk_hw_register_fixed_factor(rpi->dev,
++                                                  data->divider_name,
++                                                  data->name,
++                                                  CLK_SET_RATE_PARENT,
++                                                  1,
++                                                  data->fixed_divider);
++              if (IS_ERR(clk)) {
++                      dev_err(rpi->dev, "%s: clk_hw_register_fixed_factor(%s) failed: %ld\n", __func__, init.name, PTR_ERR(clk));
++                      return PTR_ERR(clk);
++              }
++              if (data->lookup) {
++                      lookup = clkdev_hw_create(clk, NULL, data->lookup);
++                      if (IS_ERR(lookup)) {
++                              dev_err(rpi->dev, "%s: clk_hw_register_fixed_factor(%s) failed: %ld\n", __func__, init.name, PTR_ERR(lookup));
++                              return PTR_ERR(lookup);
++                      }
++              }
++      }
+-      return devm_clk_hw_register(rpi->dev, &rpi->pllb);
++      return 0;
+ }
+-static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
++static int raspberrypi_register_clock(struct raspberrypi_clk *rpi,
++                                        const struct raspberrypi_clock_data *data)
+ {
+-      rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev,
+-                              "pllb_arm", "pllb",
+-                              CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+-                              1, 2);
+-      if (IS_ERR(rpi->pllb_arm)) {
+-              dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
+-              return PTR_ERR(rpi->pllb_arm);
+-      }
++      struct raspberrypi_clock *clock;
++      struct clk_init_data init;
++      struct clk *clk;
++      int ret;
++
++      memset(&init, 0, sizeof(init));
++      init.parent_names = data->parents;
++      init.num_parents = data->num_parents;
++      init.name = data->name;
++      init.flags = data->flags | CLK_IGNORE_UNUSED;
+-      rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0");
+-      if (!rpi->pllb_arm_lookup) {
+-              dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
+-              clk_hw_unregister_fixed_factor(rpi->pllb_arm);
++      init.ops = &raspberrypi_firmware_clk_ops;
++
++      clock = devm_kzalloc(rpi->dev, sizeof(*clock), GFP_KERNEL);
++      if (!clock)
+               return -ENOMEM;
+-      }
++      clock->rpi = rpi;
++      clock->data = data;
++      clock->hw.init = &init;
++
++      ret = raspberrypi_get_clock_range(rpi, data->clock_id, &clock->min_rate, &clock->max_rate);
++      if (ret) {
++              dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
++              return ret;
++      }
++      clk = devm_clk_register(rpi->dev, &clock->hw);
++      if (IS_ERR(clk)) {
++              dev_err(rpi->dev, "%s: devm_clk_register(%s) failed: %ld\n", __func__, init.name, PTR_ERR(clk));
++              return PTR_ERR(clk);
++      }
++      ret = clk_register_clkdev(clk, init.name, NULL);
++      if (ret) {
++              dev_err(rpi->dev, "%s: clk_register_clkdev(%s) failed: %d\n", __func__, init.name, ret);
++              return ret;
++      }
+       return 0;
+ }
++
++/*
++ * the real definition of all the pll, pll_dividers and clocks
++ * these make use of the above REGISTER_* macros
++ */
++static const struct raspberrypi_clk_desc clk_desc_array[] = {
++      /* the PLL + PLL dividers */
++      [BCM2835_CLOCK_V3D]     = REGISTER_CLK(
++              SOC_ALL,
++              .name = "v3d",
++              .parents = (const char *[]){ "osc" },
++              .num_parents = 1,
++              .clock_id = RPI_FIRMWARE_V3D_CLK_ID),
++      [BCM2835_PLLB_ARM]      = REGISTER_PLL_DIV(
++              SOC_ALL,
++              .name = "pllb",
++              .source_pll = "osc",
++              .divider_name = "pllb_arm",
++              .lookup = "cpu0",
++              .fixed_divider = 2,
++              .clock_id = RPI_FIRMWARE_ARM_CLK_ID,
++              .flags = CLK_SET_RATE_PARENT),
++};
++
+ static int raspberrypi_clk_probe(struct platform_device *pdev)
+ {
+       struct device_node *firmware_node;
+       struct device *dev = &pdev->dev;
+       struct rpi_firmware *firmware;
+       struct raspberrypi_clk *rpi;
+-      int ret;
++      const struct raspberrypi_clk_desc *desc;
++      const size_t asize = ARRAY_SIZE(clk_desc_array);
++      int i;
+       firmware_node = of_find_compatible_node(NULL, NULL,
+                                       "raspberrypi,bcm2835-firmware");
+@@ -275,16 +594,16 @@ static int raspberrypi_clk_probe(struct
+       rpi->firmware = firmware;
+       platform_set_drvdata(pdev, rpi);
+-      ret = raspberrypi_register_pllb(rpi);
+-      if (ret) {
+-              dev_err(dev, "Failed to initialize pllb, %d\n", ret);
+-              return ret;
++      for (i = 0; i < asize; i++) {
++              desc = &clk_desc_array[i];
++              if (desc->clk_register && desc->data /*&&
++                  (desc->supported & pdata->soc)*/) {
++                      int ret = desc->clk_register(rpi, desc->data);
++                      if (ret)
++                              return ret;
++              }
+       }
+-      ret = raspberrypi_register_pllb_arm(rpi);
+-      if (ret)
+-              return ret;
+-
+       rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq",
+                                                    -1, NULL, 0);
diff --git a/target/linux/brcm2708/patches-4.19/950-0766-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch b/target/linux/brcm2708/patches-4.19/950-0766-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch
deleted file mode 100644 (file)
index f10e246..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From ccf2b80332ba86e5a69f7e3a0f097d9558ad5c95 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Thu, 5 Sep 2019 17:59:14 +0100
-Subject: [PATCH] v3d_gem: Kick the clock so firmware knows we are
- using firmware clock interface
-
-Setting the v3d clock to low value allows firmware to handle dvfs in case
-where v3d hardware is not being actively used (e.g. console use).
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/gpu/drm/v3d/v3d_gem.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -1050,6 +1050,10 @@ v3d_gem_init(struct drm_device *dev)
-       mutex_init(&v3d->clk_lock);
-       INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
-+      /* kick the clock so firmware knows we are using firmware clock interface */
-+      v3d_clock_up_get(v3d);
-+      v3d_clock_up_put(v3d);
-+
-       /* Note: We don't allocate address 0.  Various bits of HW
-        * treat 0 as special, such as the occlusion query counters
-        * where 0 means "disabled".
diff --git a/target/linux/brcm2708/patches-4.19/950-0767-clk-bcm2835-Disable-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0767-clk-bcm2835-Disable-v3d-clock.patch
new file mode 100644 (file)
index 0000000..34de4de
--- /dev/null
@@ -0,0 +1,58 @@
+From e8e99169991da84d59f1ed70de9621e31b67d505 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 3 Sep 2019 20:28:00 +0100
+Subject: [PATCH] clk-bcm2835: Disable v3d clock
+
+This is controlled by firmware, see clk-raspberrypi.c
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++------------------
+ 1 file changed, 12 insertions(+), 18 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1725,16 +1725,12 @@ static const struct bcm2835_clk_desc clk
+               .hold_mask = CM_PLLA_HOLDCORE,
+               .fixed_divider = 1,
+               .flags = CLK_SET_RATE_PARENT),
+-      [BCM2835_PLLA_PER]      = REGISTER_PLL_DIV(
+-              SOC_ALL,
+-              .name = "plla_per",
+-              .source_pll = "plla",
+-              .cm_reg = CM_PLLA,
+-              .a2w_reg = A2W_PLLA_PER,
+-              .load_mask = CM_PLLA_LOADPER,
+-              .hold_mask = CM_PLLA_HOLDPER,
+-              .fixed_divider = 1,
+-              .flags = CLK_SET_RATE_PARENT),
++
++      /*
++       * PLLA_PER is used for gpu clocks. Controlled by firmware, see
++       * clk-raspberrypi.c.
++       */
++
+       [BCM2835_PLLA_DSI0]     = REGISTER_PLL_DIV(
+               SOC_ALL,
+               .name = "plla_dsi0",
+@@ -2007,14 +2003,12 @@ static const struct bcm2835_clk_desc clk
+               .int_bits = 6,
+               .frac_bits = 0,
+               .tcnt_mux = 3),
+-      [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
+-              SOC_ALL,
+-              .name = "v3d",
+-              .ctl_reg = CM_V3DCTL,
+-              .div_reg = CM_V3DDIV,
+-              .int_bits = 4,
+-              .frac_bits = 8,
+-              .tcnt_mux = 4),
++
++      /*
++       * CLOCK_V3D is used for v3d clock. Controlled by firmware, see
++       * clk-raspberrypi.c.
++       */
++
+       /*
+        * VPU clock.  This doesn't have an enable bit, since it drives
+        * the bus for everything else, and is special so it doesn't need
diff --git a/target/linux/brcm2708/patches-4.19/950-0767-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch b/target/linux/brcm2708/patches-4.19/950-0767-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch
deleted file mode 100644 (file)
index 419902a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 801156c2f2d2d074a1d966f59fc63d8056b3cef9 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 9 Sep 2019 15:49:56 +0100
-Subject: [PATCH] clk-raspberrypi: Allow cpufreq driver to also adjust
- gpu clocks
-
-For performance/power it is beneficial to adjust gpu clocks with arm clock.
-This is how the downstream cpufreq driver works
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/clk/bcm/clk-raspberrypi.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/clk/bcm/clk-raspberrypi.c
-+++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -70,7 +70,7 @@ static int raspberrypi_clock_property(st
-       struct raspberrypi_firmware_prop msg = {
-               .id = cpu_to_le32(clk),
-               .val = cpu_to_le32(*val),
--              .disable_turbo = cpu_to_le32(1),
-+              .disable_turbo = cpu_to_le32(0),
-       };
-       int ret;
diff --git a/target/linux/brcm2708/patches-4.19/950-0768-clk-raspberrypi-Also-support-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0768-clk-raspberrypi-Also-support-v3d-clock.patch
deleted file mode 100644 (file)
index c145f2f..0000000
+++ /dev/null
@@ -1,640 +0,0 @@
-From 679f68410271a32f200e48b501027f68bd114d5c Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Wed, 21 Aug 2019 14:55:56 +0100
-Subject: [PATCH] clk-raspberrypi: Also support v3d clock
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/clk/bcm/clk-raspberrypi.c | 497 ++++++++++++++++++++++++------
- 1 file changed, 408 insertions(+), 89 deletions(-)
-
---- a/drivers/clk/bcm/clk-raspberrypi.c
-+++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -15,33 +15,103 @@
- #include <linux/io.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
--
-+#include <dt-bindings/clock/bcm2835.h>
- #include <soc/bcm2835/raspberrypi-firmware.h>
- #define RPI_FIRMWARE_ARM_CLK_ID               0x00000003
-+#define RPI_FIRMWARE_V3D_CLK_ID               0x00000005
- #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
- #define RPI_FIRMWARE_STATE_WAIT_BIT   BIT(1)
--/*
-- * Even though the firmware interface alters 'pllb' the frequencies are
-- * provided as per 'pllb_arm'. We need to scale before passing them trough.
-- */
--#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE        2
--
- #define A2W_PLL_FRAC_BITS             20
-+#define SOC_BCM2835           BIT(0)
-+#define SOC_BCM2711           BIT(1)
-+#define SOC_ALL                       (SOC_BCM2835 | SOC_BCM2711)
-+
- struct raspberrypi_clk {
-       struct device *dev;
-       struct rpi_firmware *firmware;
-       struct platform_device *cpufreq;
-+};
-+
-+typedef int (*raspberrypi_clk_register)(struct raspberrypi_clk *rpi,
-+                                            const void *data);
-+
-+
-+/* assignment helper macros for different clock types */
-+#define _REGISTER(f, s, ...) { .clk_register = (raspberrypi_clk_register)f, \
-+                             .supported = s,                          \
-+                             .data = __VA_ARGS__ }
-+#define REGISTER_PLL(s, ...)  _REGISTER(&raspberrypi_register_pll,    \
-+                                        s,                            \
-+                                        &(struct raspberrypi_pll_data)        \
-+                                        {__VA_ARGS__})
-+#define REGISTER_PLL_DIV(s, ...) _REGISTER(&raspberrypi_register_pll_divider, \
-+                                         s,                             \
-+                                         &(struct raspberrypi_pll_divider_data) \
-+                                         {__VA_ARGS__})
-+#define REGISTER_CLK(s, ...)  _REGISTER(&raspberrypi_register_clock,  \
-+                                        s,                            \
-+                                        &(struct raspberrypi_clock_data)      \
-+                                        {__VA_ARGS__})
-+
-+
-+struct raspberrypi_pll_data {
-+      const char *name;
-+      const char *const *parents;
-+      int num_parents;
-+      u32 clock_id;
-+};
-+
-+struct raspberrypi_clock_data {
-+      const char *name;
-+      const char *const *parents;
-+      int num_parents;
-+      u32 flags;
-+      u32 clock_id;
-+};
-+
-+struct raspberrypi_pll_divider_data {
-+      const char *name;
-+      const char *divider_name;
-+      const char *lookup;
-+      const char *source_pll;
-+
-+      u32 fixed_divider;
-+      u32 flags;
-+      u32 clock_id;
-+};
--      unsigned long min_rate;
--      unsigned long max_rate;
-+struct raspberrypi_clk_desc {
-+      raspberrypi_clk_register clk_register;
-+      unsigned int supported;
-+      const void *data;
-+};
--      struct clk_hw pllb;
--      struct clk_hw *pllb_arm;
--      struct clk_lookup *pllb_arm_lookup;
-+struct raspberrypi_clock {
-+      struct clk_hw hw;
-+      struct raspberrypi_clk *rpi;
-+      u32 min_rate;
-+      u32 max_rate;
-+      const struct raspberrypi_clock_data *data;
-+};
-+
-+struct raspberrypi_pll {
-+      struct clk_hw hw;
-+      struct raspberrypi_clk *rpi;
-+      u32 min_rate;
-+      u32 max_rate;
-+      const struct raspberrypi_pll_data *data;
-+};
-+
-+struct raspberrypi_pll_divider {
-+      struct clk_divider div;
-+      struct raspberrypi_clk *rpi;
-+      u32 min_rate;
-+      u32 max_rate;
-+      const struct raspberrypi_pll_divider_data *data;
- };
- /*
-@@ -83,56 +153,49 @@ static int raspberrypi_clock_property(st
-       return 0;
- }
--static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
-+static int raspberrypi_fw_is_on(struct raspberrypi_clk *rpi, u32 clock_id, const char *name)
- {
--      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
--                                                 pllb);
-       u32 val = 0;
-       int ret;
-       ret = raspberrypi_clock_property(rpi->firmware,
-                                        RPI_FIRMWARE_GET_CLOCK_STATE,
--                                       RPI_FIRMWARE_ARM_CLK_ID, &val);
-+                                       clock_id, &val);
-       if (ret)
-               return 0;
-       return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
- }
--
--static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
--                                               unsigned long parent_rate)
-+static unsigned long raspberrypi_fw_get_rate(struct raspberrypi_clk *rpi,
-+                                               u32 clock_id, const char *name, unsigned long parent_rate)
- {
--      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
--                                                 pllb);
-       u32 val = 0;
-       int ret;
-       ret = raspberrypi_clock_property(rpi->firmware,
-                                        RPI_FIRMWARE_GET_CLOCK_RATE,
--                                       RPI_FIRMWARE_ARM_CLK_ID,
-+                                       clock_id,
-                                        &val);
-       if (ret)
--              return ret;
--
--      return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+              dev_err_ratelimited(rpi->dev, "Failed to get %s frequency: %d",
-+                                  name, ret);
-+      return val;
- }
--static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
--                                     unsigned long parent_rate)
-+static int raspberrypi_fw_set_rate(struct raspberrypi_clk *rpi,
-+                                 u32 clock_id, const char *name, u32 rate,
-+                                 unsigned long parent_rate)
- {
--      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
--                                                 pllb);
--      u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-       int ret;
-       ret = raspberrypi_clock_property(rpi->firmware,
-                                        RPI_FIRMWARE_SET_CLOCK_RATE,
--                                       RPI_FIRMWARE_ARM_CLK_ID,
--                                       &new_rate);
-+                                       clock_id,
-+                                       &rate);
-       if (ret)
-               dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
--                                  clk_hw_get_name(hw), ret);
-+                                  name, ret);
-       return ret;
- }
-@@ -141,16 +204,15 @@ static int raspberrypi_fw_pll_set_rate(s
-  * Sadly there is no firmware rate rounding interface. We borrowed it from
-  * clk-bcm2835.
-  */
--static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
-+static int raspberrypi_determine_rate(struct raspberrypi_clk *rpi,
-+                                        u32 clock_id, const char *name, unsigned long min_rate, unsigned long max_rate,
-                                         struct clk_rate_request *req)
- {
--      struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
--                                                 pllb);
-       u64 div, final_rate;
-       u32 ndiv, fdiv;
-       /* We can't use req->rate directly as it would overflow */
--      final_rate = clamp(req->rate, rpi->min_rate, rpi->max_rate);
-+      final_rate = clamp(req->rate, min_rate, max_rate);
-       div = (u64)final_rate << A2W_PLL_FRAC_BITS;
-       do_div(div, req->best_parent_rate);
-@@ -166,6 +228,125 @@ static int raspberrypi_pll_determine_rat
-       return 0;
- }
-+static int raspberrypi_fw_clock_is_on(struct clk_hw *hw)
-+{
-+      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_clock_data *data = pll->data;
-+
-+      return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
-+}
-+
-+static unsigned long raspberrypi_fw_clock_get_rate(struct clk_hw *hw,
-+                                               unsigned long parent_rate)
-+{
-+      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_clock_data *data = pll->data;
-+
-+      return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
-+}
-+
-+static int raspberrypi_fw_clock_set_rate(struct clk_hw *hw, unsigned long rate,
-+                                     unsigned long parent_rate)
-+{
-+      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_clock_data *data = pll->data;
-+
-+      return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
-+}
-+
-+static int raspberrypi_clock_determine_rate(struct clk_hw *hw,
-+                                        struct clk_rate_request *req)
-+{
-+      struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_clock_data *data = pll->data;
-+
-+      return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
-+}
-+
-+static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
-+{
-+      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_data *data = pll->data;
-+
-+      return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
-+}
-+
-+static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
-+                                               unsigned long parent_rate)
-+{
-+      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_data *data = pll->data;
-+
-+      return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
-+}
-+
-+static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
-+                                     unsigned long parent_rate)
-+{
-+      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_data *data = pll->data;
-+
-+      return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
-+}
-+
-+static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
-+                                        struct clk_rate_request *req)
-+{
-+      struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_data *data = pll->data;
-+
-+      return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
-+}
-+
-+
-+static int raspberrypi_fw_pll_div_is_on(struct clk_hw *hw)
-+{
-+      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+      return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
-+}
-+
-+static unsigned long raspberrypi_fw_pll_div_get_rate(struct clk_hw *hw,
-+                                               unsigned long parent_rate)
-+{
-+      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+      return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
-+}
-+
-+static int raspberrypi_fw_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
-+                                     unsigned long parent_rate)
-+{
-+      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+      return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
-+}
-+
-+static int raspberrypi_pll_div_determine_rate(struct clk_hw *hw,
-+                                        struct clk_rate_request *req)
-+{
-+      struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+      struct raspberrypi_clk *rpi = pll->rpi;
-+      const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+      return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
-+}
-+
-+
- static const struct clk_ops raspberrypi_firmware_pll_clk_ops = {
-       .is_prepared = raspberrypi_fw_pll_is_on,
-       .recalc_rate = raspberrypi_fw_pll_get_rate,
-@@ -173,87 +354,225 @@ static const struct clk_ops raspberrypi_
-       .determine_rate = raspberrypi_pll_determine_rate,
- };
--static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
-+static const struct clk_ops raspberrypi_firmware_pll_divider_clk_ops = {
-+      .is_prepared = raspberrypi_fw_pll_div_is_on,
-+      .recalc_rate = raspberrypi_fw_pll_div_get_rate,
-+      .set_rate = raspberrypi_fw_pll_div_set_rate,
-+      .determine_rate = raspberrypi_pll_div_determine_rate,
-+};
-+
-+static const struct clk_ops raspberrypi_firmware_clk_ops = {
-+      .is_prepared = raspberrypi_fw_clock_is_on,
-+      .recalc_rate = raspberrypi_fw_clock_get_rate,
-+      .set_rate = raspberrypi_fw_clock_set_rate,
-+      .determine_rate = raspberrypi_clock_determine_rate,
-+};
-+
-+
-+static int raspberrypi_get_clock_range(struct raspberrypi_clk *rpi, u32 clock_id, u32 *min_rate, u32 *max_rate)
- {
--      u32 min_rate = 0, max_rate = 0;
-+      int ret;
-+
-+      /* Get min & max rates set by the firmware */
-+      ret = raspberrypi_clock_property(rpi->firmware,
-+                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
-+                                       clock_id,
-+                                       min_rate);
-+      if (ret) {
-+              dev_err(rpi->dev, "Failed to get clock %d min freq: %d (%d)\n",
-+                      clock_id, *min_rate, ret);
-+              return ret;
-+      }
-+
-+      ret = raspberrypi_clock_property(rpi->firmware,
-+                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
-+                                       clock_id,
-+                                       max_rate);
-+      if (ret) {
-+              dev_err(rpi->dev, "Failed to get clock %d max freq: %d (%d)\n",
-+                      clock_id, *max_rate, ret);
-+              return ret;
-+      }
-+      return 0;
-+}
-+
-+
-+static int raspberrypi_register_pll(struct raspberrypi_clk *rpi,
-+                                         const struct raspberrypi_pll_data *data)
-+{
-+      struct raspberrypi_pll *pll;
-       struct clk_init_data init;
-       int ret;
-       memset(&init, 0, sizeof(init));
-       /* All of the PLLs derive from the external oscillator. */
--      init.parent_names = (const char *[]){ "osc" };
--      init.num_parents = 1;
--      init.name = "pllb";
-+      init.parent_names = data->parents;
-+      init.num_parents = data->num_parents;
-+      init.name = data->name;
-       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,
--                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
--                                       RPI_FIRMWARE_ARM_CLK_ID,
--                                       &min_rate);
-+      pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-+      if (!pll)
-+              return -ENOMEM;
-+      pll->rpi = rpi;
-+      pll->data = data;
-+      pll->hw.init = &init;
-+
-+      ret = raspberrypi_get_clock_range(rpi, data->clock_id, &pll->min_rate, &pll->max_rate);
-       if (ret) {
--              dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
--                      init.name, ret);
-+              dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
-               return ret;
-       }
--      ret = raspberrypi_clock_property(rpi->firmware,
--                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
--                                       RPI_FIRMWARE_ARM_CLK_ID,
--                                       &max_rate);
-+      ret = devm_clk_hw_register(rpi->dev, &pll->hw);
-       if (ret) {
--              dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
--                      init.name, ret);
-+              dev_err(rpi->dev, "%s: devm_clk_hw_register(%s) failed: %d\n", __func__, init.name, ret);
-               return ret;
-       }
-+      return 0;
-+}
--      if (!min_rate || !max_rate) {
--              dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
--                      min_rate, max_rate);
--              return -EINVAL;
--      }
-+static int
-+raspberrypi_register_pll_divider(struct raspberrypi_clk *rpi,
-+                           const struct raspberrypi_pll_divider_data *data)
-+{
-+      struct raspberrypi_pll_divider *divider;
-+      struct clk_init_data init;
-+      int ret;
-+
-+      memset(&init, 0, sizeof(init));
-+
-+      init.parent_names = &data->source_pll;
-+      init.num_parents = 1;
-+      init.name = data->name;
-+      init.ops = &raspberrypi_firmware_pll_divider_clk_ops;
-+      init.flags = data->flags | CLK_IGNORE_UNUSED;
--      dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
--               min_rate, max_rate);
-+      divider = devm_kzalloc(rpi->dev, sizeof(*divider), GFP_KERNEL);
-+      if (!divider)
-+              return -ENOMEM;
-+
-+      divider->div.hw.init = &init;
-+      divider->rpi = rpi;
-+      divider->data = data;
-+
-+      ret = raspberrypi_get_clock_range(rpi, data->clock_id, &divider->min_rate, &divider->max_rate);
-+      if (ret) {
-+              dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
-+              return ret;
-+      }
--      rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
--      rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+      ret = devm_clk_hw_register(rpi->dev, &divider->div.hw);
-+      if (ret) {
-+              dev_err(rpi->dev, "%s: devm_clk_hw_register(%s) failed: %d\n", __func__, init.name, ret);
-+              return ret;
-+      }
--      rpi->pllb.init = &init;
-+      /*
-+       * PLLH's channels have a fixed divide by 10 afterwards, which
-+       * is what our consumers are actually using.
-+       */
-+      if (data->fixed_divider != 1) {
-+              struct clk_lookup *lookup;
-+              struct clk_hw *clk = clk_hw_register_fixed_factor(rpi->dev,
-+                                                  data->divider_name,
-+                                                  data->name,
-+                                                  CLK_SET_RATE_PARENT,
-+                                                  1,
-+                                                  data->fixed_divider);
-+              if (IS_ERR(clk)) {
-+                      dev_err(rpi->dev, "%s: clk_hw_register_fixed_factor(%s) failed: %ld\n", __func__, init.name, PTR_ERR(clk));
-+                      return PTR_ERR(clk);
-+              }
-+              if (data->lookup) {
-+                      lookup = clkdev_hw_create(clk, NULL, data->lookup);
-+                      if (IS_ERR(lookup)) {
-+                              dev_err(rpi->dev, "%s: clk_hw_register_fixed_factor(%s) failed: %ld\n", __func__, init.name, PTR_ERR(lookup));
-+                              return PTR_ERR(lookup);
-+                      }
-+              }
-+      }
--      return devm_clk_hw_register(rpi->dev, &rpi->pllb);
-+      return 0;
- }
--static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
-+static int raspberrypi_register_clock(struct raspberrypi_clk *rpi,
-+                                        const struct raspberrypi_clock_data *data)
- {
--      rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev,
--                              "pllb_arm", "pllb",
--                              CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
--                              1, 2);
--      if (IS_ERR(rpi->pllb_arm)) {
--              dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
--              return PTR_ERR(rpi->pllb_arm);
--      }
-+      struct raspberrypi_clock *clock;
-+      struct clk_init_data init;
-+      struct clk *clk;
-+      int ret;
-+
-+      memset(&init, 0, sizeof(init));
-+      init.parent_names = data->parents;
-+      init.num_parents = data->num_parents;
-+      init.name = data->name;
-+      init.flags = data->flags | CLK_IGNORE_UNUSED;
--      rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0");
--      if (!rpi->pllb_arm_lookup) {
--              dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
--              clk_hw_unregister_fixed_factor(rpi->pllb_arm);
-+      init.ops = &raspberrypi_firmware_clk_ops;
-+
-+      clock = devm_kzalloc(rpi->dev, sizeof(*clock), GFP_KERNEL);
-+      if (!clock)
-               return -ENOMEM;
--      }
-+      clock->rpi = rpi;
-+      clock->data = data;
-+      clock->hw.init = &init;
-+
-+      ret = raspberrypi_get_clock_range(rpi, data->clock_id, &clock->min_rate, &clock->max_rate);
-+      if (ret) {
-+              dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
-+              return ret;
-+      }
-+      clk = devm_clk_register(rpi->dev, &clock->hw);
-+      if (IS_ERR(clk)) {
-+              dev_err(rpi->dev, "%s: devm_clk_register(%s) failed: %ld\n", __func__, init.name, PTR_ERR(clk));
-+              return PTR_ERR(clk);
-+      }
-+      ret = clk_register_clkdev(clk, init.name, NULL);
-+      if (ret) {
-+              dev_err(rpi->dev, "%s: clk_register_clkdev(%s) failed: %d\n", __func__, init.name, ret);
-+              return ret;
-+      }
-       return 0;
- }
-+
-+/*
-+ * the real definition of all the pll, pll_dividers and clocks
-+ * these make use of the above REGISTER_* macros
-+ */
-+static const struct raspberrypi_clk_desc clk_desc_array[] = {
-+      /* the PLL + PLL dividers */
-+      [BCM2835_CLOCK_V3D]     = REGISTER_CLK(
-+              SOC_ALL,
-+              .name = "v3d",
-+              .parents = (const char *[]){ "osc" },
-+              .num_parents = 1,
-+              .clock_id = RPI_FIRMWARE_V3D_CLK_ID),
-+      [BCM2835_PLLB_ARM]      = REGISTER_PLL_DIV(
-+              SOC_ALL,
-+              .name = "pllb",
-+              .source_pll = "osc",
-+              .divider_name = "pllb_arm",
-+              .lookup = "cpu0",
-+              .fixed_divider = 2,
-+              .clock_id = RPI_FIRMWARE_ARM_CLK_ID,
-+              .flags = CLK_SET_RATE_PARENT),
-+};
-+
- static int raspberrypi_clk_probe(struct platform_device *pdev)
- {
-       struct device_node *firmware_node;
-       struct device *dev = &pdev->dev;
-       struct rpi_firmware *firmware;
-       struct raspberrypi_clk *rpi;
--      int ret;
-+      const struct raspberrypi_clk_desc *desc;
-+      const size_t asize = ARRAY_SIZE(clk_desc_array);
-+      int i;
-       firmware_node = of_find_compatible_node(NULL, NULL,
-                                       "raspberrypi,bcm2835-firmware");
-@@ -275,16 +594,16 @@ static int raspberrypi_clk_probe(struct
-       rpi->firmware = firmware;
-       platform_set_drvdata(pdev, rpi);
--      ret = raspberrypi_register_pllb(rpi);
--      if (ret) {
--              dev_err(dev, "Failed to initialize pllb, %d\n", ret);
--              return ret;
-+      for (i = 0; i < asize; i++) {
-+              desc = &clk_desc_array[i];
-+              if (desc->clk_register && desc->data /*&&
-+                  (desc->supported & pdata->soc)*/) {
-+                      int ret = desc->clk_register(rpi, desc->data);
-+                      if (ret)
-+                              return ret;
-+              }
-       }
--      ret = raspberrypi_register_pllb_arm(rpi);
--      if (ret)
--              return ret;
--
-       rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq",
-                                                    -1, NULL, 0);
diff --git a/target/linux/brcm2708/patches-4.19/950-0768-fixup-clk-raspberrypi-Also-support-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0768-fixup-clk-raspberrypi-Also-support-v3d-clock.patch
new file mode 100644 (file)
index 0000000..64efff7
--- /dev/null
@@ -0,0 +1,29 @@
+From c4374e446b6957234432d5c3f5d5f89f1acb807d Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 7 Nov 2019 12:25:27 +0000
+Subject: [PATCH] fixup! clk-raspberrypi: Also support v3d clock
+
+---
+ 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
+@@ -474,7 +474,7 @@ raspberrypi_register_pll_divider(struct
+        * PLLH's channels have a fixed divide by 10 afterwards, which
+        * is what our consumers are actually using.
+        */
+-      if (data->fixed_divider != 1) {
++      if (data->fixed_divider != 0) {
+               struct clk_lookup *lookup;
+               struct clk_hw *clk = clk_hw_register_fixed_factor(rpi->dev,
+                                                   data->divider_name,
+@@ -559,7 +559,7 @@ static const struct raspberrypi_clk_desc
+               .source_pll = "osc",
+               .divider_name = "pllb_arm",
+               .lookup = "cpu0",
+-              .fixed_divider = 2,
++              .fixed_divider = 1,
+               .clock_id = RPI_FIRMWARE_ARM_CLK_ID,
+               .flags = CLK_SET_RATE_PARENT),
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0769-clk-bcm2835-Disable-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0769-clk-bcm2835-Disable-v3d-clock.patch
deleted file mode 100644 (file)
index 34de4de..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From e8e99169991da84d59f1ed70de9621e31b67d505 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 3 Sep 2019 20:28:00 +0100
-Subject: [PATCH] clk-bcm2835: Disable v3d clock
-
-This is controlled by firmware, see clk-raspberrypi.c
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++------------------
- 1 file changed, 12 insertions(+), 18 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1725,16 +1725,12 @@ static const struct bcm2835_clk_desc clk
-               .hold_mask = CM_PLLA_HOLDCORE,
-               .fixed_divider = 1,
-               .flags = CLK_SET_RATE_PARENT),
--      [BCM2835_PLLA_PER]      = REGISTER_PLL_DIV(
--              SOC_ALL,
--              .name = "plla_per",
--              .source_pll = "plla",
--              .cm_reg = CM_PLLA,
--              .a2w_reg = A2W_PLLA_PER,
--              .load_mask = CM_PLLA_LOADPER,
--              .hold_mask = CM_PLLA_HOLDPER,
--              .fixed_divider = 1,
--              .flags = CLK_SET_RATE_PARENT),
-+
-+      /*
-+       * PLLA_PER is used for gpu clocks. Controlled by firmware, see
-+       * clk-raspberrypi.c.
-+       */
-+
-       [BCM2835_PLLA_DSI0]     = REGISTER_PLL_DIV(
-               SOC_ALL,
-               .name = "plla_dsi0",
-@@ -2007,14 +2003,12 @@ static const struct bcm2835_clk_desc clk
-               .int_bits = 6,
-               .frac_bits = 0,
-               .tcnt_mux = 3),
--      [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
--              SOC_ALL,
--              .name = "v3d",
--              .ctl_reg = CM_V3DCTL,
--              .div_reg = CM_V3DDIV,
--              .int_bits = 4,
--              .frac_bits = 8,
--              .tcnt_mux = 4),
-+
-+      /*
-+       * CLOCK_V3D is used for v3d clock. Controlled by firmware, see
-+       * clk-raspberrypi.c.
-+       */
-+
-       /*
-        * VPU clock.  This doesn't have an enable bit, since it drives
-        * the bus for everything else, and is special so it doesn't need
diff --git a/target/linux/brcm2708/patches-4.19/950-0769-fixup-clk-raspberrypi-Also-support-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0769-fixup-clk-raspberrypi-Also-support-v3d-clock.patch
new file mode 100644 (file)
index 0000000..a15f41f
--- /dev/null
@@ -0,0 +1,36 @@
+From 05c745c001c8c82bbba8a6d953ad77ad25c92c5f Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 7 Nov 2019 14:11:08 +0000
+Subject: [PATCH] fixup! clk-raspberrypi: Also support v3d clock
+
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -351,21 +351,21 @@ static const struct clk_ops raspberrypi_
+       .is_prepared = raspberrypi_fw_pll_is_on,
+       .recalc_rate = raspberrypi_fw_pll_get_rate,
+       .set_rate = raspberrypi_fw_pll_set_rate,
+-      .determine_rate = raspberrypi_pll_determine_rate,
++      //.determine_rate = raspberrypi_pll_determine_rate,
+ };
+ static const struct clk_ops raspberrypi_firmware_pll_divider_clk_ops = {
+       .is_prepared = raspberrypi_fw_pll_div_is_on,
+       .recalc_rate = raspberrypi_fw_pll_div_get_rate,
+       .set_rate = raspberrypi_fw_pll_div_set_rate,
+-      .determine_rate = raspberrypi_pll_div_determine_rate,
++      //.determine_rate = raspberrypi_pll_div_determine_rate,
+ };
+ static const struct clk_ops raspberrypi_firmware_clk_ops = {
+       .is_prepared = raspberrypi_fw_clock_is_on,
+       .recalc_rate = raspberrypi_fw_clock_get_rate,
+       .set_rate = raspberrypi_fw_clock_set_rate,
+-      .determine_rate = raspberrypi_clock_determine_rate,
++      //.determine_rate = raspberrypi_clock_determine_rate,
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0770-fixup-clk-raspberrypi-Also-support-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0770-fixup-clk-raspberrypi-Also-support-v3d-clock.patch
deleted file mode 100644 (file)
index 64efff7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From c4374e446b6957234432d5c3f5d5f89f1acb807d Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Thu, 7 Nov 2019 12:25:27 +0000
-Subject: [PATCH] fixup! clk-raspberrypi: Also support v3d clock
-
----
- 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
-@@ -474,7 +474,7 @@ raspberrypi_register_pll_divider(struct
-        * PLLH's channels have a fixed divide by 10 afterwards, which
-        * is what our consumers are actually using.
-        */
--      if (data->fixed_divider != 1) {
-+      if (data->fixed_divider != 0) {
-               struct clk_lookup *lookup;
-               struct clk_hw *clk = clk_hw_register_fixed_factor(rpi->dev,
-                                                   data->divider_name,
-@@ -559,7 +559,7 @@ static const struct raspberrypi_clk_desc
-               .source_pll = "osc",
-               .divider_name = "pllb_arm",
-               .lookup = "cpu0",
--              .fixed_divider = 2,
-+              .fixed_divider = 1,
-               .clock_id = RPI_FIRMWARE_ARM_CLK_ID,
-               .flags = CLK_SET_RATE_PARENT),
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0770-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch b/target/linux/brcm2708/patches-4.19/950-0770-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch
new file mode 100644 (file)
index 0000000..04406c8
--- /dev/null
@@ -0,0 +1,40 @@
+From 1c038a58f4183602fc1699d68b21f5e22a12176d 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;
index a15f41f45a0b57a2586b9a62627d90d89ddd1d92..0239b19ff22c435f15339ab4950500b56680be6c 100644 (file)
@@ -1,36 +1,54 @@
-From 05c745c001c8c82bbba8a6d953ad77ad25c92c5f Mon Sep 17 00:00:00 2001
+From afb2cfe3056fc643cee8ae25991f4b9c22d48bef Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix@gmail.com>
-Date: Thu, 7 Nov 2019 14:11:08 +0000
+Date: Thu, 7 Nov 2019 14:23:38 +0000
 Subject: [PATCH] fixup! clk-raspberrypi: Also support v3d clock
 
 ---
- drivers/clk/bcm/clk-raspberrypi.c | +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
+ drivers/clk/bcm/clk-raspberrypi.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
 
 --- a/drivers/clk/bcm/clk-raspberrypi.c
 +++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -351,21 +351,21 @@ static const struct clk_ops raspberrypi_
+@@ -208,6 +208,9 @@ static int raspberrypi_determine_rate(st
+                                         u32 clock_id, const char *name, unsigned long min_rate, unsigned long max_rate,
+                                         struct clk_rate_request *req)
+ {
++#if 1
++      req->rate = clamp(req->rate, min_rate, max_rate);
++#else
+       u64 div, final_rate;
+       u32 ndiv, fdiv;
+@@ -225,6 +228,7 @@ static int raspberrypi_determine_rate(st
+       req->rate = final_rate >> A2W_PLL_FRAC_BITS;
++#endif
+       return 0;
+ }
+@@ -351,21 +355,21 @@ static const struct clk_ops raspberrypi_
        .is_prepared = raspberrypi_fw_pll_is_on,
        .recalc_rate = raspberrypi_fw_pll_get_rate,
        .set_rate = raspberrypi_fw_pll_set_rate,
--      .determine_rate = raspberrypi_pll_determine_rate,
-+      //.determine_rate = raspberrypi_pll_determine_rate,
+-      //.determine_rate = raspberrypi_pll_determine_rate,
++      .determine_rate = raspberrypi_pll_determine_rate,
  };
  
  static const struct clk_ops raspberrypi_firmware_pll_divider_clk_ops = {
        .is_prepared = raspberrypi_fw_pll_div_is_on,
        .recalc_rate = raspberrypi_fw_pll_div_get_rate,
        .set_rate = raspberrypi_fw_pll_div_set_rate,
--      .determine_rate = raspberrypi_pll_div_determine_rate,
-+      //.determine_rate = raspberrypi_pll_div_determine_rate,
+-      //.determine_rate = raspberrypi_pll_div_determine_rate,
++      .determine_rate = raspberrypi_pll_div_determine_rate,
  };
  
  static const struct clk_ops raspberrypi_firmware_clk_ops = {
        .is_prepared = raspberrypi_fw_clock_is_on,
        .recalc_rate = raspberrypi_fw_clock_get_rate,
        .set_rate = raspberrypi_fw_clock_set_rate,
--      .determine_rate = raspberrypi_clock_determine_rate,
-+      //.determine_rate = raspberrypi_clock_determine_rate,
+-      //.determine_rate = raspberrypi_clock_determine_rate,
++      .determine_rate = raspberrypi_clock_determine_rate,
  };
  
  
diff --git a/target/linux/brcm2708/patches-4.19/950-0772-arm-dts-Correct-Pi-4B-LED-values.patch b/target/linux/brcm2708/patches-4.19/950-0772-arm-dts-Correct-Pi-4B-LED-values.patch
new file mode 100644 (file)
index 0000000..4f2e46b
--- /dev/null
@@ -0,0 +1,39 @@
+From ea1e25b4c0a055b31a0217ffbfd6972c28643912 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 22 Nov 2019 15:08:25 +0000
+Subject: [PATCH] arm/dts: Correct Pi 4B LED values
+
+The initial PHY LED settings are wrong Pi 4B (the correct values got
+dropped somewhere along the way). The PHY declaration should arguably
+go in a separate file included by bcm2711-rpi-4-b.dts, but we can
+fix that as we switch over to using more of the upstream BCM2711
+support in 5.4 and later.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi    | 2 +-
+ arch/arm/boot/dts/overlays/README | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -380,7 +380,7 @@
+                                       /* No interrupts - use PHY_POLL */
+                                       max-speed = <1000>;
+                                       reg = <0x1>;
+-                                      led-modes = <0x02 0x02>;
++                                      led-modes = <0x00 0x08>; /* link/activity link */
+                               };
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -128,7 +128,7 @@ Params:
+                                 8=Link                   9=Activity
+         eth_led1                Set mode of LED1 (usually green) (Pi3B+ default
+-                                "6", Pi4 default "0"). See eth_led0 for legal
++                                "6", Pi4 default "8"). See eth_led0 for legal
+                                 values.
+         eth_max_speed           Set the maximum speed a link is allowed
diff --git a/target/linux/brcm2708/patches-4.19/950-0772-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch b/target/linux/brcm2708/patches-4.19/950-0772-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch
deleted file mode 100644 (file)
index 04406c8..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From 1c038a58f4183602fc1699d68b21f5e22a12176d 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;
diff --git a/target/linux/brcm2708/patches-4.19/950-0773-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch b/target/linux/brcm2708/patches-4.19/950-0773-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch
new file mode 100644 (file)
index 0000000..313aa8c
--- /dev/null
@@ -0,0 +1,25 @@
+From 75e50217c8c8d9ab8dc84547fd149d9bfe32ae5d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 22 Nov 2019 16:23:32 +0000
+Subject: [PATCH] drm/v3d: Set dma_mask as well as coherent_dma_mask
+
+Both coherent_dma_mask and dma_mask act as constraints on allocations
+and bounce buffer usage, so be sure to set dma_mask to the appropriate
+value otherwise the effective mask could be incorrect.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -261,7 +261,7 @@ static int v3d_platform_drm_probe(struct
+       int ret;
+       u32 ident1;
+-      dev->coherent_dma_mask = DMA_BIT_MASK(36);
++      dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
+       v3d = kzalloc(sizeof(*v3d), GFP_KERNEL);
+       if (!v3d)
diff --git a/target/linux/brcm2708/patches-4.19/950-0773-fixup-clk-raspberrypi-Also-support-v3d-clock.patch b/target/linux/brcm2708/patches-4.19/950-0773-fixup-clk-raspberrypi-Also-support-v3d-clock.patch
deleted file mode 100644 (file)
index 0239b19..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From afb2cfe3056fc643cee8ae25991f4b9c22d48bef Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Thu, 7 Nov 2019 14:23:38 +0000
-Subject: [PATCH] fixup! clk-raspberrypi: Also support v3d clock
-
----
- drivers/clk/bcm/clk-raspberrypi.c | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
---- a/drivers/clk/bcm/clk-raspberrypi.c
-+++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -208,6 +208,9 @@ static int raspberrypi_determine_rate(st
-                                         u32 clock_id, const char *name, unsigned long min_rate, unsigned long max_rate,
-                                         struct clk_rate_request *req)
- {
-+#if 1
-+      req->rate = clamp(req->rate, min_rate, max_rate);
-+#else
-       u64 div, final_rate;
-       u32 ndiv, fdiv;
-@@ -225,6 +228,7 @@ static int raspberrypi_determine_rate(st
-       req->rate = final_rate >> A2W_PLL_FRAC_BITS;
-+#endif
-       return 0;
- }
-@@ -351,21 +355,21 @@ static const struct clk_ops raspberrypi_
-       .is_prepared = raspberrypi_fw_pll_is_on,
-       .recalc_rate = raspberrypi_fw_pll_get_rate,
-       .set_rate = raspberrypi_fw_pll_set_rate,
--      //.determine_rate = raspberrypi_pll_determine_rate,
-+      .determine_rate = raspberrypi_pll_determine_rate,
- };
- static const struct clk_ops raspberrypi_firmware_pll_divider_clk_ops = {
-       .is_prepared = raspberrypi_fw_pll_div_is_on,
-       .recalc_rate = raspberrypi_fw_pll_div_get_rate,
-       .set_rate = raspberrypi_fw_pll_div_set_rate,
--      //.determine_rate = raspberrypi_pll_div_determine_rate,
-+      .determine_rate = raspberrypi_pll_div_determine_rate,
- };
- static const struct clk_ops raspberrypi_firmware_clk_ops = {
-       .is_prepared = raspberrypi_fw_clock_is_on,
-       .recalc_rate = raspberrypi_fw_clock_get_rate,
-       .set_rate = raspberrypi_fw_clock_set_rate,
--      //.determine_rate = raspberrypi_clock_determine_rate,
-+      .determine_rate = raspberrypi_clock_determine_rate,
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0774-arm-dts-2711-Add-pcie0-alias.patch b/target/linux/brcm2708/patches-4.19/950-0774-arm-dts-2711-Add-pcie0-alias.patch
new file mode 100644 (file)
index 0000000..1f86f9d
--- /dev/null
@@ -0,0 +1,24 @@
+From 11febee7b0326ade03f45238f136b7830d317e2e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 28 Nov 2019 15:49:08 +0000
+Subject: [PATCH] arm/dts: 2711: Add 'pcie0' alias
+
+It is useful for the firmware to be able to locate the pcie DT node,
+so add an alias pointing to it in the same way that "ethernet0"
+points to the genet.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -30,6 +30,7 @@
+               /delete-property/ ethernet;
+               /delete-property/ intc;
+               ethernet0 = &genet;
++              pcie0 = &pcie_0;
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0774-arm-dts-Correct-Pi-4B-LED-values.patch b/target/linux/brcm2708/patches-4.19/950-0774-arm-dts-Correct-Pi-4B-LED-values.patch
deleted file mode 100644 (file)
index 4f2e46b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From ea1e25b4c0a055b31a0217ffbfd6972c28643912 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 22 Nov 2019 15:08:25 +0000
-Subject: [PATCH] arm/dts: Correct Pi 4B LED values
-
-The initial PHY LED settings are wrong Pi 4B (the correct values got
-dropped somewhere along the way). The PHY declaration should arguably
-go in a separate file included by bcm2711-rpi-4-b.dts, but we can
-fix that as we switch over to using more of the upstream BCM2711
-support in 5.4 and later.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2838.dtsi    | 2 +-
- arch/arm/boot/dts/overlays/README | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -380,7 +380,7 @@
-                                       /* No interrupts - use PHY_POLL */
-                                       max-speed = <1000>;
-                                       reg = <0x1>;
--                                      led-modes = <0x02 0x02>;
-+                                      led-modes = <0x00 0x08>; /* link/activity link */
-                               };
-                       };
-               };
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -128,7 +128,7 @@ Params:
-                                 8=Link                   9=Activity
-         eth_led1                Set mode of LED1 (usually green) (Pi3B+ default
--                                "6", Pi4 default "0"). See eth_led0 for legal
-+                                "6", Pi4 default "8"). See eth_led0 for legal
-                                 values.
-         eth_max_speed           Set the maximum speed a link is allowed
diff --git a/target/linux/brcm2708/patches-4.19/950-0775-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch b/target/linux/brcm2708/patches-4.19/950-0775-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch
deleted file mode 100644 (file)
index 313aa8c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 75e50217c8c8d9ab8dc84547fd149d9bfe32ae5d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 22 Nov 2019 16:23:32 +0000
-Subject: [PATCH] drm/v3d: Set dma_mask as well as coherent_dma_mask
-
-Both coherent_dma_mask and dma_mask act as constraints on allocations
-and bounce buffer usage, so be sure to set dma_mask to the appropriate
-value otherwise the effective mask could be incorrect.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -261,7 +261,7 @@ static int v3d_platform_drm_probe(struct
-       int ret;
-       u32 ident1;
--      dev->coherent_dma_mask = DMA_BIT_MASK(36);
-+      dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
-       v3d = kzalloc(sizeof(*v3d), GFP_KERNEL);
-       if (!v3d)
diff --git a/target/linux/brcm2708/patches-4.19/950-0775-spidev-Completely-disable-the-DT-warning.patch b/target/linux/brcm2708/patches-4.19/950-0775-spidev-Completely-disable-the-DT-warning.patch
new file mode 100644 (file)
index 0000000..c320527
--- /dev/null
@@ -0,0 +1,32 @@
+From ce0e4cf60033eb7e15266b329183f945f2a82c61 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 2 Dec 2019 10:28:44 +0000
+Subject: [PATCH] spidev: Completely disable the DT warning
+
+The upstream SPI and DT maintainers are completely opposed to declaring
+in Device Tree that an SPI CS line is to be managed by the spidev
+driver, even though the facility is useful on a hobbyist device like a
+Raspberry Pi where arbitrary devices can be attached, and the
+alternative to DT declaration (spi_board_info) has been almost entirely
+rendered obsolete by DT.
+
+Continue to override their objections by disabling the warning.
+
+See: https://github.com/raspberrypi/linux/issues/3361
+     https://github.com/raspberrypi/linux/issues/1054
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/spi/spidev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/spi/spidev.c
++++ b/drivers/spi/spidev.c
+@@ -728,6 +728,7 @@ static int spidev_probe(struct spi_devic
+        * compatible string, it is a Linux implementation thing
+        * rather than a description of the hardware.
+        */
++      if (0) /* Disable the warning - this feature is too useful */
+       WARN(spi->dev.of_node &&
+            of_device_is_compatible(spi->dev.of_node, "spidev"),
+            "%pOF: buggy DT: spidev listed directly in DT\n", spi->dev.of_node);
diff --git a/target/linux/brcm2708/patches-4.19/950-0776-arm-dts-2711-Add-pcie0-alias.patch b/target/linux/brcm2708/patches-4.19/950-0776-arm-dts-2711-Add-pcie0-alias.patch
deleted file mode 100644 (file)
index 1f86f9d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 11febee7b0326ade03f45238f136b7830d317e2e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 28 Nov 2019 15:49:08 +0000
-Subject: [PATCH] arm/dts: 2711: Add 'pcie0' alias
-
-It is useful for the firmware to be able to locate the pcie DT node,
-so add an alias pointing to it in the same way that "ethernet0"
-points to the genet.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -30,6 +30,7 @@
-               /delete-property/ ethernet;
-               /delete-property/ intc;
-               ethernet0 = &genet;
-+              pcie0 = &pcie_0;
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0776-drm-vc4-Disable-V3D-interactions-if-the-v3d-componen.patch b/target/linux/brcm2708/patches-4.19/950-0776-drm-vc4-Disable-V3D-interactions-if-the-v3d-componen.patch
new file mode 100644 (file)
index 0000000..afc94da
--- /dev/null
@@ -0,0 +1,197 @@
+From 7140cf0d83c10f93ca8212edb17697baf9cafb45 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 1 Apr 2019 11:35:59 -0700
+Subject: [PATCH] drm/vc4: Disable V3D interactions if the v3d
+ component didn't probe.
+
+Commit ffc26740714962e3e8801dca7ef32b636b3781db upstream.
+
+One might want to use the VC4 display stack without using Mesa.
+Similar to the debugfs fixes for not having all of the possible
+display bits enabled, make sure you can't oops in vc4 if v3d isn't
+enabled.
+
+v2: Fix matching against other v3d variants (review by Paul), don't
+    forget to set irq_enabled so that the vblank uapi works
+v3: Use -ENODEV instead of -EINVAL on Paul's suggestion.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190401183559.3823-2-eric@anholt.net
+Reviewed-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+---
+ drivers/gpu/drm/vc4/vc4_drv.c     | 10 ++++++++++
+ drivers/gpu/drm/vc4/vc4_drv.h     |  1 +
+ drivers/gpu/drm/vc4/vc4_gem.c     | 10 ++++++++++
+ drivers/gpu/drm/vc4/vc4_irq.c     |  9 +++++++++
+ drivers/gpu/drm/vc4/vc4_perfmon.c | 18 ++++++++++++++++++
+ drivers/gpu/drm/vc4/vc4_v3d.c     |  2 +-
+ 6 files changed, 49 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_drv.c
++++ b/drivers/gpu/drm/vc4/vc4_drv.c
+@@ -71,6 +71,9 @@ static int vc4_get_param_ioctl(struct dr
+       if (args->pad != 0)
+               return -EINVAL;
++      if (!vc4->v3d)
++              return -ENODEV;
++
+       switch (args->param) {
+       case DRM_VC4_PARAM_V3D_IDENT0:
+               ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
+@@ -271,6 +274,7 @@ static int vc4_drm_bind(struct device *d
+       struct platform_device *pdev = to_platform_device(dev);
+       struct drm_device *drm;
+       struct vc4_dev *vc4;
++      struct device_node *node;
+       int ret = 0;
+       dev->coherent_dma_mask = DMA_BIT_MASK(32);
+@@ -279,6 +283,12 @@ static int vc4_drm_bind(struct device *d
+       if (!vc4)
+               return -ENOMEM;
++      /* If VC4 V3D is missing, don't advertise render nodes. */
++      node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL);
++      if (!node || !of_device_is_available(node))
++              vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
++      of_node_put(node);
++
+       drm = drm_dev_alloc(&vc4_drm_driver, dev);
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -787,6 +787,7 @@ void vc4_plane_async_set_fb(struct drm_p
+ /* vc4_v3d.c */
+ extern struct platform_driver vc4_v3d_driver;
++extern const struct of_device_id vc4_v3d_dt_match[];
+ int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
+ int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
+ int vc4_v3d_get_bin_slot(struct vc4_dev *vc4);
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -74,6 +74,11 @@ vc4_get_hang_state_ioctl(struct drm_devi
+       u32 i;
+       int ret = 0;
++      if (!vc4->v3d) {
++              DRM_DEBUG("VC4_GET_HANG_STATE with no VC4 V3D probed\n");
++              return -ENODEV;
++      }
++
+       spin_lock_irqsave(&vc4->job_lock, irqflags);
+       kernel_state = vc4->hang_state;
+       if (!kernel_state) {
+@@ -1124,6 +1129,11 @@ vc4_submit_cl_ioctl(struct drm_device *d
+       struct dma_fence *in_fence;
+       int ret = 0;
++      if (!vc4->v3d) {
++              DRM_DEBUG("VC4_SUBMIT_CL with no VC4 V3D probed\n");
++              return -ENODEV;
++      }
++
+       if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR |
+                            VC4_SUBMIT_CL_FIXED_RCL_ORDER |
+                            VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X |
+--- a/drivers/gpu/drm/vc4/vc4_irq.c
++++ b/drivers/gpu/drm/vc4/vc4_irq.c
+@@ -229,6 +229,9 @@ vc4_irq_preinstall(struct drm_device *de
+ {
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
++      if (!vc4->v3d)
++              return;
++
+       init_waitqueue_head(&vc4->job_wait_queue);
+       INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
+@@ -243,6 +246,9 @@ vc4_irq_postinstall(struct drm_device *d
+ {
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
++      if (!vc4->v3d)
++              return 0;
++
+       /* Enable both the render done and out of memory interrupts. */
+       V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
+@@ -254,6 +260,9 @@ vc4_irq_uninstall(struct drm_device *dev
+ {
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
++      if (!vc4->v3d)
++              return;
++
+       /* Disable sending interrupts for our driver's IRQs. */
+       V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS);
+--- a/drivers/gpu/drm/vc4/vc4_perfmon.c
++++ b/drivers/gpu/drm/vc4/vc4_perfmon.c
+@@ -100,12 +100,18 @@ void vc4_perfmon_close_file(struct vc4_f
+ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv)
+ {
++      struct vc4_dev *vc4 = to_vc4_dev(dev);
+       struct vc4_file *vc4file = file_priv->driver_priv;
+       struct drm_vc4_perfmon_create *req = data;
+       struct vc4_perfmon *perfmon;
+       unsigned int i;
+       int ret;
++      if (!vc4->v3d) {
++              DRM_DEBUG("Creating perfmon no VC4 V3D probed\n");
++              return -ENODEV;
++      }
++
+       /* Number of monitored counters cannot exceed HW limits. */
+       if (req->ncounters > DRM_VC4_MAX_PERF_COUNTERS ||
+           !req->ncounters)
+@@ -146,10 +152,16 @@ int vc4_perfmon_create_ioctl(struct drm_
+ int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+ {
++      struct vc4_dev *vc4 = to_vc4_dev(dev);
+       struct vc4_file *vc4file = file_priv->driver_priv;
+       struct drm_vc4_perfmon_destroy *req = data;
+       struct vc4_perfmon *perfmon;
++      if (!vc4->v3d) {
++              DRM_DEBUG("Destroying perfmon no VC4 V3D probed\n");
++              return -ENODEV;
++      }
++
+       mutex_lock(&vc4file->perfmon.lock);
+       perfmon = idr_remove(&vc4file->perfmon.idr, req->id);
+       mutex_unlock(&vc4file->perfmon.lock);
+@@ -164,11 +176,17 @@ int vc4_perfmon_destroy_ioctl(struct drm
+ int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+ {
++      struct vc4_dev *vc4 = to_vc4_dev(dev);
+       struct vc4_file *vc4file = file_priv->driver_priv;
+       struct drm_vc4_perfmon_get_values *req = data;
+       struct vc4_perfmon *perfmon;
+       int ret;
++      if (!vc4->v3d) {
++              DRM_DEBUG("Getting perfmon no VC4 V3D probed\n");
++              return -ENODEV;
++      }
++
+       mutex_lock(&vc4file->perfmon.lock);
+       perfmon = idr_find(&vc4file->perfmon.idr, req->id);
+       vc4_perfmon_get(perfmon);
+--- a/drivers/gpu/drm/vc4/vc4_v3d.c
++++ b/drivers/gpu/drm/vc4/vc4_v3d.c
+@@ -452,7 +452,7 @@ static int vc4_v3d_dev_remove(struct pla
+       return 0;
+ }
+-static const struct of_device_id vc4_v3d_dt_match[] = {
++const struct of_device_id vc4_v3d_dt_match[] = {
+       { .compatible = "brcm,bcm2835-v3d" },
+       { .compatible = "brcm,cygnus-v3d" },
+       { .compatible = "brcm,vc4-v3d" },
diff --git a/target/linux/brcm2708/patches-4.19/950-0777-sound-soc-only-first-codec-is-master-in-multicodec-s.patch b/target/linux/brcm2708/patches-4.19/950-0777-sound-soc-only-first-codec-is-master-in-multicodec-s.patch
new file mode 100644 (file)
index 0000000..dcfbb9d
--- /dev/null
@@ -0,0 +1,34 @@
+From 4ca89eb8570cb86314a5a7b55a15d15f53ce5757 Mon Sep 17 00:00:00 2001
+From: Johannes Krude <johannes@krude.de>
+Date: Sat, 16 Nov 2019 12:41:06 +0100
+Subject: [PATCH] sound/soc: only first codec is master in multicodec
+ setup
+
+When using multiple codecs, at most one codec should generate the master
+clock. All codecs except the first are therefore configured for slave
+mode.
+
+Signed-off-by: Johannes Krude <johannes@krude.de>
+---
+ sound/soc/soc-core.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -1688,8 +1688,15 @@ int snd_soc_runtime_set_dai_fmt(struct s
+       for (i = 0; i < rtd->num_codecs; i++) {
+               struct snd_soc_dai *codec_dai = codec_dais[i];
++              unsigned int codec_dai_fmt = dai_fmt;
+-              ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
++              // there can only be one master when using multiple codecs
++              if (i && (codec_dai_fmt & SND_SOC_DAIFMT_MASTER_MASK)) {
++                      codec_dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
++                      codec_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
++              }
++
++              ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
+               if (ret != 0 && ret != -ENOTSUPP) {
+                       dev_warn(codec_dai->dev,
+                                "ASoC: Failed to set DAI format: %d\n", ret);
diff --git a/target/linux/brcm2708/patches-4.19/950-0777-spidev-Completely-disable-the-DT-warning.patch b/target/linux/brcm2708/patches-4.19/950-0777-spidev-Completely-disable-the-DT-warning.patch
deleted file mode 100644 (file)
index c320527..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From ce0e4cf60033eb7e15266b329183f945f2a82c61 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 2 Dec 2019 10:28:44 +0000
-Subject: [PATCH] spidev: Completely disable the DT warning
-
-The upstream SPI and DT maintainers are completely opposed to declaring
-in Device Tree that an SPI CS line is to be managed by the spidev
-driver, even though the facility is useful on a hobbyist device like a
-Raspberry Pi where arbitrary devices can be attached, and the
-alternative to DT declaration (spi_board_info) has been almost entirely
-rendered obsolete by DT.
-
-Continue to override their objections by disabling the warning.
-
-See: https://github.com/raspberrypi/linux/issues/3361
-     https://github.com/raspberrypi/linux/issues/1054
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/spi/spidev.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/spi/spidev.c
-+++ b/drivers/spi/spidev.c
-@@ -728,6 +728,7 @@ static int spidev_probe(struct spi_devic
-        * compatible string, it is a Linux implementation thing
-        * rather than a description of the hardware.
-        */
-+      if (0) /* Disable the warning - this feature is too useful */
-       WARN(spi->dev.of_node &&
-            of_device_is_compatible(spi->dev.of_node, "spidev"),
-            "%pOF: buggy DT: spidev listed directly in DT\n", spi->dev.of_node);
diff --git a/target/linux/brcm2708/patches-4.19/950-0778-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch b/target/linux/brcm2708/patches-4.19/950-0778-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch
new file mode 100644 (file)
index 0000000..c8b4820
--- /dev/null
@@ -0,0 +1,435 @@
+From 8f11db84e124da59b8a717d66fc424ef070f4be0 Mon Sep 17 00:00:00 2001
+From: Johannes Krude <johannes@krude.de>
+Date: Sat, 16 Nov 2019 13:14:43 +0100
+Subject: [PATCH] Allow simultaneous use of JustBoom DAC and Digi
+
+Signed-off-by: Johannes Krude <johannes@krude.de>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  20 ++
+ .../dts/overlays/justboom-both-overlay.dts    |  65 +++++
+ sound/soc/bcm/Kconfig                         |  12 +
+ sound/soc/bcm/Makefile                        |   2 +
+ sound/soc/bcm/justboom-both.c                 | 269 ++++++++++++++++++
+ 11 files changed, 374 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/justboom-both-overlay.dts
+ create mode 100644 sound/soc/bcm/justboom-both.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -86,6 +86,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       iqaudio-digi-wm8804-audio.dtbo \
+       irs1125.dtbo \
+       jedec-spi-nor.dtbo \
++      justboom-both.dtbo \
+       justboom-dac.dtbo \
+       justboom-digi.dtbo \
+       ltc294x.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1388,6 +1388,26 @@ Params: flash-spi<n>-<m>        Enables
+                                 on SPI<n>, CS#<m>.
++Name:   justboom-both
++Info:   Simultaneous usage of an justboom-dac and justboom-digi based
++        card
++Load:   dtoverlay=justboom-both,<param>=<val>
++Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
++                                Digital volume control. Enable with
++                                "dtoverlay=justboom-dac,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!)
++
++
+ Name:   justboom-dac
+ Info:   Configures the JustBoom DAC HAT, Amp HAT, DAC Zero and Amp Zero audio
+         cards
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/justboom-both-overlay.dts
+@@ -0,0 +1,65 @@
++// SPDX-License-Identifier: GPL-2.0
++// Definitions for JustBoom Both (Digi+DAC)
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      wm8804@3b {
++                              #sound-dai-cells = <0>;
++                              compatible = "wlf,wm8804";
++                              reg = <0x3b>;
++                              PVDD-supply = <&vdd_3v3_reg>;
++                              DVDD-supply = <&vdd_3v3_reg>;
++                              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>;
++                              AVDD-supply = <&vdd_3v3_reg>;
++                              DVDD-supply = <&vdd_3v3_reg>;
++                              CPVDD-supply = <&vdd_3v3_reg>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&sound>;
++              frag3: __overlay__ {
++                      compatible = "justboom,justboom-both";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++
++      __overrides__ {
++              24db_digital_gain = <&frag3>,"justboom,24db_digital_gain?";
++      };
++};
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -102,6 +102,18 @@ config SND_BCM2708_SOC_RPI_PROTO
+       help
+         Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
++config SND_BCM2708_SOC_JUSTBOOM_BOTH
++      tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
++      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++      select SND_SOC_WM8804
++      select SND_SOC_PCM512x
++      help
++              Say Y or M if you want to add support for simultaneous
++              JustBoom Digi and JustBoom DAC.
++
++              This is not the right choice if you only have one but both of
++              these cards.
++
+ config SND_BCM2708_SOC_JUSTBOOM_DAC
+       tristate "Support for JustBoom DAC"
+       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -16,6 +16,7 @@ snd-soc-hifiberry-dacplus-objs := hifibe
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
+ snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
++snd-soc-justboom-both-objs := justboom-both.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
++obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH) += snd-soc-justboom-both.o
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+--- /dev/null
++++ b/sound/soc/bcm/justboom-both.c
+@@ -0,0 +1,269 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
++ *
++ * Authors: Johannes Krude <johannes@krude.de
++ *
++ * Driver for when connecting simultaneously justboom-digi and justboom-dac
++ *
++ * Based upon code from:
++ * justboom-digi.c
++ * by Milan Neskovic <info@justboom.co>
++ * justboom-dac.c
++ * by Milan Neskovic <info@justboom.co>
++ *
++ * 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 <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#include "../codecs/wm8804.h"
++#include "../codecs/pcm512x.h"
++
++
++static bool digital_gain_0db_limit = true;
++
++static int snd_rpi_justboom_both_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++      struct snd_soc_component *dac = rtd->codec_dais[1]->component;
++
++      /* enable  TX output */
++      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
++
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++      if (digital_gain_0db_limit) {
++              int ret;
++              struct snd_soc_card *card = rtd->card;
++
++              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);
++      }
++
++      return 0;
++}
++
++static int snd_rpi_justboom_both_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 *codec_dai = rtd->codec_dai;
++      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++
++      int sysclk = 27000000; /* This is fixed on this board */
++
++      long mclk_freq    = 0;
++      int mclk_div      = 1;
++      int sampling_freq = 1;
++
++      int ret;
++
++      int samplerate = params_rate(params);
++
++      if (samplerate <= 96000) {
++              mclk_freq = samplerate*256;
++              mclk_div  = WM8804_MCLKDIV_256FS;
++      } else {
++              mclk_freq = samplerate*128;
++              mclk_div  = WM8804_MCLKDIV_128FS;
++      }
++
++      switch (samplerate) {
++      case 32000:
++              sampling_freq = 0x03;
++              break;
++      case 44100:
++              sampling_freq = 0x00;
++              break;
++      case 48000:
++              sampling_freq = 0x02;
++              break;
++      case 88200:
++              sampling_freq = 0x08;
++              break;
++      case 96000:
++              sampling_freq = 0x0a;
++              break;
++      case 176400:
++              sampling_freq = 0x0c;
++              break;
++      case 192000:
++              sampling_freq = 0x0e;
++              break;
++      default:
++              dev_err(rtd->card->dev,
++              "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
++              samplerate);
++      }
++
++      snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
++      snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
++
++      ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
++                                      sysclk, SND_SOC_CLOCK_OUT);
++      if (ret < 0) {
++              dev_err(rtd->card->dev,
++              "Failed to set WM8804 SYSCLK: %d\n", ret);
++              return ret;
++      }
++
++      /* Enable TX output */
++      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
++
++      /* Power on */
++      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x9, 0);
++
++      /* set sampling frequency status bits */
++      snd_soc_component_update_bits(digi, WM8804_SPDTX4, 0x0f, sampling_freq);
++
++      return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
++}
++
++static int snd_rpi_justboom_both_startup(struct snd_pcm_substream *substream)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++      struct snd_soc_component *dac = rtd->codec_dais[1]->component;
++
++      /* turn on digital output */
++      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x00);
++
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++      return 0;
++}
++
++static void snd_rpi_justboom_both_shutdown(struct snd_pcm_substream *substream)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++      struct snd_soc_component *dac = rtd->codec_dais[1]->component;
++
++      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++
++      /* turn off output */
++      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x3c);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_justboom_both_ops = {
++      .hw_params = snd_rpi_justboom_both_hw_params,
++      .startup   = snd_rpi_justboom_both_startup,
++      .shutdown  = snd_rpi_justboom_both_shutdown,
++};
++
++static struct snd_soc_dai_link_component justboom_both_codecs[] = {
++{
++      .dai_name = "wm8804-spdif",
++      .name     = "wm8804.1-003b",
++},
++{
++      .dai_name = "pcm512x-hifi",
++      .name     = "pcm512x.1-004d",
++},
++};
++
++static struct snd_soc_dai_link snd_rpi_justboom_both_dai[] = {
++{
++      .name           = "JustBoom Digi",
++      .stream_name    = "JustBoom Digi HiFi",
++      .cpu_dai_name   = "bcm2708-i2s.0",
++      .platform_name  = "bcm2708-i2s.0",
++      .codecs         = justboom_both_codecs,
++      .num_codecs     = ARRAY_SIZE(justboom_both_codecs),
++      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++                                      SND_SOC_DAIFMT_CBM_CFM,
++      .ops            = &snd_rpi_justboom_both_ops,
++      .init           = snd_rpi_justboom_both_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_justboom_both = {
++      .name             = "snd_rpi_justboom_both",
++      .driver_name      = "JustBoomBoth",
++      .owner            = THIS_MODULE,
++      .dai_link         = snd_rpi_justboom_both_dai,
++      .num_links        = ARRAY_SIZE(snd_rpi_justboom_both_dai),
++};
++
++static int snd_rpi_justboom_both_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++
++      snd_rpi_justboom_both.dev = &pdev->dev;
++
++      if (pdev->dev.of_node) {
++              struct device_node *i2s_node;
++              struct snd_soc_dai_link *dai = &snd_rpi_justboom_both_dai[0];
++
++              i2s_node = of_parse_phandle(pdev->dev.of_node,
++                                      "i2s-controller", 0);
++
++              if (i2s_node) {
++                      dai->cpu_dai_name = NULL;
++                      dai->cpu_of_node = i2s_node;
++                      dai->platform_name = NULL;
++                      dai->platform_of_node = i2s_node;
++              }
++
++              digital_gain_0db_limit = !of_property_read_bool(
++                      pdev->dev.of_node, "justboom,24db_digital_gain");
++      }
++
++      ret = snd_soc_register_card(&snd_rpi_justboom_both);
++      if (ret && ret != -EPROBE_DEFER) {
++              dev_err(&pdev->dev,
++                      "snd_soc_register_card() failed: %d\n", ret);
++      }
++
++      return ret;
++}
++
++static int snd_rpi_justboom_both_remove(struct platform_device *pdev)
++{
++      return snd_soc_unregister_card(&snd_rpi_justboom_both);
++}
++
++static const struct of_device_id snd_rpi_justboom_both_of_match[] = {
++      { .compatible = "justboom,justboom-both", },
++      {},
++};
++MODULE_DEVICE_TABLE(of, snd_rpi_justboom_both_of_match);
++
++static struct platform_driver snd_rpi_justboom_both_driver = {
++      .driver = {
++              .name   = "snd-rpi-justboom-both",
++              .owner  = THIS_MODULE,
++              .of_match_table = snd_rpi_justboom_both_of_match,
++      },
++      .probe          = snd_rpi_justboom_both_probe,
++      .remove         = snd_rpi_justboom_both_remove,
++};
++
++module_platform_driver(snd_rpi_justboom_both_driver);
++
++MODULE_AUTHOR("Johannes Krude <johannes@krude.de>");
++MODULE_DESCRIPTION("ASoC Driver for simultaneous use of JustBoom PI Digi & DAC HAT Sound Cards");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0778-drm-vc4-Disable-V3D-interactions-if-the-v3d-componen.patch b/target/linux/brcm2708/patches-4.19/950-0778-drm-vc4-Disable-V3D-interactions-if-the-v3d-componen.patch
deleted file mode 100644 (file)
index afc94da..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-From 7140cf0d83c10f93ca8212edb17697baf9cafb45 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 1 Apr 2019 11:35:59 -0700
-Subject: [PATCH] drm/vc4: Disable V3D interactions if the v3d
- component didn't probe.
-
-Commit ffc26740714962e3e8801dca7ef32b636b3781db upstream.
-
-One might want to use the VC4 display stack without using Mesa.
-Similar to the debugfs fixes for not having all of the possible
-display bits enabled, make sure you can't oops in vc4 if v3d isn't
-enabled.
-
-v2: Fix matching against other v3d variants (review by Paul), don't
-    forget to set irq_enabled so that the vblank uapi works
-v3: Use -ENODEV instead of -EINVAL on Paul's suggestion.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20190401183559.3823-2-eric@anholt.net
-Reviewed-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
----
- drivers/gpu/drm/vc4/vc4_drv.c     | 10 ++++++++++
- drivers/gpu/drm/vc4/vc4_drv.h     |  1 +
- drivers/gpu/drm/vc4/vc4_gem.c     | 10 ++++++++++
- drivers/gpu/drm/vc4/vc4_irq.c     |  9 +++++++++
- drivers/gpu/drm/vc4/vc4_perfmon.c | 18 ++++++++++++++++++
- drivers/gpu/drm/vc4/vc4_v3d.c     |  2 +-
- 6 files changed, 49 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_drv.c
-+++ b/drivers/gpu/drm/vc4/vc4_drv.c
-@@ -71,6 +71,9 @@ static int vc4_get_param_ioctl(struct dr
-       if (args->pad != 0)
-               return -EINVAL;
-+      if (!vc4->v3d)
-+              return -ENODEV;
-+
-       switch (args->param) {
-       case DRM_VC4_PARAM_V3D_IDENT0:
-               ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
-@@ -271,6 +274,7 @@ static int vc4_drm_bind(struct device *d
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *drm;
-       struct vc4_dev *vc4;
-+      struct device_node *node;
-       int ret = 0;
-       dev->coherent_dma_mask = DMA_BIT_MASK(32);
-@@ -279,6 +283,12 @@ static int vc4_drm_bind(struct device *d
-       if (!vc4)
-               return -ENOMEM;
-+      /* If VC4 V3D is missing, don't advertise render nodes. */
-+      node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL);
-+      if (!node || !of_device_is_available(node))
-+              vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
-+      of_node_put(node);
-+
-       drm = drm_dev_alloc(&vc4_drm_driver, dev);
-       if (IS_ERR(drm))
-               return PTR_ERR(drm);
---- a/drivers/gpu/drm/vc4/vc4_drv.h
-+++ b/drivers/gpu/drm/vc4/vc4_drv.h
-@@ -787,6 +787,7 @@ void vc4_plane_async_set_fb(struct drm_p
- /* vc4_v3d.c */
- extern struct platform_driver vc4_v3d_driver;
-+extern const struct of_device_id vc4_v3d_dt_match[];
- int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
- int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
- int vc4_v3d_get_bin_slot(struct vc4_dev *vc4);
---- a/drivers/gpu/drm/vc4/vc4_gem.c
-+++ b/drivers/gpu/drm/vc4/vc4_gem.c
-@@ -74,6 +74,11 @@ vc4_get_hang_state_ioctl(struct drm_devi
-       u32 i;
-       int ret = 0;
-+      if (!vc4->v3d) {
-+              DRM_DEBUG("VC4_GET_HANG_STATE with no VC4 V3D probed\n");
-+              return -ENODEV;
-+      }
-+
-       spin_lock_irqsave(&vc4->job_lock, irqflags);
-       kernel_state = vc4->hang_state;
-       if (!kernel_state) {
-@@ -1124,6 +1129,11 @@ vc4_submit_cl_ioctl(struct drm_device *d
-       struct dma_fence *in_fence;
-       int ret = 0;
-+      if (!vc4->v3d) {
-+              DRM_DEBUG("VC4_SUBMIT_CL with no VC4 V3D probed\n");
-+              return -ENODEV;
-+      }
-+
-       if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR |
-                            VC4_SUBMIT_CL_FIXED_RCL_ORDER |
-                            VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X |
---- a/drivers/gpu/drm/vc4/vc4_irq.c
-+++ b/drivers/gpu/drm/vc4/vc4_irq.c
-@@ -229,6 +229,9 @@ vc4_irq_preinstall(struct drm_device *de
- {
-       struct vc4_dev *vc4 = to_vc4_dev(dev);
-+      if (!vc4->v3d)
-+              return;
-+
-       init_waitqueue_head(&vc4->job_wait_queue);
-       INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
-@@ -243,6 +246,9 @@ vc4_irq_postinstall(struct drm_device *d
- {
-       struct vc4_dev *vc4 = to_vc4_dev(dev);
-+      if (!vc4->v3d)
-+              return 0;
-+
-       /* Enable both the render done and out of memory interrupts. */
-       V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
-@@ -254,6 +260,9 @@ vc4_irq_uninstall(struct drm_device *dev
- {
-       struct vc4_dev *vc4 = to_vc4_dev(dev);
-+      if (!vc4->v3d)
-+              return;
-+
-       /* Disable sending interrupts for our driver's IRQs. */
-       V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS);
---- a/drivers/gpu/drm/vc4/vc4_perfmon.c
-+++ b/drivers/gpu/drm/vc4/vc4_perfmon.c
-@@ -100,12 +100,18 @@ void vc4_perfmon_close_file(struct vc4_f
- int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
-                            struct drm_file *file_priv)
- {
-+      struct vc4_dev *vc4 = to_vc4_dev(dev);
-       struct vc4_file *vc4file = file_priv->driver_priv;
-       struct drm_vc4_perfmon_create *req = data;
-       struct vc4_perfmon *perfmon;
-       unsigned int i;
-       int ret;
-+      if (!vc4->v3d) {
-+              DRM_DEBUG("Creating perfmon no VC4 V3D probed\n");
-+              return -ENODEV;
-+      }
-+
-       /* Number of monitored counters cannot exceed HW limits. */
-       if (req->ncounters > DRM_VC4_MAX_PERF_COUNTERS ||
-           !req->ncounters)
-@@ -146,10 +152,16 @@ int vc4_perfmon_create_ioctl(struct drm_
- int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
-                             struct drm_file *file_priv)
- {
-+      struct vc4_dev *vc4 = to_vc4_dev(dev);
-       struct vc4_file *vc4file = file_priv->driver_priv;
-       struct drm_vc4_perfmon_destroy *req = data;
-       struct vc4_perfmon *perfmon;
-+      if (!vc4->v3d) {
-+              DRM_DEBUG("Destroying perfmon no VC4 V3D probed\n");
-+              return -ENODEV;
-+      }
-+
-       mutex_lock(&vc4file->perfmon.lock);
-       perfmon = idr_remove(&vc4file->perfmon.idr, req->id);
-       mutex_unlock(&vc4file->perfmon.lock);
-@@ -164,11 +176,17 @@ int vc4_perfmon_destroy_ioctl(struct drm
- int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv)
- {
-+      struct vc4_dev *vc4 = to_vc4_dev(dev);
-       struct vc4_file *vc4file = file_priv->driver_priv;
-       struct drm_vc4_perfmon_get_values *req = data;
-       struct vc4_perfmon *perfmon;
-       int ret;
-+      if (!vc4->v3d) {
-+              DRM_DEBUG("Getting perfmon no VC4 V3D probed\n");
-+              return -ENODEV;
-+      }
-+
-       mutex_lock(&vc4file->perfmon.lock);
-       perfmon = idr_find(&vc4file->perfmon.idr, req->id);
-       vc4_perfmon_get(perfmon);
---- a/drivers/gpu/drm/vc4/vc4_v3d.c
-+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
-@@ -452,7 +452,7 @@ static int vc4_v3d_dev_remove(struct pla
-       return 0;
- }
--static const struct of_device_id vc4_v3d_dt_match[] = {
-+const struct of_device_id vc4_v3d_dt_match[] = {
-       { .compatible = "brcm,bcm2835-v3d" },
-       { .compatible = "brcm,cygnus-v3d" },
-       { .compatible = "brcm,vc4-v3d" },
diff --git a/target/linux/brcm2708/patches-4.19/950-0779-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch b/target/linux/brcm2708/patches-4.19/950-0779-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch
new file mode 100644 (file)
index 0000000..8a28f73
--- /dev/null
@@ -0,0 +1,59 @@
+From 2a15e634d80f78cf2d8aa16ecf0f3cf930e277b4 Mon Sep 17 00:00:00 2001
+From: Hui Wang <hui.wang@canonical.com>
+Date: Sun, 17 Nov 2019 10:31:46 +0800
+Subject: [PATCH] dwc_otg: checking the urb->transfer_buffer too early
+ (#3332)
+
+After enable the HIGHMEM and VMSPLIT_3G, the dwc_otg driver doesn't
+work well on Pi2/3 boards with 1G physical ram. Users experience
+the failure when copying a file of 600M size to the USB stick. And
+at the same time, the dmesg shows:
+usb 1-1.1.2: reset high-speed USB device number 8 using dwc_otg
+sd 0:0:0:0: [sda] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK
+blk_update_request: I/O error, dev sda, sector 3024048 op 0x1:(WRITE) flags 0x4000 phys_seg 15 prio class 0
+
+When this happens, the sg_buf sent to the driver is located in the
+highmem region, the usb_sg_init() in the core/message.c will leave
+transfer_buffer to NULL if the sg_buf is in highmem, but in the
+dwc_otg driver, it returns -EINVAL unconditionally if transfer_buffer
+is NULL.
+
+The driver can handle the situation of buffer to be NULL, if it is in
+DMA mode, it will convert an address from transfer_dma.
+
+But if the conversion fails or it is in the PIO mode, we should check
+buffer and return -EINVAL if it is NULL.
+
+BugLink: https://bugs.launchpad.net/bugs/1852510
+Signed-off-by: Hui Wang <hui.wang@canonical.com>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -821,10 +821,6 @@ static int dwc_otg_urb_enqueue(struct us
+               dump_urb_info(urb, "dwc_otg_urb_enqueue");
+       }
+ #endif
+-
+-      if (!urb->transfer_buffer && urb->transfer_buffer_length)
+-              return -EINVAL;
+-
+       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+           || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
+               if (!dwc_otg_hcd_is_bandwidth_allocated
+@@ -881,6 +877,13 @@ static int dwc_otg_urb_enqueue(struct us
+                             &urb->transfer_dma, buf);
+       }
++      if (!buf && urb->transfer_buffer_length) {
++              DWC_FREE(dwc_otg_urb);
++              DWC_ERROR("transfer_buffer is NULL in PIO mode or both "
++                         "transfer_buffer and transfer_dma are NULL in DMA mode\n");
++              return -EINVAL;
++      }
++
+       if (!(urb->transfer_flags & URB_NO_INTERRUPT))
+               flags |= URB_GIVEBACK_ASAP;
+       if (urb->transfer_flags & URB_ZERO_PACKET)
diff --git a/target/linux/brcm2708/patches-4.19/950-0779-sound-soc-only-first-codec-is-master-in-multicodec-s.patch b/target/linux/brcm2708/patches-4.19/950-0779-sound-soc-only-first-codec-is-master-in-multicodec-s.patch
deleted file mode 100644 (file)
index dcfbb9d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 4ca89eb8570cb86314a5a7b55a15d15f53ce5757 Mon Sep 17 00:00:00 2001
-From: Johannes Krude <johannes@krude.de>
-Date: Sat, 16 Nov 2019 12:41:06 +0100
-Subject: [PATCH] sound/soc: only first codec is master in multicodec
- setup
-
-When using multiple codecs, at most one codec should generate the master
-clock. All codecs except the first are therefore configured for slave
-mode.
-
-Signed-off-by: Johannes Krude <johannes@krude.de>
----
- sound/soc/soc-core.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
---- a/sound/soc/soc-core.c
-+++ b/sound/soc/soc-core.c
-@@ -1688,8 +1688,15 @@ int snd_soc_runtime_set_dai_fmt(struct s
-       for (i = 0; i < rtd->num_codecs; i++) {
-               struct snd_soc_dai *codec_dai = codec_dais[i];
-+              unsigned int codec_dai_fmt = dai_fmt;
--              ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
-+              // there can only be one master when using multiple codecs
-+              if (i && (codec_dai_fmt & SND_SOC_DAIFMT_MASTER_MASK)) {
-+                      codec_dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
-+                      codec_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
-+              }
-+
-+              ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
-               if (ret != 0 && ret != -ENOTSUPP) {
-                       dev_warn(codec_dai->dev,
-                                "ASoC: Failed to set DAI format: %d\n", ret);
diff --git a/target/linux/brcm2708/patches-4.19/950-0780-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch b/target/linux/brcm2708/patches-4.19/950-0780-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch
deleted file mode 100644 (file)
index c8b4820..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-From 8f11db84e124da59b8a717d66fc424ef070f4be0 Mon Sep 17 00:00:00 2001
-From: Johannes Krude <johannes@krude.de>
-Date: Sat, 16 Nov 2019 13:14:43 +0100
-Subject: [PATCH] Allow simultaneous use of JustBoom DAC and Digi
-
-Signed-off-by: Johannes Krude <johannes@krude.de>
----
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |  20 ++
- .../dts/overlays/justboom-both-overlay.dts    |  65 +++++
- sound/soc/bcm/Kconfig                         |  12 +
- sound/soc/bcm/Makefile                        |   2 +
- sound/soc/bcm/justboom-both.c                 | 269 ++++++++++++++++++
- 11 files changed, 374 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/justboom-both-overlay.dts
- create mode 100644 sound/soc/bcm/justboom-both.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -86,6 +86,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       iqaudio-digi-wm8804-audio.dtbo \
-       irs1125.dtbo \
-       jedec-spi-nor.dtbo \
-+      justboom-both.dtbo \
-       justboom-dac.dtbo \
-       justboom-digi.dtbo \
-       ltc294x.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1388,6 +1388,26 @@ Params: flash-spi<n>-<m>        Enables
-                                 on SPI<n>, CS#<m>.
-+Name:   justboom-both
-+Info:   Simultaneous usage of an justboom-dac and justboom-digi based
-+        card
-+Load:   dtoverlay=justboom-both,<param>=<val>
-+Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
-+                                Digital volume control. Enable with
-+                                "dtoverlay=justboom-dac,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!)
-+
-+
- Name:   justboom-dac
- Info:   Configures the JustBoom DAC HAT, Amp HAT, DAC Zero and Amp Zero audio
-         cards
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/justboom-both-overlay.dts
-@@ -0,0 +1,65 @@
-+// SPDX-License-Identifier: GPL-2.0
-+// Definitions for JustBoom Both (Digi+DAC)
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      wm8804@3b {
-+                              #sound-dai-cells = <0>;
-+                              compatible = "wlf,wm8804";
-+                              reg = <0x3b>;
-+                              PVDD-supply = <&vdd_3v3_reg>;
-+                              DVDD-supply = <&vdd_3v3_reg>;
-+                              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>;
-+                              AVDD-supply = <&vdd_3v3_reg>;
-+                              DVDD-supply = <&vdd_3v3_reg>;
-+                              CPVDD-supply = <&vdd_3v3_reg>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&sound>;
-+              frag3: __overlay__ {
-+                      compatible = "justboom,justboom-both";
-+                      i2s-controller = <&i2s>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      __overrides__ {
-+              24db_digital_gain = <&frag3>,"justboom,24db_digital_gain?";
-+      };
-+};
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -102,6 +102,18 @@ config SND_BCM2708_SOC_RPI_PROTO
-       help
-         Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
-+config SND_BCM2708_SOC_JUSTBOOM_BOTH
-+      tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
-+      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+      select SND_SOC_WM8804
-+      select SND_SOC_PCM512x
-+      help
-+              Say Y or M if you want to add support for simultaneous
-+              JustBoom Digi and JustBoom DAC.
-+
-+              This is not the right choice if you only have one but both of
-+              these cards.
-+
- config SND_BCM2708_SOC_JUSTBOOM_DAC
-       tristate "Support for JustBoom DAC"
-       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -16,6 +16,7 @@ snd-soc-hifiberry-dacplus-objs := hifibe
- snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
- snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
-+snd-soc-justboom-both-objs := justboom-both.o
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
-@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
-+obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH) += snd-soc-justboom-both.o
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
---- /dev/null
-+++ b/sound/soc/bcm/justboom-both.c
-@@ -0,0 +1,269 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
-+ *
-+ * Authors: Johannes Krude <johannes@krude.de
-+ *
-+ * Driver for when connecting simultaneously justboom-digi and justboom-dac
-+ *
-+ * Based upon code from:
-+ * justboom-digi.c
-+ * by Milan Neskovic <info@justboom.co>
-+ * justboom-dac.c
-+ * by Milan Neskovic <info@justboom.co>
-+ *
-+ * 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 <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+
-+#include "../codecs/wm8804.h"
-+#include "../codecs/pcm512x.h"
-+
-+
-+static bool digital_gain_0db_limit = true;
-+
-+static int snd_rpi_justboom_both_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+      struct snd_soc_component *dac = rtd->codec_dais[1]->component;
-+
-+      /* enable  TX output */
-+      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
-+
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+
-+      if (digital_gain_0db_limit) {
-+              int ret;
-+              struct snd_soc_card *card = rtd->card;
-+
-+              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);
-+      }
-+
-+      return 0;
-+}
-+
-+static int snd_rpi_justboom_both_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 *codec_dai = rtd->codec_dai;
-+      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-+
-+      int sysclk = 27000000; /* This is fixed on this board */
-+
-+      long mclk_freq    = 0;
-+      int mclk_div      = 1;
-+      int sampling_freq = 1;
-+
-+      int ret;
-+
-+      int samplerate = params_rate(params);
-+
-+      if (samplerate <= 96000) {
-+              mclk_freq = samplerate*256;
-+              mclk_div  = WM8804_MCLKDIV_256FS;
-+      } else {
-+              mclk_freq = samplerate*128;
-+              mclk_div  = WM8804_MCLKDIV_128FS;
-+      }
-+
-+      switch (samplerate) {
-+      case 32000:
-+              sampling_freq = 0x03;
-+              break;
-+      case 44100:
-+              sampling_freq = 0x00;
-+              break;
-+      case 48000:
-+              sampling_freq = 0x02;
-+              break;
-+      case 88200:
-+              sampling_freq = 0x08;
-+              break;
-+      case 96000:
-+              sampling_freq = 0x0a;
-+              break;
-+      case 176400:
-+              sampling_freq = 0x0c;
-+              break;
-+      case 192000:
-+              sampling_freq = 0x0e;
-+              break;
-+      default:
-+              dev_err(rtd->card->dev,
-+              "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
-+              samplerate);
-+      }
-+
-+      snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
-+      snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
-+
-+      ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
-+                                      sysclk, SND_SOC_CLOCK_OUT);
-+      if (ret < 0) {
-+              dev_err(rtd->card->dev,
-+              "Failed to set WM8804 SYSCLK: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* Enable TX output */
-+      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
-+
-+      /* Power on */
-+      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x9, 0);
-+
-+      /* set sampling frequency status bits */
-+      snd_soc_component_update_bits(digi, WM8804_SPDTX4, 0x0f, sampling_freq);
-+
-+      return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
-+}
-+
-+static int snd_rpi_justboom_both_startup(struct snd_pcm_substream *substream)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+      struct snd_soc_component *dac = rtd->codec_dais[1]->component;
-+
-+      /* turn on digital output */
-+      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x00);
-+
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+
-+      return 0;
-+}
-+
-+static void snd_rpi_justboom_both_shutdown(struct snd_pcm_substream *substream)
-+{
-+      struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+      struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+      struct snd_soc_component *dac = rtd->codec_dais[1]->component;
-+
-+      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
-+
-+      /* turn off output */
-+      snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x3c);
-+}
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_justboom_both_ops = {
-+      .hw_params = snd_rpi_justboom_both_hw_params,
-+      .startup   = snd_rpi_justboom_both_startup,
-+      .shutdown  = snd_rpi_justboom_both_shutdown,
-+};
-+
-+static struct snd_soc_dai_link_component justboom_both_codecs[] = {
-+{
-+      .dai_name = "wm8804-spdif",
-+      .name     = "wm8804.1-003b",
-+},
-+{
-+      .dai_name = "pcm512x-hifi",
-+      .name     = "pcm512x.1-004d",
-+},
-+};
-+
-+static struct snd_soc_dai_link snd_rpi_justboom_both_dai[] = {
-+{
-+      .name           = "JustBoom Digi",
-+      .stream_name    = "JustBoom Digi HiFi",
-+      .cpu_dai_name   = "bcm2708-i2s.0",
-+      .platform_name  = "bcm2708-i2s.0",
-+      .codecs         = justboom_both_codecs,
-+      .num_codecs     = ARRAY_SIZE(justboom_both_codecs),
-+      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+                                      SND_SOC_DAIFMT_CBM_CFM,
-+      .ops            = &snd_rpi_justboom_both_ops,
-+      .init           = snd_rpi_justboom_both_init,
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_justboom_both = {
-+      .name             = "snd_rpi_justboom_both",
-+      .driver_name      = "JustBoomBoth",
-+      .owner            = THIS_MODULE,
-+      .dai_link         = snd_rpi_justboom_both_dai,
-+      .num_links        = ARRAY_SIZE(snd_rpi_justboom_both_dai),
-+};
-+
-+static int snd_rpi_justboom_both_probe(struct platform_device *pdev)
-+{
-+      int ret = 0;
-+
-+      snd_rpi_justboom_both.dev = &pdev->dev;
-+
-+      if (pdev->dev.of_node) {
-+              struct device_node *i2s_node;
-+              struct snd_soc_dai_link *dai = &snd_rpi_justboom_both_dai[0];
-+
-+              i2s_node = of_parse_phandle(pdev->dev.of_node,
-+                                      "i2s-controller", 0);
-+
-+              if (i2s_node) {
-+                      dai->cpu_dai_name = NULL;
-+                      dai->cpu_of_node = i2s_node;
-+                      dai->platform_name = NULL;
-+                      dai->platform_of_node = i2s_node;
-+              }
-+
-+              digital_gain_0db_limit = !of_property_read_bool(
-+                      pdev->dev.of_node, "justboom,24db_digital_gain");
-+      }
-+
-+      ret = snd_soc_register_card(&snd_rpi_justboom_both);
-+      if (ret && ret != -EPROBE_DEFER) {
-+              dev_err(&pdev->dev,
-+                      "snd_soc_register_card() failed: %d\n", ret);
-+      }
-+
-+      return ret;
-+}
-+
-+static int snd_rpi_justboom_both_remove(struct platform_device *pdev)
-+{
-+      return snd_soc_unregister_card(&snd_rpi_justboom_both);
-+}
-+
-+static const struct of_device_id snd_rpi_justboom_both_of_match[] = {
-+      { .compatible = "justboom,justboom-both", },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, snd_rpi_justboom_both_of_match);
-+
-+static struct platform_driver snd_rpi_justboom_both_driver = {
-+      .driver = {
-+              .name   = "snd-rpi-justboom-both",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = snd_rpi_justboom_both_of_match,
-+      },
-+      .probe          = snd_rpi_justboom_both_probe,
-+      .remove         = snd_rpi_justboom_both_remove,
-+};
-+
-+module_platform_driver(snd_rpi_justboom_both_driver);
-+
-+MODULE_AUTHOR("Johannes Krude <johannes@krude.de>");
-+MODULE_DESCRIPTION("ASoC Driver for simultaneous use of JustBoom PI Digi & DAC HAT Sound Cards");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0780-overlays-Make-mcp342x-run-time-compatible.patch b/target/linux/brcm2708/patches-4.19/950-0780-overlays-Make-mcp342x-run-time-compatible.patch
new file mode 100644 (file)
index 0000000..900cbb2
--- /dev/null
@@ -0,0 +1,209 @@
+From e650f4bfbe9a09e5b75d702884a8ba8d9df6ccdf Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 9 Dec 2019 12:32:20 +0000
+Subject: [PATCH] overlays: Make mcp342x run-time compatible
+
+The order of processing of run-time overlays differs from that done by
+the firmware. This means that certain parameter processing techniques
+are not compatible with run-time use.  The mcp342x overlay is one such
+overlay, but it is easy to change the implementation without changing
+the interface.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=258294
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../arm/boot/dts/overlays/mcp342x-overlay.dts | 133 ++++++++++++++----
+ 1 file changed, 102 insertions(+), 31 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+@@ -8,14 +8,15 @@
+       fragment@0 {
+               target = <&i2c1>;
+-              __overlay__ {
++              __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "okay";
+-                      mcp342x: mcp@68 {
++                      mcp3421: mcp@68 {
+                               reg = <0x68>;
++                              compatible = "microchip,mcp3421";
+                               status = "okay";
+                       };
+@@ -23,71 +24,141 @@
+       };
+       fragment@1 {
+-              target = <&mcp342x>;
++              target = <&i2c1>;
+               __dormant__ {
+-                      compatible = "microchip,mcp3421";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      mcp3422: mcp@68 {
++                              reg = <0x68>;
++                              compatible = "microchip,mcp3422";
++
++                              status = "okay";
++                      };
+               };
+       };
+       fragment@2 {
+-              target = <&mcp342x>;
++              target = <&i2c1>;
+               __dormant__ {
+-                      compatible = "microchip,mcp3422";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      mcp3423: mcp@68 {
++                              reg = <0x68>;
++                              compatible = "microchip,mcp3423";
++
++                              status = "okay";
++                      };
+               };
+       };
+       fragment@3 {
+-              target = <&mcp342x>;
++              target = <&i2c1>;
+               __dormant__ {
+-                      compatible = "microchip,mcp3423";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      mcp3424: mcp@68 {
++                              reg = <0x68>;
++                              compatible = "microchip,mcp3424";
++
++                              status = "okay";
++                      };
+               };
+       };
+       fragment@4 {
+-              target = <&mcp342x>;
++              target = <&i2c1>;
+               __dormant__ {
+-                      compatible = "microchip,mcp3424";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      mcp3425: mcp@68 {
++                              reg = <0x68>;
++                              compatible = "microchip,mcp3425","mcp3425";
++
++                              status = "okay";
++                      };
+               };
+       };
+       fragment@5 {
+-              target = <&mcp342x>;
++              target = <&i2c1>;
+               __dormant__ {
+-                      compatible = "microchip,mcp3425";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      mcp3426: mcp@68 {
++                              reg = <0x68>;
++                              compatible = "microchip,mcp3426";
++
++                              status = "okay";
++                      };
+               };
+       };
+       fragment@6 {
+-              target = <&mcp342x>;
++              target = <&i2c1>;
+               __dormant__ {
+-                      compatible = "microchip,mcp3426";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      status = "okay";
++
++                      mcp3427: mcp@68 {
++                              reg = <0x68>;
++                              compatible = "microchip,mcp3427";
++
++                              status = "okay";
++                      };
+               };
+       };
+       fragment@7 {
+-              target = <&mcp342x>;
++              target = <&i2c1>;
+               __dormant__ {
+-                      compatible = "microchip,mcp3427";
+-              };
+-      };
++                      #address-cells = <1>;
++                      #size-cells = <0>;
+-      fragment@8 {
+-              target = <&mcp342x>;
+-              __dormant__ {
+-                      compatible = "microchip,mcp3428";
++                      status = "okay";
++
++                      mcp3428: mcp@68 {
++                              reg = <0x68>;
++                              compatible = "microchip,mcp3428";
++
++                              status = "okay";
++                      };
+               };
+       };
+       __overrides__ {
+-              addr = <&mcp342x>,"reg:0";
+-              mcp3421 = <0>,"=1";
+-              mcp3422 = <0>,"=2";
+-              mcp3423 = <0>,"=3";
+-              mcp3424 = <0>,"=4";
+-              mcp3425 = <0>,"=5";
+-              mcp3426 = <0>,"=6";
+-              mcp3427 = <0>,"=7";
+-              mcp3428 = <0>,"=8";
++              addr = <&mcp3421>,"reg:0",
++                     <&mcp3422>,"reg:0",
++                     <&mcp3423>,"reg:0",
++                     <&mcp3424>,"reg:0",
++                     <&mcp3425>,"reg:0",
++                     <&mcp3426>,"reg:0",
++                     <&mcp3427>,"reg:0",
++                     <&mcp3428>,"reg:0";
++              mcp3421 = <0>,"=0";
++              mcp3422 = <0>,"=1";
++              mcp3423 = <0>,"=2";
++              mcp3424 = <0>,"=3";
++              mcp3425 = <0>,"=4";
++              mcp3426 = <0>,"=5";
++              mcp3427 = <0>,"=6";
++              mcp3428 = <0>,"=7";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0781-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch b/target/linux/brcm2708/patches-4.19/950-0781-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch
deleted file mode 100644 (file)
index 8a28f73..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 2a15e634d80f78cf2d8aa16ecf0f3cf930e277b4 Mon Sep 17 00:00:00 2001
-From: Hui Wang <hui.wang@canonical.com>
-Date: Sun, 17 Nov 2019 10:31:46 +0800
-Subject: [PATCH] dwc_otg: checking the urb->transfer_buffer too early
- (#3332)
-
-After enable the HIGHMEM and VMSPLIT_3G, the dwc_otg driver doesn't
-work well on Pi2/3 boards with 1G physical ram. Users experience
-the failure when copying a file of 600M size to the USB stick. And
-at the same time, the dmesg shows:
-usb 1-1.1.2: reset high-speed USB device number 8 using dwc_otg
-sd 0:0:0:0: [sda] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK
-blk_update_request: I/O error, dev sda, sector 3024048 op 0x1:(WRITE) flags 0x4000 phys_seg 15 prio class 0
-
-When this happens, the sg_buf sent to the driver is located in the
-highmem region, the usb_sg_init() in the core/message.c will leave
-transfer_buffer to NULL if the sg_buf is in highmem, but in the
-dwc_otg driver, it returns -EINVAL unconditionally if transfer_buffer
-is NULL.
-
-The driver can handle the situation of buffer to be NULL, if it is in
-DMA mode, it will convert an address from transfer_dma.
-
-But if the conversion fails or it is in the PIO mode, we should check
-buffer and return -EINVAL if it is NULL.
-
-BugLink: https://bugs.launchpad.net/bugs/1852510
-Signed-off-by: Hui Wang <hui.wang@canonical.com>
----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 11 +++++++----
- 1 file changed, 7 insertions(+), 4 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -821,10 +821,6 @@ static int dwc_otg_urb_enqueue(struct us
-               dump_urb_info(urb, "dwc_otg_urb_enqueue");
-       }
- #endif
--
--      if (!urb->transfer_buffer && urb->transfer_buffer_length)
--              return -EINVAL;
--
-       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
-           || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
-               if (!dwc_otg_hcd_is_bandwidth_allocated
-@@ -881,6 +877,13 @@ static int dwc_otg_urb_enqueue(struct us
-                             &urb->transfer_dma, buf);
-       }
-+      if (!buf && urb->transfer_buffer_length) {
-+              DWC_FREE(dwc_otg_urb);
-+              DWC_ERROR("transfer_buffer is NULL in PIO mode or both "
-+                         "transfer_buffer and transfer_dma are NULL in DMA mode\n");
-+              return -EINVAL;
-+      }
-+
-       if (!(urb->transfer_flags & URB_NO_INTERRUPT))
-               flags |= URB_GIVEBACK_ASAP;
-       if (urb->transfer_flags & URB_ZERO_PACKET)
diff --git a/target/linux/brcm2708/patches-4.19/950-0781-overlays-dht11-Allow-multiple-instantiation.patch b/target/linux/brcm2708/patches-4.19/950-0781-overlays-dht11-Allow-multiple-instantiation.patch
new file mode 100644 (file)
index 0000000..5eed1ba
--- /dev/null
@@ -0,0 +1,34 @@
+From 26e95c876831692f28894041c5a1db5934715939 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 18 Dec 2019 10:41:33 +0000
+Subject: [PATCH] overlays: dht11: Allow multiple instantiation
+
+Add addresses to the dht11 and dht11_pins nodes to allow unique names
+to be generated by assigning to the "reg" property.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/dht11-overlay.dts | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
+@@ -24,7 +24,7 @@
+       fragment@1 {
+               target = <&gpio>;
+               __overlay__ {
+-                      dht11_pins: dht11_pins {
++                      dht11_pins: dht11_pins@0 {
+                               brcm,pins = <4>;
+                               brcm,function = <0>; // in
+                               brcm,pull = <0>; // off
+@@ -34,6 +34,8 @@
+       __overrides__ {
+               gpiopin = <&dht11_pins>,"brcm,pins:0",
+-                      <&dht11>,"gpios:4";
++                      <&dht11_pins>, "reg:0",
++                      <&dht11>,"gpios:4",
++                      <&dht11>,"reg:0";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0782-overlays-Make-mcp342x-run-time-compatible.patch b/target/linux/brcm2708/patches-4.19/950-0782-overlays-Make-mcp342x-run-time-compatible.patch
deleted file mode 100644 (file)
index 900cbb2..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-From e650f4bfbe9a09e5b75d702884a8ba8d9df6ccdf Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 9 Dec 2019 12:32:20 +0000
-Subject: [PATCH] overlays: Make mcp342x run-time compatible
-
-The order of processing of run-time overlays differs from that done by
-the firmware. This means that certain parameter processing techniques
-are not compatible with run-time use.  The mcp342x overlay is one such
-overlay, but it is easy to change the implementation without changing
-the interface.
-
-See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=258294
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../arm/boot/dts/overlays/mcp342x-overlay.dts | 133 ++++++++++++++----
- 1 file changed, 102 insertions(+), 31 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-@@ -8,14 +8,15 @@
-       fragment@0 {
-               target = <&i2c1>;
--              __overlay__ {
-+              __dormant__ {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       status = "okay";
--                      mcp342x: mcp@68 {
-+                      mcp3421: mcp@68 {
-                               reg = <0x68>;
-+                              compatible = "microchip,mcp3421";
-                               status = "okay";
-                       };
-@@ -23,71 +24,141 @@
-       };
-       fragment@1 {
--              target = <&mcp342x>;
-+              target = <&i2c1>;
-               __dormant__ {
--                      compatible = "microchip,mcp3421";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      mcp3422: mcp@68 {
-+                              reg = <0x68>;
-+                              compatible = "microchip,mcp3422";
-+
-+                              status = "okay";
-+                      };
-               };
-       };
-       fragment@2 {
--              target = <&mcp342x>;
-+              target = <&i2c1>;
-               __dormant__ {
--                      compatible = "microchip,mcp3422";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      mcp3423: mcp@68 {
-+                              reg = <0x68>;
-+                              compatible = "microchip,mcp3423";
-+
-+                              status = "okay";
-+                      };
-               };
-       };
-       fragment@3 {
--              target = <&mcp342x>;
-+              target = <&i2c1>;
-               __dormant__ {
--                      compatible = "microchip,mcp3423";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      mcp3424: mcp@68 {
-+                              reg = <0x68>;
-+                              compatible = "microchip,mcp3424";
-+
-+                              status = "okay";
-+                      };
-               };
-       };
-       fragment@4 {
--              target = <&mcp342x>;
-+              target = <&i2c1>;
-               __dormant__ {
--                      compatible = "microchip,mcp3424";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      mcp3425: mcp@68 {
-+                              reg = <0x68>;
-+                              compatible = "microchip,mcp3425","mcp3425";
-+
-+                              status = "okay";
-+                      };
-               };
-       };
-       fragment@5 {
--              target = <&mcp342x>;
-+              target = <&i2c1>;
-               __dormant__ {
--                      compatible = "microchip,mcp3425";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      mcp3426: mcp@68 {
-+                              reg = <0x68>;
-+                              compatible = "microchip,mcp3426";
-+
-+                              status = "okay";
-+                      };
-               };
-       };
-       fragment@6 {
--              target = <&mcp342x>;
-+              target = <&i2c1>;
-               __dormant__ {
--                      compatible = "microchip,mcp3426";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      status = "okay";
-+
-+                      mcp3427: mcp@68 {
-+                              reg = <0x68>;
-+                              compatible = "microchip,mcp3427";
-+
-+                              status = "okay";
-+                      };
-               };
-       };
-       fragment@7 {
--              target = <&mcp342x>;
-+              target = <&i2c1>;
-               __dormant__ {
--                      compatible = "microchip,mcp3427";
--              };
--      };
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
--      fragment@8 {
--              target = <&mcp342x>;
--              __dormant__ {
--                      compatible = "microchip,mcp3428";
-+                      status = "okay";
-+
-+                      mcp3428: mcp@68 {
-+                              reg = <0x68>;
-+                              compatible = "microchip,mcp3428";
-+
-+                              status = "okay";
-+                      };
-               };
-       };
-       __overrides__ {
--              addr = <&mcp342x>,"reg:0";
--              mcp3421 = <0>,"=1";
--              mcp3422 = <0>,"=2";
--              mcp3423 = <0>,"=3";
--              mcp3424 = <0>,"=4";
--              mcp3425 = <0>,"=5";
--              mcp3426 = <0>,"=6";
--              mcp3427 = <0>,"=7";
--              mcp3428 = <0>,"=8";
-+              addr = <&mcp3421>,"reg:0",
-+                     <&mcp3422>,"reg:0",
-+                     <&mcp3423>,"reg:0",
-+                     <&mcp3424>,"reg:0",
-+                     <&mcp3425>,"reg:0",
-+                     <&mcp3426>,"reg:0",
-+                     <&mcp3427>,"reg:0",
-+                     <&mcp3428>,"reg:0";
-+              mcp3421 = <0>,"=0";
-+              mcp3422 = <0>,"=1";
-+              mcp3423 = <0>,"=2";
-+              mcp3424 = <0>,"=3";
-+              mcp3425 = <0>,"=4";
-+              mcp3426 = <0>,"=5";
-+              mcp3427 = <0>,"=6";
-+              mcp3428 = <0>,"=7";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0782-overlays-i2c-rtc-Add-pcf85363-support.patch b/target/linux/brcm2708/patches-4.19/950-0782-overlays-i2c-rtc-Add-pcf85363-support.patch
new file mode 100644 (file)
index 0000000..af04096
--- /dev/null
@@ -0,0 +1,56 @@
+From b85f76a63d5f1b13220c61244469d55487db84f1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 22 Dec 2019 15:29:40 +0000
+Subject: [PATCH] overlays: i2c-rtc: Add pcf85363 support
+
+See: https://github.com/raspberrypi/firmware/issues/1309
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ 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
+@@ -1078,6 +1078,8 @@ Params: abx80x                  Select o
+         pcf8523                 Select the PCF8523 device
++        pcf85363                Select the PCF85363 device
++
+         pcf8563                 Select the PCF8563 device
+         rv3028                  Select the Micro Crystal RV3028 device
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -188,6 +188,21 @@
+               };
+       };
++      fragment@12 {
++              target = <&i2c_arm>;
++             __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      pcf85363@51 {
++                              compatible = "nxp,pcf85363";
++                              reg = <0x51>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+0";
+               ds1307 = <0>,"+1";
+@@ -201,6 +216,7 @@
+               m41t62 = <0>,"+9";
+               rv3028 = <0>,"+10";
+               pcf2129 = <0>,"+11";
++              pcf85363 = <0>,"+12";
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
diff --git a/target/linux/brcm2708/patches-4.19/950-0783-overlays-dht11-Allow-multiple-instantiation.patch b/target/linux/brcm2708/patches-4.19/950-0783-overlays-dht11-Allow-multiple-instantiation.patch
deleted file mode 100644 (file)
index 5eed1ba..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 26e95c876831692f28894041c5a1db5934715939 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 18 Dec 2019 10:41:33 +0000
-Subject: [PATCH] overlays: dht11: Allow multiple instantiation
-
-Add addresses to the dht11 and dht11_pins nodes to allow unique names
-to be generated by assigning to the "reg" property.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/dht11-overlay.dts | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
-@@ -24,7 +24,7 @@
-       fragment@1 {
-               target = <&gpio>;
-               __overlay__ {
--                      dht11_pins: dht11_pins {
-+                      dht11_pins: dht11_pins@0 {
-                               brcm,pins = <4>;
-                               brcm,function = <0>; // in
-                               brcm,pull = <0>; // off
-@@ -34,6 +34,8 @@
-       __overrides__ {
-               gpiopin = <&dht11_pins>,"brcm,pins:0",
--                      <&dht11>,"gpios:4";
-+                      <&dht11_pins>, "reg:0",
-+                      <&dht11>,"gpios:4",
-+                      <&dht11>,"reg:0";
-       };
- };
diff --git a/target/linux/brcm2708/patches-4.19/950-0783-pinctrl-bcm2835-Remove-gpiochip-on-error.patch b/target/linux/brcm2708/patches-4.19/950-0783-pinctrl-bcm2835-Remove-gpiochip-on-error.patch
new file mode 100644 (file)
index 0000000..d976e37
--- /dev/null
@@ -0,0 +1,25 @@
+From e1bbcb1097b9d968ae61397a66a73a440a0ce705 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 6 Jan 2020 16:04:30 +0000
+Subject: [PATCH] pinctrl: bcm2835: Remove gpiochip on error
+
+A failure in gpiochip_irqchip_add leads to a leak of a gpiochip. Fix
+the leak with the use of devm_gpiochip_add_data.
+
+Fixes: 85ae9e512f43 ("pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP")
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -1140,7 +1140,7 @@ static int bcm2835_pinctrl_probe(struct
+               raw_spin_lock_init(&pc->irq_lock[i]);
+       }
+-      err = gpiochip_add_data(&pc->gpio_chip, pc);
++      err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
+       if (err) {
+               dev_err(dev, "could not add GPIO chip\n");
+               return err;
diff --git a/target/linux/brcm2708/patches-4.19/950-0784-overlays-i2c-rtc-Add-pcf85363-support.patch b/target/linux/brcm2708/patches-4.19/950-0784-overlays-i2c-rtc-Add-pcf85363-support.patch
deleted file mode 100644 (file)
index af04096..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From b85f76a63d5f1b13220c61244469d55487db84f1 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Sun, 22 Dec 2019 15:29:40 +0000
-Subject: [PATCH] overlays: i2c-rtc: Add pcf85363 support
-
-See: https://github.com/raspberrypi/firmware/issues/1309
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- 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
-@@ -1078,6 +1078,8 @@ Params: abx80x                  Select o
-         pcf8523                 Select the PCF8523 device
-+        pcf85363                Select the PCF85363 device
-+
-         pcf8563                 Select the PCF8563 device
-         rv3028                  Select the Micro Crystal RV3028 device
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -188,6 +188,21 @@
-               };
-       };
-+      fragment@12 {
-+              target = <&i2c_arm>;
-+             __dormant__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      pcf85363@51 {
-+                              compatible = "nxp,pcf85363";
-+                              reg = <0x51>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+
-       __overrides__ {
-               abx80x = <0>,"+0";
-               ds1307 = <0>,"+1";
-@@ -201,6 +216,7 @@
-               m41t62 = <0>,"+9";
-               rv3028 = <0>,"+10";
-               pcf2129 = <0>,"+11";
-+              pcf85363 = <0>,"+12";
-               addr = <&abx80x>, "reg:0",
-                      <&ds1307>, "reg:0",
diff --git a/target/linux/brcm2708/patches-4.19/950-0784-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch b/target/linux/brcm2708/patches-4.19/950-0784-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch
new file mode 100644 (file)
index 0000000..09166b7
--- /dev/null
@@ -0,0 +1,82 @@
+From 0b3764707993123148b4e94d44ff282b111c8edb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 6 Jan 2020 14:05:42 +0000
+Subject: [PATCH] pinctrl: bcm2835: Change init order for gpio hogs
+
+pinctrl-bcm2835 is a combined pinctrl/gpio driver. Currently the gpio
+side is registered first, but this breaks gpio hogs (which are
+configured during gpiochip_add_data). Part of the hog initialisation
+is a call to pinctrl_gpio_request, and since the pinctrl driver hasn't
+yet been registered this results in an -EPROBE_DEFER from which it can
+never recover.
+
+Change the initialisation sequence to register the pinctrl driver
+first.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=260600
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 34 +++++++++++++--------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -1140,9 +1140,25 @@ static int bcm2835_pinctrl_probe(struct
+               raw_spin_lock_init(&pc->irq_lock[i]);
+       }
++      match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
++      if (match) {
++              bcm2835_pinctrl_desc.confops =
++                      (const struct pinconf_ops *)match->data;
++      }
++
++      pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
++      if (IS_ERR(pc->pctl_dev))
++              return PTR_ERR(pc->pctl_dev);
++
++      pc->gpio_range = bcm2835_pinctrl_gpio_range;
++      pc->gpio_range.base = pc->gpio_chip.base;
++      pc->gpio_range.gc = &pc->gpio_chip;
++      pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
++
+       err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
+       if (err) {
+               dev_err(dev, "could not add GPIO chip\n");
++              pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
+               return err;
+       }
+@@ -1150,6 +1166,7 @@ static int bcm2835_pinctrl_probe(struct
+                                  0, handle_level_irq, IRQ_TYPE_NONE);
+       if (err) {
+               dev_info(dev, "could not add irqchip\n");
++              pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
+               return err;
+       }
+@@ -1172,23 +1189,6 @@ static int bcm2835_pinctrl_probe(struct
+                                            bcm2835_gpio_irq_handler);
+       }
+-      match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
+-      if (match) {
+-              bcm2835_pinctrl_desc.confops =
+-                      (const struct pinconf_ops *)match->data;
+-      }
+-
+-      pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
+-      if (IS_ERR(pc->pctl_dev)) {
+-              gpiochip_remove(&pc->gpio_chip);
+-              return PTR_ERR(pc->pctl_dev);
+-      }
+-
+-      pc->gpio_range = bcm2835_pinctrl_gpio_range;
+-      pc->gpio_range.base = pc->gpio_chip.base;
+-      pc->gpio_range.gc = &pc->gpio_chip;
+-      pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
+-
+       return 0;
+ }
diff --git a/target/linux/brcm2708/patches-4.19/950-0785-Pisound-MIDI-communication-fixes-for-scaled-down-CPU.patch b/target/linux/brcm2708/patches-4.19/950-0785-Pisound-MIDI-communication-fixes-for-scaled-down-CPU.patch
new file mode 100644 (file)
index 0000000..c363e1d
--- /dev/null
@@ -0,0 +1,100 @@
+From 5b12b655f266ea29e91a7b7a46385df05bb70ed8 Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Tue, 7 Jan 2020 11:04:21 +0200
+Subject: [PATCH] Pisound: MIDI communication fixes for scaled down
+ CPU.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+* Increased maximum SPI communication speed to avoid running too slow
+  when the CPU is scaled down and losing MIDI data.
+
+* Keep track of buffer usage in millibytes for higher precision.
+
+Signed-off-by: Giedrius Trainavičius <giedrius@blokas.io>
+---
+ sound/soc/bcm/pisound.c | 31 ++++++++++++++++++-------------
+ 1 file changed, 18 insertions(+), 13 deletions(-)
+
+--- a/sound/soc/bcm/pisound.c
++++ b/sound/soc/bcm/pisound.c
+@@ -1,6 +1,6 @@
+ /*
+  * Pisound Linux kernel module.
+- * Copyright (C) 2016-2019  Vilniaus Blokas UAB, https://blokas.io/pisound
++ * Copyright (C) 2016-2020  Vilniaus Blokas UAB, https://blokas.io/pisound
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+@@ -326,7 +326,7 @@ static void spi_transfer(const uint8_t *
+       transfer.tx_buf = txbuf;
+       transfer.rx_buf = rxbuf;
+       transfer.len = len;
+-      transfer.speed_hz = 100000;
++      transfer.speed_hz = 150000;
+       transfer.delay_usecs = 10;
+       spi_message_add_tail(&transfer, &msg);
+@@ -403,9 +403,9 @@ static struct spi_device *pisnd_spi_find
+ static void pisnd_work_handler(struct work_struct *work)
+ {
+       enum { TRANSFER_SIZE = 4 };
+-      enum { PISOUND_OUTPUT_BUFFER_SIZE = 128 };
+-      enum { MIDI_BYTES_PER_SECOND = 3125 };
+-      int out_buffer_used = 0;
++      enum { PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES = 127 * 1000 };
++      enum { MIDI_MILLIBYTES_PER_JIFFIE = (3125 * 1000) / HZ };
++      int out_buffer_used_millibytes = 0;
+       unsigned long now;
+       uint8_t val;
+       uint8_t txbuf[TRANSFER_SIZE];
+@@ -445,7 +445,9 @@ static void pisnd_work_handler(struct wo
+                       had_data = false;
+                       memset(txbuf, 0, sizeof(txbuf));
+                       for (i = 0; i < sizeof(txbuf) &&
+-                              out_buffer_used < PISOUND_OUTPUT_BUFFER_SIZE;
++                              ((out_buffer_used_millibytes+1000 <
++                              PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES) ||
++                              g_ledFlashDurationChanged);
+                               i += 2) {
+                               val = 0;
+@@ -458,7 +460,7 @@ static void pisnd_work_handler(struct wo
+                               } else if (kfifo_get(&spi_fifo_out, &val)) {
+                                       txbuf[i+0] = 0x0f;
+                                       txbuf[i+1] = val;
+-                                      ++out_buffer_used;
++                                      out_buffer_used_millibytes += 1000;
+                               }
+                       }
+@@ -469,12 +471,14 @@ static void pisnd_work_handler(struct wo
+                        * rate.
+                        */
+                       now = jiffies;
+-                      out_buffer_used -=
+-                              (MIDI_BYTES_PER_SECOND / HZ) /
+-                              (now - last_transfer_at);
+-                      if (out_buffer_used < 0)
+-                              out_buffer_used = 0;
+-                      last_transfer_at = now;
++                      if (now != last_transfer_at) {
++                              out_buffer_used_millibytes -=
++                                      (now - last_transfer_at) *
++                                      MIDI_MILLIBYTES_PER_JIFFIE;
++                              if (out_buffer_used_millibytes < 0)
++                                      out_buffer_used_millibytes = 0;
++                              last_transfer_at = now;
++                      }
+                       for (i = 0; i < sizeof(rxbuf); i += 2) {
+                               if (rxbuf[i]) {
+@@ -489,6 +493,7 @@ static void pisnd_work_handler(struct wo
+                       || !kfifo_is_empty(&spi_fifo_out)
+                       || pisnd_spi_has_more()
+                       || g_ledFlashDurationChanged
++                      || out_buffer_used_millibytes != 0
+                       );
+               if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)
diff --git a/target/linux/brcm2708/patches-4.19/950-0786-leds-pca963x-Fix-open-drain-initialization.patch b/target/linux/brcm2708/patches-4.19/950-0786-leds-pca963x-Fix-open-drain-initialization.patch
new file mode 100644 (file)
index 0000000..e63d4c6
--- /dev/null
@@ -0,0 +1,61 @@
+From 1738aaf187e0c8e97fbdd9661960b835f45e8985 Mon Sep 17 00:00:00 2001
+From: Zahari Petkov <zahari@balena.io>
+Date: Mon, 18 Nov 2019 23:02:55 +0200
+Subject: [PATCH] leds: pca963x: Fix open-drain initialization
+
+commit 697529091ac7a0a90ca349b914bb30641c13c753 upstream.
+
+Before commit bb29b9cccd95 ("leds: pca963x: Add bindings to invert
+polarity") Mode register 2 was initialized directly with either 0x01
+or 0x05 for open-drain or totem pole (push-pull) configuration.
+
+Afterwards, MODE2 initialization started using bitwise operations on
+top of the default MODE2 register value (0x05). Using bitwise OR for
+setting OUTDRV with 0x01 and 0x05 does not produce correct results.
+When open-drain is used, instead of setting OUTDRV to 0, the driver
+keeps it as 1:
+
+Open-drain: 0x05 | 0x01 -> 0x05 (0b101 - incorrect)
+Totem pole: 0x05 | 0x05 -> 0x05 (0b101 - correct but still wrong)
+
+Now OUTDRV setting uses correct bitwise operations for initialization:
+
+Open-drain: 0x05 & ~0x04 -> 0x01 (0b001 - correct)
+Totem pole: 0x05 | 0x04 -> 0x05 (0b101 - correct)
+
+Additional MODE2 register definitions are introduced now as well.
+
+Fixes: bb29b9cccd95 ("leds: pca963x: Add bindings to invert polarity")
+Signed-off-by: Zahari Petkov <zahari@balena.io>
+Signed-off-by: Pavel Machek <pavel@ucw.cz>
+---
+ drivers/leds/leds-pca963x.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/leds/leds-pca963x.c
++++ b/drivers/leds/leds-pca963x.c
+@@ -43,6 +43,8 @@
+ #define PCA963X_LED_PWM               0x2     /* Controlled through PWM */
+ #define PCA963X_LED_GRP_PWM   0x3     /* Controlled through PWM/GRPPWM */
++#define PCA963X_MODE2_OUTDRV  0x04    /* Open-drain or totem pole */
++#define PCA963X_MODE2_INVRT   0x10    /* Normal or inverted direction */
+ #define PCA963X_MODE2_DMBLNK  0x20    /* Enable blinking */
+ #define PCA963X_MODE1         0x00
+@@ -462,12 +464,12 @@ static int pca963x_probe(struct i2c_clie
+                                                   PCA963X_MODE2);
+               /* Configure output: open-drain or totem pole (push-pull) */
+               if (pdata->outdrv == PCA963X_OPEN_DRAIN)
+-                      mode2 |= 0x01;
++                      mode2 &= ~PCA963X_MODE2_OUTDRV;
+               else
+-                      mode2 |= 0x05;
++                      mode2 |= PCA963X_MODE2_OUTDRV;
+               /* Configure direction: normal or inverted */
+               if (pdata->dir == PCA963X_INVERTED)
+-                      mode2 |= 0x10;
++                      mode2 |= PCA963X_MODE2_INVRT;
+               i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2,
+                                         mode2);
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0787-add-BME680-to-i2c-sensor-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0787-add-BME680-to-i2c-sensor-overlay.patch
new file mode 100644 (file)
index 0000000..55e34e2
--- /dev/null
@@ -0,0 +1,67 @@
+From ca88aee39825dd81ef1e8306b5947c5ae3918d1a Mon Sep 17 00:00:00 2001
+From: Willem Remie <w.remie@drebble.io>
+Date: Thu, 9 Jan 2020 21:16:49 +0100
+Subject: [PATCH] add BME680 to i2c-sensor overlay
+
+---
+ arch/arm/boot/dts/overlays/README             |  7 +++++--
+ .../boot/dts/overlays/i2c-sensor-overlay.dts  | 19 ++++++++++++++++++-
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1159,12 +1159,15 @@ Name:   i2c-sensor
+ Info:   Adds support for a number of I2C barometric pressure and temperature
+         sensors on i2c_arm
+ Load:   dtoverlay=i2c-sensor,<param>=<val>
+-Params: addr                    Set the address for the BME280, BMP280, DS1621,
+-                                HDC100X, LM75, SHT3x or TMP102
++Params: addr                    Set the address for the BME280, BME680, BMP280,
++                                DS1621, HDC100X, LM75, SHT3x or TMP102
+         bme280                  Select the Bosch Sensortronic BME280
+                                 Valid addresses 0x76-0x77, default 0x76
++        bme680                  Select the Bosch Sensortronic BME680
++                                Valid addresses 0x76-0x77, default 0x76
++
+         bmp085                  Select the Bosch Sensortronic BMP085
+         bmp180                  Select the Bosch Sensortronic BMP180
+--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
+@@ -216,10 +216,26 @@
+               };
+       };
++      fragment@14 {
++              target = <&i2c_arm>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      bme680: bme680@76 {
++                              compatible = "bosch,bme680";
++                              reg = <0x76>;
++                              status = "okay";
++                      };
++              };
++      };
++
++
+       __overrides__ {
+               addr =  <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0",
+                       <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0",
+-                      <&ds1621>,"reg:0";
++                      <&ds1621>,"reg:0", <&bme680>,"reg:0";
+               bme280 = <0>,"+0";
+               bmp085 = <0>,"+1";
+               bmp180 = <0>,"+2";
+@@ -235,5 +251,6 @@
+               sht3x = <0>,"+11";
+               ds1621 = <0>,"+12";
+               max17040 = <0>,"+13";
++              bme680 = <0>,"+14";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0788-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch b/target/linux/brcm2708/patches-4.19/950-0788-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch
new file mode 100644 (file)
index 0000000..ae110ad
--- /dev/null
@@ -0,0 +1,43 @@
+From 7ae8ef63c14ca2fea76c9db5799321f1b3e31c36 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 7 Jan 2020 10:08:19 +0000
+Subject: [PATCH] dwc_otg: constrain endpoint max packet and transfer
+ size on split IN
+
+The hcd would unconditionally set the transfer length to the endpoint
+packet size for non-isoc IN transfers. If the remaining buffer length
+was less than the length of returned data, random memory would get
+scribbled over, with bad effects if it crossed a page boundary.
+
+Force a babble error if this happens by limiting the max transfer size
+to the available buffer space. DMA will stop writing to memory on a
+babble condition.
+
+The hardware expects xfersize to be an integer multiple of maxpacket
+size, so override hcchar.b.mps as well.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -1813,7 +1813,7 @@ int fiq_fsm_queue_split_transaction(dwc_
+       st->nr_errors = 0;
+       st->hcchar_copy.d32 = 0;
+-      st->hcchar_copy.b.mps = hc->max_packet;
++      st->hcchar_copy.b.mps = min_t(uint32_t, hc->xfer_len, hc->max_packet);
+       st->hcchar_copy.b.epdir = hc->ep_is_in;
+       st->hcchar_copy.b.devaddr = hc->dev_addr;
+       st->hcchar_copy.b.epnum = hc->ep_num;
+@@ -1858,7 +1858,7 @@ int fiq_fsm_queue_split_transaction(dwc_
+       st->hctsiz_copy.b.pid = hc->data_pid_start;
+       if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
+-              hc->xfer_len = hc->max_packet;
++              hc->xfer_len = min_t(uint32_t, hc->xfer_len, hc->max_packet);
+       } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
+               hc->xfer_len = 188;
+       }
diff --git a/target/linux/brcm2708/patches-4.19/950-0789-dwc_otg-fiq_fsm-pause-when-cancelling-split-transact.patch b/target/linux/brcm2708/patches-4.19/950-0789-dwc_otg-fiq_fsm-pause-when-cancelling-split-transact.patch
new file mode 100644 (file)
index 0000000..53c93a5
--- /dev/null
@@ -0,0 +1,95 @@
+From af6743f045159970b95f6426de13c0fb82678e67 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 8 Jan 2020 12:48:09 +0000
+Subject: [PATCH] dwc_otg: fiq_fsm: pause when cancelling split
+ transactions
+
+Non-periodic splits will DMA to/from the driver-provided transfer_buffer,
+which may be freed immediately after the dequeue call returns. Block until
+we know the transfer is complete.
+
+A similar delay is needed when cleaning up disconnects, as the FIQ could
+have started a periodic transfer in the previous microframe to the one
+that triggered a disconnect.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c    | 33 +++++++++++++++++++++--
+ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h |  1 +
+ 2 files changed, 32 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -175,6 +175,7 @@ static void kill_urbs_in_qh_list(dwc_otg
+       dwc_list_link_t *qh_item, *qh_tmp;
+       dwc_otg_qh_t *qh;
+       dwc_otg_qtd_t *qtd, *qtd_tmp;
++      int quiesced = 0;
+       DWC_LIST_FOREACH_SAFE(qh_item, qh_tmp, qh_list) {
+               qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
+@@ -198,8 +199,17 @@ static void kill_urbs_in_qh_list(dwc_otg
+                               qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
+                               qh->channel->halt_pending = 1;
+                               if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
+-                                      hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
++                                  hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
+                                       hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
++                              /* We're called from disconnect callback or in the middle of freeing the HCD here,
++                               * so FIQ is disabled, top-level interrupts masked and we're holding the spinlock.
++                               * No further URBs will be submitted, but wait 1 microframe for any previously
++                               * submitted periodic DMA to finish.
++                               */
++                              if (!quiesced) {
++                                      udelay(125);
++                                      quiesced = 1;
++                              }
+                       } else {
+                               dwc_otg_hc_halt(hcd->core_if, qh->channel,
+                                               DWC_OTG_HC_XFER_URB_DEQUEUE);
+@@ -600,15 +610,34 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_
+                       /* In FIQ FSM mode, we need to shut down carefully.
+                        * The FIQ may attempt to restart a disabled channel */
+                       if (fiq_fsm_enable && (hcd->fiq_state->channel[n].fsm != FIQ_PASSTHROUGH)) {
++                              int retries = 3;
++                              int running = 0;
++                              enum fiq_fsm_state state;
++
+                               local_fiq_disable();
+                               fiq_fsm_spin_lock(&hcd->fiq_state->lock);
+                               qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
+                               qh->channel->halt_pending = 1;
+                               if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
+-                                      hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
++                                  hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
+                                       hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
+                               fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
+                               local_fiq_enable();
++
++                              if (dwc_qh_is_non_per(qh)) {
++                                      do {
++                                              state = READ_ONCE(hcd->fiq_state->channel[n].fsm);
++                                              running = (state != FIQ_NP_SPLIT_DONE) &&
++                                                        (state != FIQ_NP_SPLIT_LS_ABORTED) &&
++                                                        (state != FIQ_NP_SPLIT_HS_ABORTED);
++                                              if (!running)
++                                                      break;
++                                              udelay(125);
++                                      } while(--retries);
++                                      if (!retries)
++                                              DWC_WARN("Timed out waiting for FSM NP transfer to complete on %d",
++                                                       qh->channel->hc_num);
++                              }
+                       } else {
+                               dwc_otg_hc_halt(hcd->core_if, qh->channel,
+                                               DWC_OTG_HC_XFER_URB_DEQUEUE);
+--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+@@ -27,6 +27,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/stat.h>
+ #include <linux/pci.h>
++#include <linux/compiler.h>
+ #include <linux/version.h>
diff --git a/target/linux/brcm2708/patches-4.19/950-0790-dwc_otg-fiq_fsm-add-a-barrier-on-entry-into-FIQ-hand.patch b/target/linux/brcm2708/patches-4.19/950-0790-dwc_otg-fiq_fsm-add-a-barrier-on-entry-into-FIQ-hand.patch
new file mode 100644 (file)
index 0000000..dc48605
--- /dev/null
@@ -0,0 +1,49 @@
+From b2d43d61a1d6d070664f10d12b3c8b6df11eb21d Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Mon, 13 Jan 2020 15:54:55 +0000
+Subject: [PATCH] dwc_otg: fiq_fsm: add a barrier on entry into FIQ
+ handler(s)
+
+On BCM2835, there is no hardware guarantee that multiple outstanding
+reads to different peripherals will complete in-order. The FIQ code
+uses peripheral reads without barriers for performance, so in the case
+where a read to a slow peripheral was issued immediately prior to FIQ
+entry, the first peripheral read that the FIQ did could end up with
+wrong read data returned.
+
+Add dsb(sy) on entry so that all outstanding reads are retired.
+
+The FIQ only issues reads to the dwc_otg core, so per-read barriers
+in the handler itself are not required.
+
+On BCM2836 and BCM2837 the barrier is not strictly required due to
+differences in how the peripheral bus is implemented, but having
+arch-specific handlers that introduce different latencies is risky.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -1259,6 +1259,9 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
+       haintmsk_data_t haintmsk;
+       int kick_irq = 0;
++      /* Ensure peripheral reads issued prior to FIQ entry are complete */
++      dsb(sy);
++
+       gintsts_handled.d32 = 0;
+       haint_handled.d32 = 0;
+@@ -1379,6 +1382,9 @@ void notrace dwc_otg_fiq_nop(struct fiq_
+       gintmsk_data_t gintmsk;
+       hfnum_data_t hfnum;
++      /* Ensure peripheral reads issued prior to FIQ entry are complete */
++      dsb(sy);
++
+       fiq_fsm_spin_lock(&state->lock);
+       hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
+       gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS);
diff --git a/target/linux/brcm2708/patches-4.19/950-0791-Add-universal-device-tree-overlay-for-SPI-devices.patch b/target/linux/brcm2708/patches-4.19/950-0791-Add-universal-device-tree-overlay-for-SPI-devices.patch
new file mode 100644 (file)
index 0000000..ce027e7
--- /dev/null
@@ -0,0 +1,273 @@
+From 4d19be9132ca10cf582450a86dcb2c41f227f589 Mon Sep 17 00:00:00 2001
+From: Ed Spiridonov <edo.rus@gmail.com>
+Date: Tue, 10 Dec 2019 22:45:04 +0300
+Subject: [PATCH] Add universal device tree overlay for SPI devices
+
+Just specify the SPI address and device name ("compatible" property).
+This overlay lacks any device-specific parameter support!
+(some of them could be added later)
+
+Examples:
+1. SPI NOR flash on spi0.1, maximum SPI clock frequency 45MHz:
+    dtoverlay=anyspi:spi0-1,dev="jedec,spi-nor",speed=45000000
+2. MCP3204 ADC on spi1.2, maximum SPI clock frequency 500kHz:
+    dtoverlay=anyspi:spi1-2,dev="microchip,mcp3204"
+
+Signed-off-by: Ed Spiridonov <edo.rus@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  23 ++
+ arch/arm/boot/dts/overlays/anyspi-overlay.dts | 205 ++++++++++++++++++
+ 3 files changed, 229 insertions(+)
+ create mode 100755 arch/arm/boot/dts/overlays/anyspi-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -15,6 +15,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       allo-katana-dac-audio.dtbo \
+       allo-piano-dac-pcm512x-audio.dtbo \
+       allo-piano-dac-plus-pcm512x-audio.dtbo \
++      anyspi.dtbo \
+       apds9960.dtbo \
+       applepi-dac.dtbo \
+       at86rf233.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -441,6 +441,29 @@ Params: 24db_digital_gain       Allow ga
+                                 better voice quality. (default Off)
++Name:   anyspi
++Info:   Universal device tree overlay for SPI devices
++
++        Just specify the SPI address and device name ("compatible" property).
++        This overlay lacks any device-specific parameter support!
++
++        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.
++
++        Examples:
++        1. SPI NOR flash on spi0.1, maximum SPI clock frequency 45MHz:
++            dtoverlay=anyspi:spi0-1,dev="jedec,spi-nor",speed=45000000
++        2. MCP3204 ADC on spi1.2, maximum SPI clock frequency 500kHz:
++            dtoverlay=anyspi:spi1-2,dev="microchip,mcp3204"
++Load:   dtoverlay=anyspi,<param>=<val>
++Params: spi<n>-<m>              Configure device at spi<n>, cs<m>
++                                (boolean, required)
++        dev                     Set device name to search compatible module
++                                (string, required)
++        speed                   Set SPI clock frequency in Hz
++                                (integer, optional, default 500000)
++
++
+ Name:   apds9960
+ Info:   Configures the AVAGO APDS9960 digital proximity, ambient light, RGB and
+         gesture sensor
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/anyspi-overlay.dts
+@@ -0,0 +1,205 @@
++/*
++ * 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";
++              };
++      };
++
++      fragment@8 {
++              target = <&spi0>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_00: anyspi@0 {
++                              reg = <0>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@9 {
++              target = <&spi0>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_01: anyspi@1 {
++                              reg = <1>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@10 {
++              target = <&spi1>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_10: anyspi@0 {
++                              reg = <0>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@11 {
++              target = <&spi1>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_11: anyspi@1 {
++                              reg = <1>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@12 {
++              target = <&spi1>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_12: anyspi@2 {
++                              reg = <2>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@13 {
++              target = <&spi2>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_20: anyspi@0 {
++                              reg = <0>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@14 {
++              target = <&spi2>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_21: anyspi@1 {
++                              reg = <1>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@15 {
++              target = <&spi2>;
++              __dormant__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      anyspi_22: anyspi@2 {
++                              reg = <2>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              spi0-0 = <0>, "+0+8";
++              spi0-1 = <0>, "+1+9";
++              spi1-0 = <0>, "+2+10";
++              spi1-1 = <0>, "+3+11";
++              spi1-2 = <0>, "+4+12";
++              spi2-0 = <0>, "+5+13";
++              spi2-1 = <0>, "+6+14";
++              spi2-2 = <0>, "+7+15";
++              dev = <&anyspi_00>,"compatible",
++                    <&anyspi_01>,"compatible",
++                    <&anyspi_10>,"compatible",
++                    <&anyspi_11>,"compatible",
++                    <&anyspi_12>,"compatible",
++                    <&anyspi_20>,"compatible",
++                    <&anyspi_21>,"compatible",
++                    <&anyspi_22>,"compatible";
++              speed = <&anyspi_00>, "spi-max-frequency:0",
++                      <&anyspi_01>, "spi-max-frequency:0",
++                      <&anyspi_10>, "spi-max-frequency:0",
++                      <&anyspi_11>, "spi-max-frequency:0",
++                      <&anyspi_12>, "spi-max-frequency:0",
++                      <&anyspi_20>, "spi-max-frequency:0",
++                      <&anyspi_21>, "spi-max-frequency:0",
++                      <&anyspi_22>, "spi-max-frequency:0";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0792-sound-Add-the-HiFiBerry-DAC-HD-version.patch b/target/linux/brcm2708/patches-4.19/950-0792-sound-Add-the-HiFiBerry-DAC-HD-version.patch
new file mode 100644 (file)
index 0000000..c8b8fd5
--- /dev/null
@@ -0,0 +1,776 @@
+From bb4781b1dac98688a3cf64cf728a64d811ca6add Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=B6rg=20Schambacher?=
+ <j-schambacher@users.noreply.github.com>
+Date: Tue, 21 Jan 2020 15:58:39 +0100
+Subject: [PATCH] sound: Add the HiFiBerry DAC+HD version
+
+This adds the driver for the DAC+HD version supporting HiFiBerry's
+PCM179x based DACs. It also adds PLL control for clock generation.
+
+Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   6 +
+ .../overlays/hifiberry-dacplushd-overlay.dts  | 106 ++++++
+ drivers/clk/Makefile                          |   1 +
+ drivers/clk/clk-hifiberry-dachd.c             | 333 ++++++++++++++++++
+ sound/soc/bcm/Kconfig                         |   7 +
+ sound/soc/bcm/Makefile                        |   2 +
+ sound/soc/bcm/hifiberry_dacplushd.c           | 235 ++++++++++++
+ 13 files changed, 696 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts
+ create mode 100644 drivers/clk/clk-hifiberry-dachd.c
+ create mode 100644 sound/soc/bcm/hifiberry_dacplushd.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -57,6 +57,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       hifiberry-dacplusadc.dtbo \
+       hifiberry-dacplusadcpro.dtbo \
+       hifiberry-dacplusdsp.dtbo \
++      hifiberry-dacplushd.dtbo \
+       hifiberry-digi.dtbo \
+       hifiberry-digi-pro.dtbo \
+       hy28a.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -956,6 +956,12 @@ Load:   dtoverlay=hifiberry-dacplusdsp
+ Params: <None>
++Name:   hifiberry-dacplushd
++Info:   Configures the HifiBerry DAC+ HD audio card
++Load:   dtoverlay=hifiberry-dacplushd
++Params: <None>
++
++
+ Name:   hifiberry-digi
+ Info:   Configures the HifiBerry Digi and Digi+ audio card
+ Load:   dtoverlay=hifiberry-digi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts
+@@ -0,0 +1,106 @@
++// Definitions for HiFiBerry DAC+ HD
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target-path = "/clocks";
++              __overlay__ {
++                      dachd_osc: pll_dachd_osc {
++                              compatible = "hifiberry,dachd-clk";
++                              #clock-cells = <0>;
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      pcm1792a@4c {
++                              compatible = "ti,pcm1792a";
++                              #sound-dai-cells = <0>;
++                              #clock-cells = <0>;
++                              clocks = <&dachd_osc>;
++                              reg = <0x4c>;
++                              status = "okay";
++                      };
++                      pll: pll@62 {
++                              compatible = "hifiberry,dachd-clk";
++                              #clock-cells = <0>;
++                              reg = <0x62>;
++                              clocks = <&dachd_osc>;
++                              status = "okay";
++                              common_pll_regs = [
++                                      02 53 03 00 07 20 0F 00
++                                      10 0D 11 1D 12 0D 13 8C
++                                      14 8C 15 8C 16 8C 17 8C
++                                      18 2A 1C 00 1D 0F 1F 00
++                                      2A 00 2C 00 2F 00 30 00
++                                      31 00 32 00 34 00 37 00
++                                      38 00 39 00 3A 00 3B 01
++                                      3E 00 3F 00 40 00 41 00
++                                      5A 00 5B 00 95 00 96 00
++                                      97 00 98 00 99 00 9A 00
++                                      9B 00 A2 00 A3 00 A4 00
++                                      B7 92 ];
++                              192k_pll_regs = [
++                                      1A 0C 1B 35 1E F0 20 09
++                                      21 50 2B 02 2D 10 2E 40
++                                      33 01 35 22 36 80 3C 22
++                                      3D 46 ];
++                              96k_pll_regs = [
++                                      1A 0C 1B 35 1E F0 20 09
++                                      21 50 2B 02 2D 10 2E 40
++                                      33 01 35 47 36 00 3C 32
++                                      3D 46 ];
++                              48k_pll_regs = [
++                                      1A 0C 1B 35 1E F0 20 09
++                                      21 50 2B 02 2D 10 2E 40
++                                      33 01 35 90 36 00 3C 42
++                                      3D 46 ];
++                              176k4_pll_regs = [
++                                      1A 3D 1B 09 1E F3 20 13
++                                      21 75 2B 04 2D 11 2E E0
++                                      33 02 35 25 36 C0 3C 22
++                                      3D 7A ];
++                              88k2_pll_regs = [
++                                      1A 3D 1B 09 1E F3 20 13
++                                      21 75 2B 04 2D 11 2E E0
++                                      33 01 35 4D 36 80 3C 32
++                                      3D 7A ];
++                              44k1_pll_regs = [
++                                      1A 3D 1B 09 1E F3 20 13
++                                      21 75 2B 04 2D 11 2E E0
++                                      33 01 35 9D 36 00 3C 42
++                                      3D 7A ];
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&sound>;
++              __overlay__ {
++                      compatible = "hifiberry,hifiberry-dacplushd";
++                      i2s-controller = <&i2s>;
++                      clocks = <&pll 0>;
++                      reset-gpio = <&gpio 16 GPIO_ACTIVE_LOW>;
++                      status = "okay";
++              };
++      };
++
++};
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -32,6 +32,7 @@ obj-$(CONFIG_COMMON_CLK_ASPEED)              += clk-
+ obj-$(CONFIG_ARCH_HIGHBANK)           += clk-highbank.o
+ obj-$(CONFIG_CLK_HSDK)                        += clk-hsdk-pll.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD) += clk-hifiberry-dachd.o
+ obj-$(CONFIG_COMMON_CLK_MAX77686)     += clk-max77686.o
+ obj-$(CONFIG_COMMON_CLK_MAX9485)      += clk-max9485.o
+ obj-$(CONFIG_ARCH_MOXART)             += clk-moxart.o
+--- /dev/null
++++ b/drivers/clk/clk-hifiberry-dachd.c
+@@ -0,0 +1,333 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Clock Driver for HiFiBerry DAC+ HD
++ *
++ * Author: Joerg Schambacher, i2Audio GmbH for HiFiBerry
++ *         Copyright 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/clk-provider.h>
++#include <linux/clk.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++#include <linux/regmap.h>
++
++#define NO_PLL_RESET                  0
++#define PLL_RESET                     1
++#define HIFIBERRY_PLL_MAX_REGISTER    256
++#define DEFAULT_RATE                  44100
++
++static struct reg_default hifiberry_pll_reg_defaults[] = {
++      {0x02, 0x53}, {0x03, 0x00}, {0x07, 0x20}, {0x0F, 0x00},
++      {0x10, 0x0D}, {0x11, 0x1D}, {0x12, 0x0D}, {0x13, 0x8C},
++      {0x14, 0x8C}, {0x15, 0x8C}, {0x16, 0x8C}, {0x17, 0x8C},
++      {0x18, 0x2A}, {0x1C, 0x00}, {0x1D, 0x0F}, {0x1F, 0x00},
++      {0x2A, 0x00}, {0x2C, 0x00}, {0x2F, 0x00}, {0x30, 0x00},
++      {0x31, 0x00}, {0x32, 0x00}, {0x34, 0x00}, {0x37, 0x00},
++      {0x38, 0x00}, {0x39, 0x00}, {0x3A, 0x00}, {0x3B, 0x01},
++      {0x3E, 0x00}, {0x3F, 0x00}, {0x40, 0x00}, {0x41, 0x00},
++      {0x5A, 0x00}, {0x5B, 0x00}, {0x95, 0x00}, {0x96, 0x00},
++      {0x97, 0x00}, {0x98, 0x00}, {0x99, 0x00}, {0x9A, 0x00},
++      {0x9B, 0x00}, {0xA2, 0x00}, {0xA3, 0x00}, {0xA4, 0x00},
++      {0xB7, 0x92},
++      {0x1A, 0x3D}, {0x1B, 0x09}, {0x1E, 0xF3}, {0x20, 0x13},
++      {0x21, 0x75}, {0x2B, 0x04}, {0x2D, 0x11}, {0x2E, 0xE0},
++      {0x3D, 0x7A},
++      {0x35, 0x9D}, {0x36, 0x00}, {0x3C, 0x42},
++      { 177, 0xAC},
++};
++static struct reg_default common_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
++static int num_common_pll_regs;
++static struct reg_default dedicated_192k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
++static int num_dedicated_192k_pll_regs;
++static struct reg_default dedicated_96k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
++static int num_dedicated_96k_pll_regs;
++static struct reg_default dedicated_48k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
++static int num_dedicated_48k_pll_regs;
++static struct reg_default dedicated_176k4_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
++static int num_dedicated_176k4_pll_regs;
++static struct reg_default dedicated_88k2_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
++static int num_dedicated_88k2_pll_regs;
++static struct reg_default dedicated_44k1_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
++static int num_dedicated_44k1_pll_regs;
++
++/**
++ * struct clk_hifiberry_drvdata - Common struct to the HiFiBerry DAC HD Clk
++ * @hw: clk_hw for the common clk framework
++ */
++struct clk_hifiberry_drvdata {
++      struct regmap *regmap;
++      struct clk *clk;
++      struct clk_hw hw;
++      unsigned long rate;
++};
++
++#define to_hifiberry_clk(_hw) \
++      container_of(_hw, struct clk_hifiberry_drvdata, hw)
++
++static int clk_hifiberry_dachd_write_pll_regs(struct regmap *regmap,
++                              struct reg_default *regs,
++                              int num, int do_pll_reset)
++{
++      int i;
++      int ret = 0;
++      char pll_soft_reset[] = { 177, 0xAC, };
++
++      for (i = 0; i < num; i++) {
++              ret |= regmap_write(regmap, regs[i].reg, regs[i].def);
++              if (ret)
++                      return ret;
++      }
++      if (do_pll_reset) {
++              ret |= regmap_write(regmap, pll_soft_reset[0],
++                                              pll_soft_reset[1]);
++              mdelay(10);
++      }
++      return ret;
++}
++
++static unsigned long clk_hifiberry_dachd_recalc_rate(struct clk_hw *hw,
++      unsigned long parent_rate)
++{
++      return to_hifiberry_clk(hw)->rate;
++}
++
++static long clk_hifiberry_dachd_round_rate(struct clk_hw *hw,
++      unsigned long rate, unsigned long *parent_rate)
++{
++      return rate;
++}
++
++static int clk_hifiberry_dachd_set_rate(struct clk_hw *hw,
++      unsigned long rate, unsigned long parent_rate)
++{
++      int ret;
++      struct clk_hifiberry_drvdata *drvdata = to_hifiberry_clk(hw);
++
++      switch (rate) {
++      case 44100:
++              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
++                      dedicated_44k1_pll_regs, num_dedicated_44k1_pll_regs,
++                      PLL_RESET);
++              break;
++      case 88200:
++              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
++                      dedicated_88k2_pll_regs, num_dedicated_88k2_pll_regs,
++                      PLL_RESET);
++              break;
++      case 176400:
++              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
++                      dedicated_176k4_pll_regs, num_dedicated_176k4_pll_regs,
++                      PLL_RESET);
++              break;
++      case 48000:
++              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
++                      dedicated_48k_pll_regs, num_dedicated_48k_pll_regs,
++                      PLL_RESET);
++              break;
++      case 96000:
++              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
++                      dedicated_96k_pll_regs, num_dedicated_96k_pll_regs,
++                      PLL_RESET);
++              break;
++      case 192000:
++              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
++                      dedicated_192k_pll_regs, num_dedicated_192k_pll_regs,
++                      PLL_RESET);
++              break;
++      default:
++              ret = -EINVAL;
++              break;
++      }
++      to_hifiberry_clk(hw)->rate = rate;
++
++      return ret;
++}
++
++const struct clk_ops clk_hifiberry_dachd_rate_ops = {
++      .recalc_rate = clk_hifiberry_dachd_recalc_rate,
++      .round_rate = clk_hifiberry_dachd_round_rate,
++      .set_rate = clk_hifiberry_dachd_set_rate,
++};
++
++static int clk_hifiberry_get_prop_values(struct device *dev,
++                                      char *prop_name,
++                                      struct reg_default *regs)
++{
++      int ret;
++      int i;
++      u8 tmp[2 * HIFIBERRY_PLL_MAX_REGISTER];
++
++      ret = of_property_read_variable_u8_array(dev->of_node, prop_name,
++                      tmp, 0, 2 * HIFIBERRY_PLL_MAX_REGISTER);
++      if (ret < 0)
++              return ret;
++      if (ret & 1) {
++              dev_err(dev,
++                      "%s <%s> -> #%i odd number of bytes for reg/val pairs!",
++                      __func__,
++                      prop_name,
++                      ret);
++              return -EINVAL;
++      }
++      ret /= 2;
++      for (i = 0; i < ret; i++) {
++              regs[i].reg = (u32)tmp[2 * i];
++              regs[i].def = (u32)tmp[2 * i + 1];
++      }
++      return ret;
++}
++
++
++static int clk_hifiberry_dachd_dt_parse(struct device *dev)
++{
++      num_common_pll_regs = clk_hifiberry_get_prop_values(dev,
++                              "common_pll_regs", common_pll_regs);
++      num_dedicated_44k1_pll_regs = clk_hifiberry_get_prop_values(dev,
++                              "44k1_pll_regs", dedicated_44k1_pll_regs);
++      num_dedicated_88k2_pll_regs = clk_hifiberry_get_prop_values(dev,
++                              "88k2_pll_regs", dedicated_88k2_pll_regs);
++      num_dedicated_176k4_pll_regs = clk_hifiberry_get_prop_values(dev,
++                              "176k4_pll_regs", dedicated_176k4_pll_regs);
++      num_dedicated_48k_pll_regs = clk_hifiberry_get_prop_values(dev,
++                              "48k_pll_regs", dedicated_48k_pll_regs);
++      num_dedicated_96k_pll_regs = clk_hifiberry_get_prop_values(dev,
++                              "96k_pll_regs", dedicated_96k_pll_regs);
++      num_dedicated_192k_pll_regs = clk_hifiberry_get_prop_values(dev,
++                              "192k_pll_regs", dedicated_192k_pll_regs);
++      return 0;
++}
++
++
++static int clk_hifiberry_dachd_remove(struct device *dev)
++{
++      of_clk_del_provider(dev->of_node);
++      return 0;
++}
++
++const struct regmap_config hifiberry_pll_regmap = {
++      .reg_bits = 8,
++      .val_bits = 8,
++      .max_register = HIFIBERRY_PLL_MAX_REGISTER,
++      .reg_defaults = hifiberry_pll_reg_defaults,
++      .num_reg_defaults = ARRAY_SIZE(hifiberry_pll_reg_defaults),
++      .cache_type = REGCACHE_RBTREE,
++};
++EXPORT_SYMBOL_GPL(hifiberry_pll_regmap);
++
++
++static int clk_hifiberry_dachd_i2c_probe(struct i2c_client *i2c,
++                           const struct i2c_device_id *id)
++{
++      struct clk_hifiberry_drvdata *hdclk;
++      int ret = 0;
++      struct clk_init_data init;
++      struct device *dev = &i2c->dev;
++      struct device_node *dev_node = dev->of_node;
++      struct regmap_config config = hifiberry_pll_regmap;
++
++      hdclk = devm_kzalloc(&i2c->dev,
++                      sizeof(struct clk_hifiberry_drvdata), GFP_KERNEL);
++      if (!hdclk)
++              return -ENOMEM;
++
++      i2c_set_clientdata(i2c, hdclk);
++
++      hdclk->regmap = devm_regmap_init_i2c(i2c, &config);
++
++      if (IS_ERR(hdclk->regmap))
++              return PTR_ERR(hdclk->regmap);
++
++      /* start PLL to allow detection of DAC */
++      ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap,
++                              hifiberry_pll_reg_defaults,
++                              ARRAY_SIZE(hifiberry_pll_reg_defaults),
++                              PLL_RESET);
++      if (ret)
++              return ret;
++
++      clk_hifiberry_dachd_dt_parse(dev);
++
++      /* restart PLL with configs from DTB */
++      ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap, common_pll_regs,
++                                      num_common_pll_regs, PLL_RESET);
++      if (ret)
++              return ret;
++
++      init.name = "clk-hifiberry-dachd";
++      init.ops = &clk_hifiberry_dachd_rate_ops;
++      init.flags = CLK_IS_BASIC;
++      init.parent_names = NULL;
++      init.num_parents = 0;
++
++      hdclk->hw.init = &init;
++
++      hdclk->clk = devm_clk_register(dev, &hdclk->hw);
++      if (IS_ERR(hdclk->clk)) {
++              dev_err(dev, "unable to register %s\n", init.name);
++              return PTR_ERR(hdclk->clk);
++      }
++
++      ret = of_clk_add_provider(dev_node, of_clk_src_simple_get, hdclk->clk);
++      if (ret != 0) {
++              dev_err(dev, "Cannot of_clk_add_provider");
++              return ret;
++      }
++
++      ret = clk_set_rate(hdclk->hw.clk, DEFAULT_RATE);
++      if (ret != 0) {
++              dev_err(dev, "Cannot set rate : %d\n",  ret);
++              return -EINVAL;
++      }
++
++      return ret;
++}
++
++static int clk_hifiberry_dachd_i2c_remove(struct i2c_client *i2c)
++{
++      clk_hifiberry_dachd_remove(&i2c->dev);
++      return 0;
++}
++
++static const struct i2c_device_id clk_hifiberry_dachd_i2c_id[] = {
++      { "dachd-clk", },
++      { }
++};
++MODULE_DEVICE_TABLE(i2c, clk_hifiberry_dachd_i2c_id);
++
++static const struct of_device_id clk_hifiberry_dachd_of_match[] = {
++      { .compatible = "hifiberry,dachd-clk", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, clk_hifiberry_dachd_of_match);
++
++static struct i2c_driver clk_hifiberry_dachd_i2c_driver = {
++      .probe          = clk_hifiberry_dachd_i2c_probe,
++      .remove         = clk_hifiberry_dachd_i2c_remove,
++      .id_table       = clk_hifiberry_dachd_i2c_id,
++      .driver         = {
++              .name   = "dachd-clk",
++              .of_match_table = of_match_ptr(clk_hifiberry_dachd_of_match),
++      },
++};
++
++module_i2c_driver(clk_hifiberry_dachd_i2c_driver);
++
++
++MODULE_DESCRIPTION("HiFiBerry DAC+ HD clock driver");
++MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:clk-hifiberry-dachd");
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -40,6 +40,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
+         help
+          Say Y or M if you want to add support for HifiBerry DAC+.
++config SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD
++        tristate "Support for HifiBerry DAC+ HD"
++        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++        select SND_SOC_PCM179X_I2C
++        help
++         Say Y or M if you want to add support for HifiBerry DAC+ HD.
++
+ config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
+         tristate "Support for HifiBerry DAC+ADC"
+         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -13,6 +13,7 @@ snd-soc-googlevoicehat-codec-objs := goo
+ # BCM2708 Machine Support
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
++snd-soc-hifiberry-dacplushd-objs := hifiberry_dacplushd.o
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
+ snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
+@@ -40,6 +41,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
+ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD)  += snd-soc-googlevoicehat-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD) += snd-soc-hifiberry-dacplushd.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
+--- /dev/null
++++ b/sound/soc/bcm/hifiberry_dacplushd.c
+@@ -0,0 +1,235 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * ASoC Driver for HiFiBerry DAC+ HD
++ *
++ * Author:    Joerg Schambacher, i2Audio GmbH for HiFiBerry
++ *            Copyright 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/kernel.h>
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/delay.h>
++#include <linux/gpio.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/i2c.h>
++#include <linux/clk.h>
++
++#include "../codecs/pcm179x.h"
++
++#define DEFAULT_RATE          44100
++
++struct brd_drv_data {
++      struct regmap *regmap;
++      struct clk *sclk;
++};
++
++static struct brd_drv_data drvdata;
++static struct gpio_desc *reset_gpio;
++static const unsigned int hb_dacplushd_rates[] = {
++      192000, 96000, 48000, 176400, 88200, 44100,
++};
++
++static struct snd_pcm_hw_constraint_list hb_dacplushd_constraints = {
++      .list = hb_dacplushd_rates,
++      .count = ARRAY_SIZE(hb_dacplushd_rates),
++};
++
++static int snd_rpi_hb_dacplushd_startup(struct snd_pcm_substream *substream)
++{
++      /* constraints for standard sample rates */
++      snd_pcm_hw_constraint_list(substream->runtime, 0,
++                              SNDRV_PCM_HW_PARAM_RATE,
++                              &hb_dacplushd_constraints);
++      return 0;
++}
++
++static void snd_rpi_hifiberry_dacplushd_set_sclk(
++              struct snd_soc_component *component,
++              int sample_rate)
++{
++      if (!IS_ERR(drvdata.sclk))
++              clk_set_rate(drvdata.sclk, sample_rate);
++}
++
++static int snd_rpi_hifiberry_dacplushd_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_dai_link *dai = rtd->dai_link;
++      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++
++      dai->name = "HiFiBerry DAC+ HD";
++      dai->stream_name = "HiFiBerry DAC+ HD HiFi";
++      dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++              | SND_SOC_DAIFMT_CBM_CFM;
++
++      /* allow only fixed 32 clock counts per channel */
++      snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
++
++      return 0;
++}
++
++static int snd_rpi_hifiberry_dacplushd_hw_params(
++      struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++      int ret = 0;
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++
++      struct snd_soc_component *component = rtd->codec_dai->component;
++
++      snd_rpi_hifiberry_dacplushd_set_sclk(component, params_rate(params));
++      return ret;
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_hifiberry_dacplushd_ops = {
++      .startup = snd_rpi_hb_dacplushd_startup,
++      .hw_params = snd_rpi_hifiberry_dacplushd_hw_params,
++};
++
++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplushd_dai[] = {
++{
++      .name           = "HiFiBerry DAC+ HD",
++      .stream_name    = "HiFiBerry DAC+ HD HiFi",
++      .cpu_dai_name   = "bcm2708-i2s.0",
++      .codec_dai_name = "pcm179x-hifi",
++      .platform_name  = "bcm2708-i2s.0",
++      .codec_name     = "pcm179x.1-004c",
++      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++                              SND_SOC_DAIFMT_CBS_CFS,
++      .ops            = &snd_rpi_hifiberry_dacplushd_ops,
++      .init           = snd_rpi_hifiberry_dacplushd_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_hifiberry_dacplushd = {
++      .name         = "snd_rpi_hifiberry_dacplushd",
++      .driver_name  = "HifiberryDacplusHD",
++      .owner        = THIS_MODULE,
++      .dai_link     = snd_rpi_hifiberry_dacplushd_dai,
++      .num_links    = ARRAY_SIZE(snd_rpi_hifiberry_dacplushd_dai),
++};
++
++static int snd_rpi_hifiberry_dacplushd_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++      static int dac_reset_done;
++      struct device *dev = &pdev->dev;
++      struct device_node *dev_node = dev->of_node;
++
++      snd_rpi_hifiberry_dacplushd.dev = &pdev->dev;
++
++      /* get GPIO and release DAC from RESET */
++      if (!dac_reset_done) {
++              reset_gpio = gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
++              if (IS_ERR(reset_gpio)) {
++                      dev_err(&pdev->dev, "gpiod_get() failed\n");
++                      return -EINVAL;
++              }
++              dac_reset_done = 1;
++      }
++      if (!IS_ERR(reset_gpio))
++              gpiod_set_value(reset_gpio, 0);
++      msleep(1);
++      if (!IS_ERR(reset_gpio))
++              gpiod_set_value(reset_gpio, 1);
++      msleep(1);
++      if (!IS_ERR(reset_gpio))
++              gpiod_set_value(reset_gpio, 0);
++
++      if (pdev->dev.of_node) {
++              struct device_node *i2s_node;
++              struct snd_soc_dai_link *dai;
++
++              dai = &snd_rpi_hifiberry_dacplushd_dai[0];
++              i2s_node = of_parse_phandle(pdev->dev.of_node,
++                      "i2s-controller", 0);
++
++              if (i2s_node) {
++                      dai->cpu_dai_name = NULL;
++                      dai->cpu_of_node = i2s_node;
++                      dai->platform_name = NULL;
++                      dai->platform_of_node = i2s_node;
++              } else {
++                      return -EPROBE_DEFER;
++              }
++
++      }
++
++      ret = devm_snd_soc_register_card(&pdev->dev,
++                      &snd_rpi_hifiberry_dacplushd);
++      if (ret && ret != -EPROBE_DEFER) {
++              dev_err(&pdev->dev,
++                      "snd_soc_register_card() failed: %d\n", ret);
++              return ret;
++      }
++      if (ret == -EPROBE_DEFER)
++              return ret;
++
++      dev_set_drvdata(dev, &drvdata);
++      if (dev_node == NULL) {
++              dev_err(&pdev->dev, "Device tree node not found\n");
++              return -ENODEV;
++      }
++
++      drvdata.sclk = devm_clk_get(dev, NULL);
++      if (IS_ERR(drvdata.sclk)) {
++              drvdata.sclk = ERR_PTR(-ENOENT);
++              return -ENODEV;
++      }
++
++      clk_set_rate(drvdata.sclk, DEFAULT_RATE);
++
++      return ret;
++}
++
++static int snd_rpi_hifiberry_dacplushd_remove(struct platform_device *pdev)
++{
++      if (IS_ERR(reset_gpio))
++              return -EINVAL;
++
++      /* put DAC into RESET and release GPIO */
++      gpiod_set_value(reset_gpio, 0);
++      gpiod_put(reset_gpio);
++
++      return 0;
++}
++
++static const struct of_device_id snd_rpi_hifiberry_dacplushd_of_match[] = {
++      { .compatible = "hifiberry,hifiberry-dacplushd", },
++      {},
++};
++
++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplushd_of_match);
++
++static struct platform_driver snd_rpi_hifiberry_dacplushd_driver = {
++      .driver = {
++              .name   = "snd-rpi-hifiberry-dacplushd",
++              .owner  = THIS_MODULE,
++              .of_match_table = snd_rpi_hifiberry_dacplushd_of_match,
++      },
++      .probe          = snd_rpi_hifiberry_dacplushd_probe,
++      .remove         = snd_rpi_hifiberry_dacplushd_remove,
++};
++
++module_platform_driver(snd_rpi_hifiberry_dacplushd_driver);
++
++MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ HD");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/brcm2708/patches-4.19/950-0793-Initialise-rpi-firmware-before-clk-bcm2835.patch b/target/linux/brcm2708/patches-4.19/950-0793-Initialise-rpi-firmware-before-clk-bcm2835.patch
new file mode 100644 (file)
index 0000000..3a68193
--- /dev/null
@@ -0,0 +1,47 @@
+From 43551a95378230b8d062e107e012573739af2bf1 Mon Sep 17 00:00:00 2001
+From: Luke Hinds <7058938+lukehinds@users.noreply.github.com>
+Date: Wed, 22 Jan 2020 16:03:00 +0000
+Subject: [PATCH] Initialise rpi-firmware before clk-bcm2835
+
+The IMA (Integrity Measurement Architecture) looks for a TPM (Trusted
+Platform Module) having been registered when it initialises; otherwise
+it assumes there is no TPM. It has been observed on BCM2835 that IMA
+is initialised before TPM, and that initialising the BCM2835 clock
+driver before the firmware driver has the effect of reversing this
+order.
+
+Change the firmware driver to initialise at core_initcall, delaying the
+BCM2835 clock driver to postcore_initcall.
+
+See: https://github.com/raspberrypi/linux/issues/3291
+     https://github.com/raspberrypi/linux/pull/3297
+
+Signed-off-by: Luke Hinds <lhinds@redhat.com>
+Co-authored-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c  | 2 +-
+ drivers/firmware/raspberrypi.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -2388,7 +2388,7 @@ static int __init __bcm2835_clk_driver_i
+ {
+       return platform_driver_register(&bcm2835_clk_driver);
+ }
+-core_initcall(__bcm2835_clk_driver_init);
++postcore_initcall(__bcm2835_clk_driver_init);
+ MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+ MODULE_DESCRIPTION("BCM2835 clock driver");
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -404,7 +404,7 @@ out2:
+ out1:
+       return ret;
+ }
+-subsys_initcall(rpi_firmware_init);
++core_initcall(rpi_firmware_init);
+ static void __init rpi_firmware_exit(void)
+ {
diff --git a/target/linux/brcm2708/patches-4.19/950-0794-Fix-master-mode-settings-of-HiFiBerry-DAC-ADC-PRO-ca.patch b/target/linux/brcm2708/patches-4.19/950-0794-Fix-master-mode-settings-of-HiFiBerry-DAC-ADC-PRO-ca.patch
new file mode 100644 (file)
index 0000000..020118d
--- /dev/null
@@ -0,0 +1,26 @@
+From 898cec85907f8f171264c8be281a9ac2979b1655 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=B6rg=20Schambacher?=
+ <j-schambacher@users.noreply.github.com>
+Date: Thu, 23 Jan 2020 13:32:13 +0100
+Subject: [PATCH] Fix master mode settings of HiFiBerry DAC+ADC PRO
+ card (#3424)
+
+This patch fixes the board DAI setting when in master-mode.
+Wrong setting could have caused random pop noise.
+
+Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
+---
+ sound/soc/bcm/hifiberry_dacplusadcpro.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/soc/bcm/hifiberry_dacplusadcpro.c
++++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
+@@ -285,6 +285,8 @@ static int snd_rpi_hifiberry_dacplusadcp
+               dai->name = "HiFiBerry DAC+ADC Pro";
+               dai->stream_name = "HiFiBerry DAC+ADC Pro HiFi";
++              dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++                      | SND_SOC_DAIFMT_CBM_CFM;
+               // set DAC DAI configuration
+               ret = snd_soc_dai_set_fmt(rtd->codec_dais[0],
diff --git a/target/linux/brcm2708/patches-4.19/950-0795-overlays-Use-preferred-compatible-strings.patch b/target/linux/brcm2708/patches-4.19/950-0795-overlays-Use-preferred-compatible-strings.patch
new file mode 100644 (file)
index 0000000..7e5921d
--- /dev/null
@@ -0,0 +1,72 @@
+From 0a865ae13d5f98594562ebe5713caec65ab689e5 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 24 Jan 2020 09:02:37 +0000
+Subject: [PATCH] overlays: Use preferred compatible strings
+
+Make sure all overlays have correct compatible strings before enabling
+the automated checking.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts           | 2 +-
+ arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts               | 2 ++
+ arch/arm/boot/dts/overlays/pwm-overlay.dts                     | 2 ++
+ arch/arm/boot/dts/overlays/smi-dev-overlay.dts                 | 2 ++
+ 5 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target-path = "/clocks";
+--- a/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
++++ b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+ / {
+-      compatible = "brcm,bcm2708";
++      compatible = "brcm,bcm2835";
+       fragment@0 {
+               target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts
+@@ -17,6 +17,8 @@ N.B.:
+ */
+ / {
++      compatible = "brcm,bcm2835";
++
+       fragment@0 {
+               target = <&gpio>;
+               __overlay__ {
+--- a/arch/arm/boot/dts/overlays/pwm-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pwm-overlay.dts
+@@ -15,6 +15,8 @@ N.B.:
+ */
+ / {
++      compatible = "brcm,bcm2835";
++
+       fragment@0 {
+               target = <&gpio>;
+               __overlay__ {
+--- a/arch/arm/boot/dts/overlays/smi-dev-overlay.dts
++++ b/arch/arm/boot/dts/overlays/smi-dev-overlay.dts
+@@ -5,6 +5,8 @@
+ /plugin/;
+ /{
++      compatible = "brcm,bcm2835";
++
+       fragment@0 {
+               target = <&soc>;
+               __overlay__ {
diff --git a/target/linux/brcm2708/patches-4.19/950-0796-tty-amba-pl011-Add-un-throttle-support.patch b/target/linux/brcm2708/patches-4.19/950-0796-tty-amba-pl011-Add-un-throttle-support.patch
new file mode 100644 (file)
index 0000000..0ab6cf2
--- /dev/null
@@ -0,0 +1,61 @@
+From d4f4b57c667141ca98711cfcb30ae2b8deb1a034 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 24 Jan 2020 11:38:28 +0000
+Subject: [PATCH] tty: amba-pl011: Add un/throttle support
+
+The PL011 driver lacks throttle and unthrottle methods. As a result,
+sending more data to the Pi than it can immediately sink while CRTSCTS
+is enabled causes a NULL pointer to be followed.
+
+Add a throttle handler that disables the RX interrupts, and an
+unthrottle handler that reenables them.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/tty/serial/amba-pl011.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -1323,6 +1323,32 @@ static void pl011_start_tx(struct uart_p
+               pl011_start_tx_pio(uap);
+ }
++static void pl011_throttle(struct uart_port *port)
++{
++      struct uart_amba_port *uap =
++          container_of(port, struct uart_amba_port, port);
++      unsigned long flags;
++
++      spin_lock_irqsave(&uap->port.lock, flags);
++      uap->im &= ~(UART011_RTIM | UART011_RXIM);
++      pl011_write(uap->im, uap, REG_IMSC);
++      spin_unlock_irqrestore(&uap->port.lock, flags);
++}
++
++static void pl011_unthrottle(struct uart_port *port)
++{
++      struct uart_amba_port *uap =
++          container_of(port, struct uart_amba_port, port);
++      unsigned long flags;
++
++      spin_lock_irqsave(&uap->port.lock, flags);
++      uap->im |= UART011_RTIM;
++      if (!pl011_dma_rx_running(uap))
++          uap->im |= UART011_RXIM;
++      pl011_write(uap->im, uap, REG_IMSC);
++      spin_unlock_irqrestore(&uap->port.lock, flags);
++}
++
+ static void pl011_stop_rx(struct uart_port *port)
+ {
+       struct uart_amba_port *uap =
+@@ -2165,6 +2191,8 @@ static const struct uart_ops amba_pl011_
+       .stop_tx        = pl011_stop_tx,
+       .start_tx       = pl011_start_tx,
+       .stop_rx        = pl011_stop_rx,
++      .throttle       = pl011_throttle,
++      .unthrottle     = pl011_unthrottle,
+       .enable_ms      = pl011_enable_ms,
+       .break_ctl      = pl011_break_ctl,
+       .startup        = pl011_startup,
diff --git a/target/linux/brcm2708/patches-4.19/950-0797-Fix-i2c-pwm-pca9685a-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0797-Fix-i2c-pwm-pca9685a-overlay.patch
new file mode 100644 (file)
index 0000000..e01e7fd
--- /dev/null
@@ -0,0 +1,20 @@
+From 493aa5b9a2f57003dd0a16946eb56b08650090b4 Mon Sep 17 00:00:00 2001
+From: MikeDK <m.kaplan@evva.com>
+Date: Sun, 26 Jan 2020 23:33:54 +0100
+Subject: [PATCH] Fix i2c-pwm-pca9685a overlay
+
+---
+ arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
+@@ -13,7 +13,7 @@
+                       status = "okay";
+                       pca: pca@40 {
+-                              compatible = "nxp,pca9685";
++                              compatible = "nxp,pca9685-pwm";
+                               #pwm-cells = <2>;
+                               reg = <0x40>;
+                               status = "okay";
diff --git a/target/linux/brcm2708/patches-4.19/950-0798-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-PRO-sound-.patch b/target/linux/brcm2708/patches-4.19/950-0798-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-PRO-sound-.patch
new file mode 100644 (file)
index 0000000..233e368
--- /dev/null
@@ -0,0 +1,89 @@
+From c23190019110e3314041f2184552a8343de55117 Mon Sep 17 00:00:00 2001
+From: j-schambacher <joerg@i2audio.com>
+Date: Mon, 27 Jan 2020 17:45:51 +0100
+Subject: [PATCH] adds LED OFF feature to HiFiBerry DAC+ADC PRO sound
+ card
+
+This adds a DT overlay parameter 'leds_off' which allows
+to switch off the onboard activity LEDs at all times
+which has been requested by some users.
+
+Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
+---
+ arch/arm/boot/dts/overlays/README                 |  2 ++
+ .../overlays/hifiberry-dacplusadcpro-overlay.dts  |  1 +
+ sound/soc/bcm/hifiberry_dacplusadcpro.c           | 15 +++++++++++++--
+ 3 files changed, 16 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -948,6 +948,8 @@ Params: 24db_digital_gain       Allow ga
+                                 that does not result in clipping/distortion!)
+         slave                   Force DAC+ADC 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.
+ Name:   hifiberry-dacplusdsp
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
+@@ -60,5 +60,6 @@
+               24db_digital_gain =
+                       <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,24db_digital_gain?";
+               slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?";
++              leds_off = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,leds_off?";
+       };
+ };
+--- a/sound/soc/bcm/hifiberry_dacplusadcpro.c
++++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
+@@ -54,6 +54,7 @@ struct pcm512x_priv {
+ static bool slave;
+ static bool snd_rpi_hifiberry_is_dacpro;
+ static bool digital_gain_0db_limit = true;
++static bool leds_off;
+ static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
+       0x00, 0x01, 0x02, 0x03, 0x10
+@@ -321,7 +322,10 @@ static int snd_rpi_hifiberry_dacplusadcp
+       snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
+       snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
+-      snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++      if (leds_off)
++              snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++      else
++              snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
+       ret = pcm1863_add_controls(adc);
+       if (ret < 0)
+@@ -331,7 +335,10 @@ static int snd_rpi_hifiberry_dacplusadcp
+       /* set GPIO2 to output, GPIO3 input */
+       snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
+       snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
+-      snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
++      if (leds_off)
++              snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
++      else
++              snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
+       if (digital_gain_0db_limit) {
+               int ret;
+@@ -417,6 +424,8 @@ static int snd_rpi_hifiberry_dacplusadcp
+       struct snd_soc_component *dac = rtd->codec_dais[0]->component;
+       struct snd_soc_component *adc = rtd->codec_dais[1]->component;
++      if (leds_off)
++              return 0;
+       /* switch on respective LED */
+       if (!substream->stream)
+               snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
+@@ -508,6 +517,8 @@ static int snd_rpi_hifiberry_dacplusadcp
+               pdev->dev.of_node, "hifiberry-dacplusadcpro,24db_digital_gain");
+       slave = of_property_read_bool(pdev->dev.of_node,
+                                       "hifiberry-dacplusadcpro,slave");
++      leds_off = of_property_read_bool(pdev->dev.of_node,
++                                      "hifiberry-dacplusadcpro,leds_off");
+       ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplusadcpro);
+       if (ret && ret != -EPROBE_DEFER)
+               dev_err(&pdev->dev,
diff --git a/target/linux/brcm2708/patches-4.19/950-0799-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-sound-card.patch b/target/linux/brcm2708/patches-4.19/950-0799-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-sound-card.patch
new file mode 100644 (file)
index 0000000..2bc0306
--- /dev/null
@@ -0,0 +1,76 @@
+From ee513338448ddbb72ac8f76e7053865fe926a18c Mon Sep 17 00:00:00 2001
+From: j-schambacher <joerg@i2audio.com>
+Date: Mon, 27 Jan 2020 20:37:34 +0100
+Subject: [PATCH] adds LED OFF feature to HiFiBerry DAC+ADC sound card
+
+This adds a DT overlay parameter 'leds_off' which allows
+to switch off the onboard activity LEDs at all times
+which has been requested by some users.
+
+Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
+---
+ arch/arm/boot/dts/overlays/README                      |  2 ++
+ .../boot/dts/overlays/hifiberry-dacplusadc-overlay.dts |  1 +
+ sound/soc/bcm/hifiberry_dacplusadc.c                   | 10 +++++++++-
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -927,6 +927,8 @@ Params: 24db_digital_gain       Allow ga
+                                 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.
+ Name:   hifiberry-dacplusadcpro
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
+@@ -67,5 +67,6 @@
+               24db_digital_gain =
+                       <&hifiberry_dacplusadc>,"hifiberry,24db_digital_gain?";
+               slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?";
++              leds_off = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,leds_off?";
+       };
+ };
+--- a/sound/soc/bcm/hifiberry_dacplusadc.c
++++ b/sound/soc/bcm/hifiberry_dacplusadc.c
+@@ -54,6 +54,7 @@ struct pcm512x_priv {
+ static bool slave;
+ static bool snd_rpi_hifiberry_is_dacpro;
+ static bool digital_gain_0db_limit = true;
++static bool leds_off;
+ static void snd_rpi_hifiberry_dacplusadc_select_clk(struct snd_soc_component *component,
+       int clk_id)
+@@ -175,7 +176,10 @@ static int snd_rpi_hifiberry_dacplusadc_
+       snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
+       snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
+-      snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++      if (leds_off)
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++      else
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
+       if (digital_gain_0db_limit) {
+               int ret;
+@@ -256,6 +260,8 @@ static int snd_rpi_hifiberry_dacplusadc_
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_component *component = rtd->codec_dai->component;
++      if (leds_off)
++              return 0;
+       snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
+                                        0x08, 0x08);
+       hifiberry_dacplusadc_LED_cnt++;
+@@ -347,6 +353,8 @@ static int snd_rpi_hifiberry_dacplusadc_
+               pdev->dev.of_node, "hifiberry,24db_digital_gain");
+       slave = of_property_read_bool(pdev->dev.of_node,
+                                       "hifiberry-dacplusadc,slave");
++      leds_off = of_property_read_bool(pdev->dev.of_node,
++                                      "hifiberry-dacplusadc,leds_off");
+       ret = devm_snd_soc_register_card(&pdev->dev,
+                                                &snd_rpi_hifiberry_dacplusadc);
diff --git a/target/linux/brcm2708/patches-4.19/950-0800-adds-LED-OFF-feature-to-HiFiBerry-DAC-DAC-PRO-sound-.patch b/target/linux/brcm2708/patches-4.19/950-0800-adds-LED-OFF-feature-to-HiFiBerry-DAC-DAC-PRO-sound-.patch
new file mode 100644 (file)
index 0000000..68763fe
--- /dev/null
@@ -0,0 +1,77 @@
+From 5eccee0e620b799558d89ebee29280116ad37e4f Mon Sep 17 00:00:00 2001
+From: j-schambacher <joerg@i2audio.com>
+Date: Mon, 27 Jan 2020 20:58:24 +0100
+Subject: [PATCH] adds LED OFF feature to HiFiBerry DAC+/DAC+PRO sound
+ cards
+
+This adds a DT overlay parameter 'leds_off' which allows
+to switch off the onboard activity LEDs at all times
+which has been requested by some users.
+
+Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
+---
+ arch/arm/boot/dts/overlays/README                      |  2 ++
+ .../boot/dts/overlays/hifiberry-dacplus-overlay.dts    |  1 +
+ sound/soc/bcm/hifiberry_dacplus.c                      | 10 +++++++++-
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -906,6 +906,8 @@ Params: 24db_digital_gain       Allow ga
+                                 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.
+ Name:   hifiberry-dacplusadc
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
+@@ -55,5 +55,6 @@
+               24db_digital_gain =
+                       <&hifiberry_dacplus>,"hifiberry,24db_digital_gain?";
+               slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?";
++              leds_off = <&hifiberry_dacplus>,"hifiberry-dacplus,leds_off?";
+       };
+ };
+--- a/sound/soc/bcm/hifiberry_dacplus.c
++++ b/sound/soc/bcm/hifiberry_dacplus.c
+@@ -50,6 +50,7 @@ struct pcm512x_priv {
+ static bool slave;
+ static bool snd_rpi_hifiberry_is_dacpro;
+ static bool digital_gain_0db_limit = true;
++static bool leds_off;
+ static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_component *component,
+       int clk_id)
+@@ -171,7 +172,10 @@ static int snd_rpi_hifiberry_dacplus_ini
+       snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
+       snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
+-      snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++      if (leds_off)
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++      else
++              snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
+       if (digital_gain_0db_limit)
+       {
+@@ -251,6 +255,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 (leds_off)
++              return 0;
+       snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
+       return 0;
+ }
+@@ -319,6 +325,8 @@ static int snd_rpi_hifiberry_dacplus_pro
+                       pdev->dev.of_node, "hifiberry,24db_digital_gain");
+               slave = of_property_read_bool(pdev->dev.of_node,
+                                               "hifiberry-dacplus,slave");
++              leds_off = of_property_read_bool(pdev->dev.of_node,
++                                              "hifiberry-dacplus,leds_off");
+       }
+       ret = devm_snd_soc_register_card(&pdev->dev,
diff --git a/target/linux/brcm2708/patches-4.19/950-0801-pisound-Added-reading-Pisound-board-hardware-revisio.patch b/target/linux/brcm2708/patches-4.19/950-0801-pisound-Added-reading-Pisound-board-hardware-revisio.patch
new file mode 100644 (file)
index 0000000..bb6afe3
--- /dev/null
@@ -0,0 +1,201 @@
+From a879ab9cad6b598c08988404934273d3cbfbd993 Mon Sep 17 00:00:00 2001
+From: gtrainavicius <gtrainavicius@users.noreply.github.com>
+Date: Tue, 28 Jan 2020 14:16:37 +0200
+Subject: [PATCH] pisound: Added reading Pisound board hardware
+ revision and exposing it (#3425)
+
+pisound: Added reading Pisound board hardware revision and exposing it in kernel log and sysfs file:
+
+/sys/kernel/pisound/hw_version
+
+Signed-off-by: Giedrius <giedrius@blokas.io>
+---
+ sound/soc/bcm/pisound.c | 86 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 59 insertions(+), 27 deletions(-)
+
+--- a/sound/soc/bcm/pisound.c
++++ b/sound/soc/bcm/pisound.c
+@@ -51,7 +51,8 @@ static void pisnd_spi_set_callback(pisnd
+ static const char *pisnd_spi_get_serial(void);
+ static const char *pisnd_spi_get_id(void);
+-static const char *pisnd_spi_get_version(void);
++static const char *pisnd_spi_get_fw_version(void);
++static const char *pisnd_spi_get_hw_version(void);
+ static int pisnd_midi_init(struct snd_card *card);
+ static void pisnd_midi_uninit(void);
+@@ -222,7 +223,9 @@ static pisnd_spi_recv_cb g_recvCallback;
+ static char g_serial_num[11];
+ static char g_id[25];
+-static char g_version[5];
++enum { MAX_VERSION_STR_LEN = 6 };
++static char g_fw_version[MAX_VERSION_STR_LEN];
++static char g_hw_version[MAX_VERSION_STR_LEN];
+ static uint8_t g_ledFlashDuration;
+ static bool    g_ledFlashDurationChanged;
+@@ -558,7 +561,8 @@ static int spi_read_info(void)
+       char *p;
+       memset(g_serial_num, 0, sizeof(g_serial_num));
+-      memset(g_version, 0, sizeof(g_version));
++      memset(g_fw_version, 0, sizeof(g_fw_version));
++      strcpy(g_hw_version, "1.0"); // Assume 1.0 hw version.
+       memset(g_id, 0, sizeof(g_id));
+       tmp = spi_transfer16(0);
+@@ -581,12 +585,28 @@ static int spi_read_info(void)
+                               return -EINVAL;
+                       snprintf(
+-                              g_version,
+-                              sizeof(g_version),
++                              g_fw_version,
++                              MAX_VERSION_STR_LEN,
+                               "%x.%02x",
+                               buffer[0],
+                               buffer[1]
+                               );
++
++                      g_fw_version[MAX_VERSION_STR_LEN-1] = '\0';
++                      break;
++              case 3:
++                      if (n != 2)
++                              return -EINVAL;
++
++                      snprintf(
++                              g_hw_version,
++                              MAX_VERSION_STR_LEN,
++                              "%x.%x",
++                              buffer[0],
++                              buffer[1]
++                      );
++
++                      g_hw_version[MAX_VERSION_STR_LEN-1] = '\0';
+                       break;
+               case 1:
+                       if (n >= sizeof(g_serial_num))
+@@ -596,12 +616,14 @@ static int spi_read_info(void)
+                       break;
+               case 2:
+                       {
+-                              if (n >= sizeof(g_id))
++                              if (n*2 >= sizeof(g_id))
+                                       return -EINVAL;
+                               p = g_id;
+                               for (j = 0; j < n; ++j)
+                                       p += sprintf(p, "%02x", buffer[j]);
++
++                              *p = '\0';
+                       }
+                       break;
+               default:
+@@ -619,7 +641,8 @@ static int pisnd_spi_init(struct device
+       memset(g_serial_num, 0, sizeof(g_serial_num));
+       memset(g_id, 0, sizeof(g_id));
+-      memset(g_version, 0, sizeof(g_version));
++      memset(g_fw_version, 0, sizeof(g_fw_version));
++      memset(g_hw_version, 0, sizeof(g_hw_version));
+       spi = pisnd_spi_find_device();
+@@ -729,26 +752,22 @@ static void pisnd_spi_set_callback(pisnd
+ static const char *pisnd_spi_get_serial(void)
+ {
+-      if (strlen(g_serial_num))
+-              return g_serial_num;
+-
+-      return "";
++      return g_serial_num;
+ }
+ static const char *pisnd_spi_get_id(void)
+ {
+-      if (strlen(g_id))
+-              return g_id;
+-
+-      return "";
++      return g_id;
+ }
+-static const char *pisnd_spi_get_version(void)
++static const char *pisnd_spi_get_fw_version(void)
+ {
+-      if (strlen(g_version))
+-              return g_version;
++      return g_fw_version;
++}
+-      return "";
++static const char *pisnd_spi_get_hw_version(void)
++{
++      return g_hw_version;
+ }
+ static const struct of_device_id pisound_of_match[] = {
+@@ -1054,13 +1073,22 @@ static ssize_t pisnd_id_show(
+       return sprintf(buf, "%s\n", pisnd_spi_get_id());
+ }
+-static ssize_t pisnd_version_show(
++static ssize_t pisnd_fw_version_show(
+       struct kobject *kobj,
+       struct kobj_attribute *attr,
+       char *buf
+       )
+ {
+-      return sprintf(buf, "%s\n", pisnd_spi_get_version());
++      return sprintf(buf, "%s\n", pisnd_spi_get_fw_version());
++}
++
++static ssize_t pisnd_hw_version_show(
++      struct kobject *kobj,
++      struct kobj_attribute *attr,
++      char *buf
++)
++{
++      return sprintf(buf, "%s\n", pisnd_spi_get_hw_version());
+ }
+ static ssize_t pisnd_led_store(
+@@ -1085,15 +1113,18 @@ static struct kobj_attribute pisnd_seria
+       __ATTR(serial, 0444, pisnd_serial_show, NULL);
+ static struct kobj_attribute pisnd_id_attribute =
+       __ATTR(id, 0444, pisnd_id_show, NULL);
+-static struct kobj_attribute pisnd_version_attribute =
+-      __ATTR(version, 0444, pisnd_version_show, NULL);
++static struct kobj_attribute pisnd_fw_version_attribute =
++      __ATTR(version, 0444, pisnd_fw_version_show, NULL);
++static struct kobj_attribute pisnd_hw_version_attribute =
++__ATTR(hw_version, 0444, pisnd_hw_version_show, NULL);
+ static struct kobj_attribute pisnd_led_attribute =
+       __ATTR(led, 0644, NULL, pisnd_led_store);
+ static struct attribute *attrs[] = {
+       &pisnd_serial_attribute.attr,
+       &pisnd_id_attribute.attr,
+-      &pisnd_version_attribute.attr,
++      &pisnd_fw_version_attribute.attr,
++      &pisnd_hw_version_attribute.attr,
+       &pisnd_led_attribute.attr,
+       NULL
+ };
+@@ -1112,9 +1143,10 @@ static int pisnd_probe(struct platform_d
+       }
+       printi("Detected Pisound card:\n");
+-      printi("\tSerial:  %s\n", pisnd_spi_get_serial());
+-      printi("\tVersion: %s\n", pisnd_spi_get_version());
+-      printi("\tId:      %s\n", pisnd_spi_get_id());
++      printi("\tSerial:           %s\n", pisnd_spi_get_serial());
++      printi("\tFirmware Version: %s\n", pisnd_spi_get_fw_version());
++      printi("\tHardware Version: %s\n", pisnd_spi_get_hw_version());
++      printi("\tId:               %s\n", pisnd_spi_get_id());
+       pisnd_kobj = kobject_create_and_add("pisound", kernel_kobj);
+       if (!pisnd_kobj) {
diff --git a/target/linux/brcm2708/patches-4.19/950-0802-mmc-sdhci-iproc-Fix-vmmc-regulators-on-iProc.patch b/target/linux/brcm2708/patches-4.19/950-0802-mmc-sdhci-iproc-Fix-vmmc-regulators-on-iProc.patch
new file mode 100644 (file)
index 0000000..5046fc9
--- /dev/null
@@ -0,0 +1,46 @@
+From 5ee0de9d7abd644d4cb678fe26ac5130a1a8075f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 2 Aug 2019 15:20:11 +0100
+Subject: [PATCH] mmc: sdhci-iproc: Fix vmmc regulators on iProc
+
+The Linux support for controlling card power via regulators appears to
+be contentious. I would argue that the default behaviour is contrary to
+the SDHCI spec - turning off the power writes a reserved value to the
+SD Bus Voltage Select field of the Power Control Register, which
+seems to kill the Arasan/iProc controller - but fortunately there is a
+hook in sdhci_ops to override the behaviour. Borrow the implementation
+from sdhci_arasan_set_power.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/sdhci-iproc.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/mmc/host/sdhci-iproc.c
++++ b/drivers/mmc/host/sdhci-iproc.c
+@@ -162,6 +162,17 @@ static void sdhci_iproc_writeb(struct sd
+       sdhci_iproc_writel(host, newval, reg & ~3);
+ }
++static void sdhci_iproc_set_power(struct sdhci_host *host, unsigned char mode,
++                                unsigned short vdd)
++{
++      if (!IS_ERR(host->mmc->supply.vmmc)) {
++              struct mmc_host *mmc = host->mmc;
++
++              mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
++      }
++      sdhci_set_power_noreg(host, mode, vdd);
++}
++
+ static const struct sdhci_ops sdhci_iproc_ops = {
+       .set_clock = sdhci_set_clock,
+       .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+@@ -178,6 +189,7 @@ static const struct sdhci_ops sdhci_ipro
+       .write_w = sdhci_iproc_writew,
+       .write_b = sdhci_iproc_writeb,
+       .set_clock = sdhci_set_clock,
++      .set_power = sdhci_iproc_set_power,
+       .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+       .set_bus_width = sdhci_set_bus_width,
+       .reset = sdhci_reset,
diff --git a/target/linux/brcm2708/patches-4.19/950-0803-ARM-dts-Declare-RPi-4B-SD-card-power-regulator.patch b/target/linux/brcm2708/patches-4.19/950-0803-ARM-dts-Declare-RPi-4B-SD-card-power-regulator.patch
new file mode 100644 (file)
index 0000000..f08fd3d
--- /dev/null
@@ -0,0 +1,43 @@
+From 03bd617d5ba9124a59e86f285385b95415962af7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 30 Jul 2019 12:37:02 +0100
+Subject: [PATCH] ARM: dts: Declare RPi 4B SD card power regulator
+
+Later revisions of the Raspberry Pi 4B have a separate control over the
+SD card power. Expose that control to Linux as a fixed regulator with
+a GPIO enable.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 11 +++++++++++
+ arch/arm/configs/bcm2711_defconfig    |  2 +-
+ arch/arm64/configs/bcm2711_defconfig  |  2 +-
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -122,6 +122,16 @@
+               states = <1800000 0x1
+                         3300000 0x0>;
+       };
++
++      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 {
+@@ -132,6 +142,7 @@
+       status = "okay";
+       broken-cd;
+       vqmmc-supply = <&sd_io_1v8_reg>;
++      vmmc-supply = <&sd_vcc_reg>;
+ };
+ &leds {
diff --git a/target/linux/brcm2708/patches-4.19/950-0804-pcie-brcmstb-Bounce-buffer-support-is-for-BCM2711B0.patch b/target/linux/brcm2708/patches-4.19/950-0804-pcie-brcmstb-Bounce-buffer-support-is-for-BCM2711B0.patch
new file mode 100644 (file)
index 0000000..05172eb
--- /dev/null
@@ -0,0 +1,88 @@
+From 4b777f389e22abb364e398f45673e54bcda9cc55 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 12 Jul 2019 11:41:25 +0100
+Subject: [PATCH] pcie-brcmstb: Bounce buffer support is for BCM2711B0
+
+Add a new compatible string to identify BCM2711B0, as later revisions
+don't require the bounce buffer support.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 31 +++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -206,6 +206,8 @@ enum pcie_type {
+       BCM7435,
+       GENERIC,
+       BCM7278,
++      BCM2711B0,
++      BCM2711,
+ };
+ struct brcm_window {
+@@ -302,6 +304,20 @@ static const int pcie_offsets[] = {
+       [EXT_CFG_DATA]   = 0x8000,
+ };
++static const struct pcie_cfg_data bcm2711b0_cfg = {
++      .reg_field_info = pcie_reg_field_info,
++      .offsets        = pcie_offsets,
++      .max_burst_size = BURST_SIZE_128,
++      .type           = BCM2711B0,
++};
++
++static const struct pcie_cfg_data bcm2711_cfg = {
++      .reg_field_info = pcie_reg_field_info,
++      .offsets        = pcie_offsets,
++      .max_burst_size = BURST_SIZE_128,
++      .type           = BCM2711,
++};
++
+ static const struct pcie_cfg_data bcm7435_cfg = {
+       .reg_field_info = pcie_reg_field_info,
+       .offsets        = pcie_offsets,
+@@ -312,7 +328,7 @@ static const struct pcie_cfg_data bcm743
+ static const struct pcie_cfg_data generic_cfg = {
+       .reg_field_info = pcie_reg_field_info,
+       .offsets        = pcie_offsets,
+-      .max_burst_size = BURST_SIZE_128, // before BURST_SIZE_512
++      .max_burst_size = BURST_SIZE_512,
+       .type           = GENERIC,
+ };
+@@ -380,7 +396,7 @@ static unsigned int bounce_buffer = 32*1
+ module_param(bounce_buffer, uint, 0644);
+ MODULE_PARM_DESC(bounce_buffer, "Size of bounce buffer");
+-static unsigned int bounce_threshold = 0xc0000000;
++static unsigned int bounce_threshold;
+ module_param(bounce_threshold, uint, 0644);
+ MODULE_PARM_DESC(bounce_threshold, "Bounce threshold");
+@@ -1681,6 +1697,8 @@ static int brcm_pcie_remove(struct platf
+ }
+ static const struct of_device_id brcm_pcie_match[] = {
++      { .compatible = "brcm,bcm2711b0-pcie", .data = &bcm2711b0_cfg },
++      { .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg },
+       { .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
+       { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
+       { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
+@@ -1736,8 +1754,13 @@ static int brcm_pcie_probe(struct platfo
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+-      /* To Do: Add hardware check if this ever gets fixed */
+-      if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
++      if (!bounce_threshold) {
++              /* PCIe on BCM2711B0 can only address 3GB */
++              if (pcie->type == BCM2711B0 || pcie->type == GENERIC)
++                      bounce_threshold = 0xc0000000;
++      }
++
++      if (bounce_threshold && (max_pfn > (bounce_threshold/PAGE_SIZE))) {
+               int ret;
+               ret = brcm_pcie_bounce_init(&pdev->dev, bounce_buffer,
+                                           (dma_addr_t)bounce_threshold);
diff --git a/target/linux/brcm2708/patches-4.19/950-0805-bcm2838.dtsi-Use-BCM2711-PCIe-compatible-string.patch b/target/linux/brcm2708/patches-4.19/950-0805-bcm2838.dtsi-Use-BCM2711-PCIe-compatible-string.patch
new file mode 100644 (file)
index 0000000..9286c9b
--- /dev/null
@@ -0,0 +1,29 @@
+From bacf6a02fe12125d2d675f0c6238d9265d31b45f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 12 Jul 2019 11:43:03 +0100
+Subject: [PATCH] bcm2838.dtsi: Use BCM2711 PCIe compatible string
+
+The BCM2711 PCIe controller has a limited address range in the B0
+silicon, and the driver uses a compatible string to identify the
+limitation. The current Pi 4 firmware will override the compatible
+string if it detects a downstream DTB and it is running on a newer
+revision but set the default value to enable the workaround for
+backwards-compatibility with old firmware.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -327,7 +327,8 @@
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       bus-range = <0x0 0x01>;
+-                      compatible = "brcm,bcm7211-pcie", "brcm,bcm7445-pcie",
++                      compatible = "brcm,bcm2711b0-pcie", // Safe value
++                                   "brcm,bcm2711-pcie",
+                                    "brcm,pci-plat-dev";
+                       max-link-speed = <2>;
+                       tot-num-pcie = <1>;
diff --git a/target/linux/brcm2708/patches-4.19/950-0806-ARM-dts-Remove-bcm2838-rpi-4-b.dts.patch b/target/linux/brcm2708/patches-4.19/950-0806-ARM-dts-Remove-bcm2838-rpi-4-b.dts.patch
new file mode 100644 (file)
index 0000000..7a0b8c5
--- /dev/null
@@ -0,0 +1,146 @@
+From 8aa8fd89094952e3201b927fb846ba61b30cab6b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 Jan 2020 11:29:06 +0000
+Subject: [PATCH] ARM: dts: Remove bcm2838-rpi-4-b.dts
+
+Upstream are not going to use the bcm2838 identifier, so begin the
+cleanup by removing the suggested upstream Pi 4 .dts file.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile            |   1 -
+ arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 118 --------------------------
+ 2 files changed, 119 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/bcm2838-rpi-4-b.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -95,7 +95,6 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2836-rpi-2-b.dtb \
+       bcm2837-rpi-3-b.dtb \
+       bcm2837-rpi-3-b-plus.dtb \
+-      bcm2838-rpi-4-b.dtb \
+       bcm2835-rpi-zero.dtb \
+       bcm2835-rpi-zero-w.dtb
+ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+--- a/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
++++ /dev/null
+@@ -1,118 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/dts-v1/;
+-#include "bcm2838.dtsi"
+-#include "bcm2835-rpi.dtsi"
+-#include "bcm2838-rpi.dtsi"
+-
+-/ {
+-      compatible = "raspberrypi,4-model-b", "brcm,bcm2711";
+-      model = "Raspberry Pi 4 Model B";
+-
+-      chosen {
+-              /* 8250 auxiliary UART instead of pl011 */
+-              stdout-path = "serial1:115200n8";
+-      };
+-
+-      memory@0 {
+-              reg = <0 0 0x40000000>;
+-      };
+-
+-      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 {
+-              status = "okay";
+-              compatible = "regulator-gpio";
+-              vin-supply = <&vdd_5v0_reg>;
+-              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>;
+-      };
+-};
+-
+-&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",
+-                                "",
+-                                "";
+-              status = "okay";
+-      };
+-};
+-
+-&pwm1 {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&pwm0_gpio40 &pwm1_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>;
+-      status = "okay";
+-      bus-width = <4>;
+-      non-removable;
+-      mmc-pwrseq = <&wifi_pwrseq>;
+-
+-      brcmf: wifi@1 {
+-              reg = <1>;
+-              compatible = "brcm,bcm4329-fmac";
+-      };
+-};
+-
+-/* EMMC2 is used to drive the SD card */
+-&emmc2 {
+-      status = "okay";
+-      broken-cd;
+-      vqmmc-supply = <&sd_io_1v8_reg>;
+-};
+-
+-/* uart0 communicates with the BT module */
+-&uart0 {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32 &gpclk2_gpio43>;
+-      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";
+-};
diff --git a/target/linux/brcm2708/patches-4.19/950-0807-tty-amba-pl011-Avoid-rare-write-when-full-error.patch b/target/linux/brcm2708/patches-4.19/950-0807-tty-amba-pl011-Avoid-rare-write-when-full-error.patch
new file mode 100644 (file)
index 0000000..8deb882
--- /dev/null
@@ -0,0 +1,42 @@
+From 8ef5143f743a4e922fdf0029f81452d3d7003daf Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 Jan 2020 09:35:19 +0000
+Subject: [PATCH] tty: amba-pl011: Avoid rare write-when-full error
+
+Under some circumstances on BCM283x processors data loss can be
+observed - a single byte missing from the TX output stream. These bytes
+are always the last byte of a batch of 8 written from pl011_tx_chars
+when from_irq is true, meaning that the FIFO full flag is not checked
+before writing.
+
+The transmit optimisation relies on the FIFO being half-empty when the
+TX interrupt is raised. Instrumenting the driver further showed that
+the failure case correlated with the TX FIFO full flag being set at the
+point where the last byte was written to the data register, which
+explains the data loss but not how the FIFO appeared to be prematurely
+full. A possible explanation is that a FIFO write was in flight at the
+time the interrupt was raised, but as yet there is no hypothesis as to
+how this might occur.
+
+In the absence of a clear understanding of the failure mechanism, avoid
+the problem by checking the FIFO levels before writing the last byte of
+the group, which will have minimal performance impact.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/tty/serial/amba-pl011.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -1444,6 +1444,10 @@ static bool pl011_tx_chars(struct uart_a
+               if (likely(from_irq) && count-- == 0)
+                       break;
++              if (likely(from_irq) && count == 0 &&
++                  pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
++                      break;
++
+               if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq))
+                       break;
diff --git a/target/linux/brcm2708/patches-4.19/950-0808-usb-xhci-Raspberry-Pi-FW-loader-for-VIA-VL805.patch b/target/linux/brcm2708/patches-4.19/950-0808-usb-xhci-Raspberry-Pi-FW-loader-for-VIA-VL805.patch
new file mode 100644 (file)
index 0000000..ba1e9d4
--- /dev/null
@@ -0,0 +1,84 @@
+From fd483c4e43a983d90c308c4d668e83be4fd6a392 Mon Sep 17 00:00:00 2001
+From: Tim Gover <990920+timg236@users.noreply.github.com>
+Date: Wed, 15 Jan 2020 11:26:19 +0000
+Subject: [PATCH] usb: xhci: Raspberry Pi FW loader for VIA VL805
+
+The VL805 FW may either be loaded from an SPI EEPROM or alternatively
+loaded directly by the VideoCore firmware. A PCI reset will reset
+the VL805 XHCI controller on the Raspberry Pi4 requiring the firmware
+to be reloaded if an SPI EEPROM is not present.
+
+Use a VideoCore mailbox to trigger the loading of the VL805
+firmware (if necessary) after a PCI reset.
+
+Signed-off-by: Tim Gover <tim.gover@raspberrypi.org>
+---
+ drivers/usb/host/pci-quirks.c              | 31 +++++++++++++++++++++-
+ include/soc/bcm2835/raspberrypi-firmware.h |  2 +-
+ 2 files changed, 31 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -18,7 +18,7 @@
+ #include <linux/dmi.h>
+ #include "pci-quirks.h"
+ #include "xhci-ext-caps.h"
+-
++#include <soc/bcm2835/raspberrypi-firmware.h>
+ #define UHCI_USBLEGSUP                0xc0            /* legacy support */
+ #define UHCI_USBCMD           0               /* command register */
+@@ -632,6 +632,32 @@ EXPORT_SYMBOL_GPL(usb_amd_pt_check_port)
+ #endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */
++/* The VL805 firmware may either be loaded from an EEPROM or by the BIOS into
++ * memory. If run from memory it must be reloaded after a PCI fundmental reset.
++ * The Raspberry Pi firmware acts as the BIOS in this case.
++ */
++static void usb_vl805_init(struct pci_dev *pdev)
++{
++#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
++      struct rpi_firmware *fw;
++      struct {
++              u32 dev_addr;
++      } packet;
++      int ret;
++
++      fw = rpi_firmware_get(NULL);
++      if (!fw)
++              return;
++
++      packet.dev_addr = (pdev->bus->number << 20) |
++              (PCI_SLOT(pdev->devfn) << 15) | (PCI_FUNC(pdev->devfn) << 12);
++
++      dev_dbg(&pdev->dev, "RPI_FIRMWARE_NOTIFY_XHCI_RESET %x", packet.dev_addr);
++      ret = rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_XHCI_RESET,
++                      &packet, sizeof(packet));
++#endif
++}
++
+ #if IS_ENABLED(CONFIG_USB_UHCI_HCD)
+ /*
+@@ -1226,6 +1252,9 @@ hc_init:
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+               usb_enable_intel_xhci_ports(pdev);
++      if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483)
++              usb_vl805_init(pdev);
++
+       op_reg_base = base + XHCI_HC_LENGTH(readl(base));
+       /* Wait for the host controller to be ready before writing any
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -98,7 +98,7 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_SET_PERIPH_REG =                         0x00038045,
+       RPI_FIRMWARE_GET_POE_HAT_VAL =                        0x00030049,
+       RPI_FIRMWARE_SET_POE_HAT_VAL =                        0x00030050,
+-
++      RPI_FIRMWARE_NOTIFY_XHCI_RESET =                      0x00030058,
+       /* Dispmanx TAGS */
+       RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE =                   0x00040001,
diff --git a/target/linux/brcm2708/patches-4.19/950-0809-overlays-Correct-the-eth_led-colour-assignments.patch b/target/linux/brcm2708/patches-4.19/950-0809-overlays-Correct-the-eth_led-colour-assignments.patch
new file mode 100644 (file)
index 0000000..1130964
--- /dev/null
@@ -0,0 +1,51 @@
+From 8a120b47005fccce4534f8a73c3a3deda92f95fa Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 Jan 2020 14:32:51 +0000
+Subject: [PATCH] overlays: Correct the eth_led* colour assignments
+
+See: https://github.com/raspberrypi/firmware/issues/1311
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -109,27 +109,28 @@ Params:
+                                 Legal values are 2, 3, 4, 5 and 0, where
+                                 0 means never downshift (default 2). Pi3B+ only.
+-        eth_led0                Set mode of LED0 (usually orange). The legal
+-                                values are:
++        eth_led0                Set mode of LED0 - amber on Pi3B+ (default "1"),
++                                green on Pi4 (default "0").
++                                The legal values are:
+                                 Pi3B+
+-                                0=link/activity    1=link1000/activity (default)
++                                0=link/activity          1=link1000/activity
+                                 2=link100/activity       3=link10/activity
+                                 4=link100/1000/activity  5=link10/1000/activity
+                                 6=link10/100/activity    14=off    15=on
+                                 Pi4
+-                                0=Speed/Activity (default)       1=Speed
+-                                2=Speed/Flash activity   3=FDX
++                                0=Speed/Activity         1=Speed
++                                2=Flash activity         3=FDX
+                                 4=Off                    5=On
+                                 6=Alt                    7=Speed/Flash
+                                 8=Link                   9=Activity
+-        eth_led1                Set mode of LED1 (usually green) (Pi3B+ default
+-                                "6", Pi4 default "8"). See eth_led0 for legal
+-                                values.
++        eth_led1                Set mode of LED1 - green on Pi3B (default "6"),
++                                amber on Pi4 (default "8"). See eth_led0 for
++                                legal values.
+         eth_max_speed           Set the maximum speed a link is allowed
+                                 to negotiate. Legal values are 10, 100 and
diff --git a/target/linux/brcm2708/patches-4.19/950-0810-overlays-Remove-hack-from-uart0-overlay.patch b/target/linux/brcm2708/patches-4.19/950-0810-overlays-Remove-hack-from-uart0-overlay.patch
new file mode 100644 (file)
index 0000000..ca582b8
--- /dev/null
@@ -0,0 +1,45 @@
+From b006cc7ddfa96c044068ef367c0bc82c2d221ca3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 1 Oct 2019 10:19:50 +0100
+Subject: [PATCH] overlays: Remove hack from uart0 overlay
+
+The uart0 overlay contained a hack to return GPIOs 14 and 15 to inputs
+when the UART0 function was moved to alternative pins. This has the
+unwanted side effect of claiming GPIOs 14 & 15, preventing them being
+used for something else.
+
+See: https://github.com/raspberrypi/linux/issues/2856
+     https://www.raspberrypi.org/forums/viewtopic.php?f=98&t=252911
+
+Signed-off-by: Stefan Enge <stefan.enge@escatec.com>
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/uart0-overlay.dts | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/uart0-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart0-overlay.dts
+@@ -17,17 +17,16 @@
+               target = <&gpio>;
+               __overlay__ {
+                       uart0_pins: uart0_pins {
+-                              brcm,pins = <14 15 14 15>;
+-                              brcm,function = <0 0 4 4>; /* alt0 */
+-                              brcm,pull = <0 0 0 2>;
++                              brcm,pins = <14 15>;
++                              brcm,function = <4>; /* alt0 */
++                              brcm,pull = <0 2>;
+                       };
+               };
+       };
+       __overrides__ {
+-              txd0_pin = <&uart0_pins>,"brcm,pins:8";
+-              rxd0_pin = <&uart0_pins>,"brcm,pins:12";
+-              pin_func = <&uart0_pins>,"brcm,function:8",
+-                         <&uart0_pins>,"brcm,function:12";
++              txd0_pin = <&uart0_pins>,"brcm,pins:0";
++              rxd0_pin = <&uart0_pins>,"brcm,pins:4";
++              pin_func = <&uart0_pins>,"brcm,function:0";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0811-ARM-dts-Add-sd_poll_once-dtparam-to-bcm283x-2711.patch b/target/linux/brcm2708/patches-4.19/950-0811-ARM-dts-Add-sd_poll_once-dtparam-to-bcm283x-2711.patch
new file mode 100644 (file)
index 0000000..449380b
--- /dev/null
@@ -0,0 +1,59 @@
+From d7044f06dea839c61a01e6016a4b9dee15543f8d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 30 Jan 2020 09:47:00 +0000
+Subject: [PATCH] ARM: dts: Add sd_poll_once dtparam to bcm283x/2711
+
+The old sdtweak overlay allowed the SD interface to be effectively
+disabled unless there was a card present at boot time, but that
+overlay doesn't work on bcm2711 and has largely been replaced by
+a set of sd_* dtparams (which have the advantage of being board-
+specific.
+
+Add an sd_poll_once dtparam to allow the same functionality on
+all Raspberry Pi boards.
+
+See: https://github.com/raspberrypi/linux/issues/3286
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi    | 1 +
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 ++
+ arch/arm/boot/dts/overlays/README     | 7 +++++++
+ 3 files changed, 10 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -92,6 +92,7 @@
+               watchdog = <&watchdog>,"status";
+               random = <&random>,"status";
+               sd_overclock = <&sdhost>,"brcm,overclock-50:0";
++              sd_poll_once = <&sdhost>,"non-removable?";
+               sd_force_pio = <&sdhost>,"brcm,force-pio?";
+               sd_pio_limit = <&sdhost>,"brcm,pio-limit:0";
+               sd_debug     = <&sdhost>,"brcm,debug";
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -349,5 +349,7 @@
+               eth_led0 = <&phy1>,"led-modes:0";
+               eth_led1 = <&phy1>,"led-modes:4";
++
++              sd_poll_once = <&emmc2>, "non-removable?";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -165,6 +165,13 @@ Params:
+         sd_overclock            Clock (in MHz) to use when the MMC framework
+                                 requests 50MHz
++        sd_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)
++
+         sd_force_pio            Disable DMA support for SD driver (default off)
+         sd_pio_limit            Number of blocks above which to use DMA for
diff --git a/target/linux/brcm2708/patches-4.19/950-0812-overlays-Add-ssd1306-spi-overlay-3440.patch b/target/linux/brcm2708/patches-4.19/950-0812-overlays-Add-ssd1306-spi-overlay-3440.patch
new file mode 100644 (file)
index 0000000..e27893d
--- /dev/null
@@ -0,0 +1,132 @@
+From db048a80e63c66607b3bd73fa641802ec83bf166 Mon Sep 17 00:00:00 2001
+From: MikeDK <m.kaplan@evva.com>
+Date: Fri, 31 Jan 2020 10:57:21 +0100
+Subject: [PATCH] overlays: Add ssd1306-spi overlay (#3440)
+
+Add an overlay for SSD1306 based OLED boards using SPI.
+This will load the staging fbtft driver.
+
+Signed-off-by: Michael Kaplan <m.kaplan@evva.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             | 12 +++
+ .../boot/dts/overlays/ssd1306-spi-overlay.dts | 82 +++++++++++++++++++
+ 3 files changed, 95 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -168,6 +168,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       spi6-1cs.dtbo \
+       spi6-2cs.dtbo \
+       ssd1306.dtbo \
++      ssd1306-spi.dtbo \
+       superaudioboard.dtbo \
+       sx150x.dtbo \
+       tc358743.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2428,6 +2428,18 @@ Params: address                 Location
+         https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
++Name:   ssd1306-spi
++Info:   Overlay for SSD1306 OLED via SPI using fbtft staging driver.
++Load:   dtoverlay=ssd1306-spi,<param>=<val>
++Params: speed                   SPI bus speed (default 10000000)
++        rotate                  Display rotation (0, 90, 180 or 270; default 0)
++        fps                     Delay between frame updates (default 25)
++        debug                   Debug output level (0-7; default 0)
++        dc_pin                  GPIO pin for D/C (default 24)
++        reset_pin               GPIO pin for RESET (default 25)
++        height                  Display height (32 or 64; default 64)
++
++
+ Name:   superaudioboard
+ Info:   Configures the SuperAudioBoard sound card
+ Load:   dtoverlay=superaudioboard,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
+@@ -0,0 +1,82 @@
++/*
++ * Device Tree overlay for SSD1306 based SPI OLED display
++ *
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@2 {
++              target = <&spidev1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@3 {
++              target = <&gpio>;
++              __overlay__ {
++                      ssd1306_pins: ssd1306_pins {
++                                brcm,pins = <25 24>;
++                                brcm,function = <1 1>; /* out out */
++                      };
++              };
++      };
++
++      fragment@4 {
++              target = <&spi0>;
++              __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      ssd1306: ssd1306@0{
++                              compatible = "solomon,ssd1306";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&ssd1306_pins>;
++
++                              spi-max-frequency = <10000000>;
++                              bgr = <0>;
++                              bpp = <1>;
++                              rotate = <0>;
++                              fps = <25>;
++                              buswidth = <8>;
++                              reset-gpios = <&gpio 25 0>;
++                              dc-gpios = <&gpio 24 0>;
++                              debug = <0>;
++
++                              solomon,height = <64>;
++                              solomon,width = <128>;
++                              solomon,page-offset = <0>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              speed           = <&ssd1306>,"spi-max-frequency:0";
++              rotate          = <&ssd1306>,"rotate:0";
++              fps             = <&ssd1306>,"fps:0";
++              debug           = <&ssd1306>,"debug:0";
++              dc_pin          = <&ssd1306>,"dc-gpios:4>";
++              reset_pin       = <&ssd1306>,"reset-gpios:4>";
++              height          = <&ssd1306>,"solomon,height:0>";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0813-overlays-Add-sh1106-spi-and-ssd1351-spi-overlays-344.patch b/target/linux/brcm2708/patches-4.19/950-0813-overlays-Add-sh1106-spi-and-ssd1351-spi-overlays-344.patch
new file mode 100644 (file)
index 0000000..4dc8e09
--- /dev/null
@@ -0,0 +1,248 @@
+From 1b8ea7066ee06404e0148702bc3e85a191f6d867 Mon Sep 17 00:00:00 2001
+From: MikeDK <m.kaplan@evva.com>
+Date: Fri, 31 Jan 2020 12:45:43 +0100
+Subject: [PATCH] overlays: Add sh1106-spi and ssd1351-spi overlays
+ (#3442)
+
+Add overlays for SH1106 and SSD1351 based OLED displays.
+SH1106 is present in many 1.3 inch OLEDs and SSD1351 is present in
+1.5 inch RGB OLEDs from AliExpress.
+
+This will load the staging fbtft drivers.
+
+Signed-off-by: Michael Kaplan <m.kaplan@evva.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  2 +
+ arch/arm/boot/dts/overlays/README             | 23 ++++++
+ .../boot/dts/overlays/sh1106-spi-overlay.dts  | 82 +++++++++++++++++++
+ .../boot/dts/overlays/ssd1351-spi-overlay.dts | 81 ++++++++++++++++++
+ 4 files changed, 188 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -145,6 +145,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       sdhost.dtbo \
+       sdio.dtbo \
+       sdtweak.dtbo \
++      sh1106-spi.dtbo \
+       smi.dtbo \
+       smi-dev.dtbo \
+       smi-nand.dtbo \
+@@ -169,6 +170,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       spi6-2cs.dtbo \
+       ssd1306.dtbo \
+       ssd1306-spi.dtbo \
++      ssd1351-spi.dtbo \
+       superaudioboard.dtbo \
+       sx150x.dtbo \
+       tc358743.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2145,6 +2145,18 @@ Params: overclock_50            Clock (i
+                                 (default on)
++Name:   sh1106-spi
++Info:   Overlay for SH1106 OLED via SPI using fbtft staging driver.
++Load:   dtoverlay=sh1106-spi,<param>=<val>
++Params: speed                   SPI bus speed (default 4000000)
++        rotate                  Display rotation (0, 90, 180 or 270; default 0)
++        fps                     Delay between frame updates (default 25)
++        debug                   Debug output level (0-7; default 0)
++        dc_pin                  GPIO pin for D/C (default 24)
++        reset_pin               GPIO pin for RESET (default 25)
++        height                  Display height (32 or 64; default 64)
++
++
+ Name:   smi
+ Info:   Enables the Secondary Memory Interface peripheral. Uses GPIOs 2-25!
+ Load:   dtoverlay=smi
+@@ -2440,6 +2452,17 @@ Params: speed                   SPI bus
+         height                  Display height (32 or 64; default 64)
++Name:   ssd1351-spi
++Info:   Overlay for SSD1351 OLED via SPI using fbtft staging driver.
++Load:   dtoverlay=ssd1351-spi,<param>=<val>
++Params: speed                   SPI bus speed (default 4500000)
++        rotate                  Display rotation (0, 90, 180 or 270; default 0)
++        fps                     Delay between frame updates (default 25)
++        debug                   Debug output level (0-7; default 0)
++        dc_pin                  GPIO pin for D/C (default 24)
++        reset_pin               GPIO pin for RESET (default 25)
++
++
+ Name:   superaudioboard
+ Info:   Configures the SuperAudioBoard sound card
+ Load:   dtoverlay=superaudioboard,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
+@@ -0,0 +1,82 @@
++/*
++ * Device Tree overlay for SH1106 based SPI OLED display
++ *
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@2 {
++              target = <&spidev1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@3 {
++              target = <&gpio>;
++              __overlay__ {
++                      sh1106_pins: sh1106_pins {
++                                brcm,pins = <25 24>;
++                                brcm,function = <1 1>; /* out out */
++                      };
++              };
++      };
++
++      fragment@4 {
++              target = <&spi0>;
++              __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      sh1106: sh1106@0{
++                              compatible = "sinowealth,sh1106";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&sh1106_pins>;
++
++                              spi-max-frequency = <4000000>;
++                              bgr = <0>;
++                              bpp = <1>;
++                              rotate = <0>;
++                              fps = <25>;
++                              buswidth = <8>;
++                              reset-gpios = <&gpio 25 0>;
++                              dc-gpios = <&gpio 24 0>;
++                              debug = <0>;
++
++                              sinowealth,height = <64>;
++                              sinowealth,width = <128>;
++                              sinowealth,page-offset = <0>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              speed           = <&sh1106>,"spi-max-frequency:0";
++              rotate          = <&sh1106>,"rotate:0";
++              fps             = <&sh1106>,"fps:0";
++              debug           = <&sh1106>,"debug:0";
++              dc_pin          = <&sh1106>,"dc-gpios:4>";
++              reset_pin       = <&sh1106>,"reset-gpios:4>";
++              height          = <&sh1106>,"sinowealth,height:0>";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
+@@ -0,0 +1,81 @@
++/*
++ * Device Tree overlay for SSD1351 based SPI OLED display
++ *
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@2 {
++              target = <&spidev1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@3 {
++              target = <&gpio>;
++              __overlay__ {
++                      ssd1351_pins: ssd1351_pins {
++                                brcm,pins = <25 24>;
++                                brcm,function = <1 1>; /* out out */
++                      };
++              };
++      };
++
++      fragment@4 {
++              target = <&spi0>;
++              __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      ssd1351: ssd1351@0{
++                              compatible = "solomon,ssd1351";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&ssd1351_pins>;
++
++                              spi-max-frequency = <4500000>;
++                              bgr = <0>;
++                              bpp = <16>;
++                              rotate = <0>;
++                              fps = <25>;
++                              buswidth = <8>;
++                              reset-gpios = <&gpio 25 0>;
++                              dc-gpios = <&gpio 24 0>;
++                              debug = <0>;
++
++                              solomon,height = <128>;
++                              solomon,width = <128>;
++                              solomon,page-offset = <0>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              speed           = <&ssd1351>,"spi-max-frequency:0";
++              rotate          = <&ssd1351>,"rotate:0";
++              fps             = <&ssd1351>,"fps:0";
++              debug           = <&ssd1351>,"debug:0";
++              dc_pin          = <&ssd1351>,"dc-gpios:4>";
++              reset_pin       = <&ssd1351>,"reset-gpios:4>";
++      };
++};
diff --git a/target/linux/brcm2708/patches-4.19/950-0814-overlays-dwc2-Increase-RX-FIFO-size.patch b/target/linux/brcm2708/patches-4.19/950-0814-overlays-dwc2-Increase-RX-FIFO-size.patch
new file mode 100644 (file)
index 0000000..a8e7bd3
--- /dev/null
@@ -0,0 +1,32 @@
+From 389107911744588cce5e06c23a058c9cfb641f33 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 4 Feb 2020 13:03:21 +0000
+Subject: [PATCH] overlays: dwc2: Increase RX FIFO size
+
+The previous version of the dwc2 overlay set the RX FIFO size to
+256 4-byte words. This sounds large enough for a 1024 byte packet (the
+largest isochronous high speed packet allowed), but it doesn't take
+into account some extra space needed by the hardware.
+
+Minas Harutyunyan at Synopsys (the source of the DWC OTG design)
+came up with a more correct value, 301, but since there is spare packet
+RAM this can be increased to 558 to allow two packets per frame.
+
+See: https://github.com/raspberrypi/linux/issues/3447
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/dwc2-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
+@@ -12,7 +12,7 @@
+                       compatible = "brcm,bcm2835-usb";
+                       dr_mode = "otg";
+                       g-np-tx-fifo-size = <32>;
+-                      g-rx-fifo-size = <256>;
++                      g-rx-fifo-size = <558>;
+                       g-tx-fifo-size = <512 512 512 512 512 256 256>;
+                       status = "okay";
+               };
diff --git a/target/linux/brcm2708/patches-4.19/950-0815-overlays-Fix-mcp23017-s-addr-parameter.patch b/target/linux/brcm2708/patches-4.19/950-0815-overlays-Fix-mcp23017-s-addr-parameter.patch
new file mode 100644 (file)
index 0000000..f1750b2
--- /dev/null
@@ -0,0 +1,46 @@
+From 11ef396f6e72b22469e1c8aebf5fd50488a9431d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 4 Feb 2020 15:22:55 +0000
+Subject: [PATCH] overlays: Fix mcp23017's addr parameter
+
+The addr parameter of the mcp23017 overlay was broken by the addition
+of the noints parameter; splitting the mcp node in two without also
+modifying the second half from the addr parameter would cause the two
+halves to separate. Change the implementation strategy to patch
+fragment 2 (as was originally proposed). This will prevent the
+overlay from being applied at runtime until the "dtoverlay" command
+is improved, but the overlay already has this restriction due to
+fragment 3 so this isn't a step backwards.
+
+See: https://github.com/raspberrypi/linux/issues/3449
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
+@@ -48,15 +48,13 @@
+       };
+       fragment@4 {
+-              target = <&i2c1>;
+-              __overlay__ {
+-                      mcp23017_irq: mcp@20 {
+-                              #interrupt-cells=<2>;
+-                              interrupt-parent = <&gpio>;
+-                              interrupts = <4 2>;
+-                              interrupt-controller;
+-                              microchip,irq-mirror;
+-                      };
++              target = <&mcp23017>;
++              mcp23017_irq: __overlay__ {
++                      #interrupt-cells=<2>;
++                      interrupt-parent = <&gpio>;
++                      interrupts = <4 2>;
++                      interrupt-controller;
++                      microchip,irq-mirror;
+               };
+       };
diff --git a/target/linux/brcm2708/patches-4.19/950-0816-overlays-fix-sh1106-spi-ssd1306-spi-and-ssd1351-spi-.patch b/target/linux/brcm2708/patches-4.19/950-0816-overlays-fix-sh1106-spi-ssd1306-spi-and-ssd1351-spi-.patch
new file mode 100644 (file)
index 0000000..837e7bf
--- /dev/null
@@ -0,0 +1,81 @@
+From f80af7bdb76f767a236eeb55b6ea210023180cd6 Mon Sep 17 00:00:00 2001
+From: Michael Kaplan <m.kaplan@evva.com>
+Date: Tue, 4 Feb 2020 16:14:48 +0100
+Subject: [PATCH] overlays: fix sh1106-spi, ssd1306-spi and ssd1351-spi overlays
+
+---
+ .../arm/boot/dts/overlays/sh1106-spi-overlay.dts | 16 +++++++++-------
+ .../boot/dts/overlays/ssd1306-spi-overlay.dts    | 16 +++++++++-------
+ .../boot/dts/overlays/ssd1351-spi-overlay.dts    | 14 ++++++++------
+ 3 files changed, 26 insertions(+), 20 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
+@@ -71,12 +71,14 @@
+       };
+       __overrides__ {
+-              speed           = <&sh1106>,"spi-max-frequency:0";
+-              rotate          = <&sh1106>,"rotate:0";
+-              fps             = <&sh1106>,"fps:0";
+-              debug           = <&sh1106>,"debug:0";
+-              dc_pin          = <&sh1106>,"dc-gpios:4>";
+-              reset_pin       = <&sh1106>,"reset-gpios:4>";
+-              height          = <&sh1106>,"sinowealth,height:0>";
++              speed     = <&sh1106>,"spi-max-frequency:0";
++              rotate    = <&sh1106>,"rotate:0";
++              fps       = <&sh1106>,"fps:0";
++              debug     = <&sh1106>,"debug:0";
++              dc_pin    = <&sh1106>,"dc-gpios:4",
++                          <&sh1106_pins>,"brcm,pins:4;
++              reset_pin = <&sh1106>,"reset-gpios:4",
++                          <&sh1106_pins>,"brcm,pins:0;
++              height    = <&sh1106>,"sinowealth,height:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
+@@ -71,12 +71,14 @@
+       };
+       __overrides__ {
+-              speed           = <&ssd1306>,"spi-max-frequency:0";
+-              rotate          = <&ssd1306>,"rotate:0";
+-              fps             = <&ssd1306>,"fps:0";
+-              debug           = <&ssd1306>,"debug:0";
+-              dc_pin          = <&ssd1306>,"dc-gpios:4>";
+-              reset_pin       = <&ssd1306>,"reset-gpios:4>";
+-              height          = <&ssd1306>,"solomon,height:0>";
++              speed     = <&ssd1306>,"spi-max-frequency:0";
++              rotate    = <&ssd1306>,"rotate:0";
++              fps       = <&ssd1306>,"fps:0";
++              debug     = <&ssd1306>,"debug:0";
++              dc_pin    = <&ssd1306>,"dc-gpios:4";
++                          <&ssd1306_pins>,"brcm,pins:4";
++              reset_pin = <&ssd1306>,"reset-gpios:4";
++                          <&ssd1306_pins>,"brcm,pins:0";
++              height    = <&ssd1306>,"solomon,height:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
+@@ -71,11 +71,13 @@
+       };
+       __overrides__ {
+-              speed           = <&ssd1351>,"spi-max-frequency:0";
+-              rotate          = <&ssd1351>,"rotate:0";
+-              fps             = <&ssd1351>,"fps:0";
+-              debug           = <&ssd1351>,"debug:0";
+-              dc_pin          = <&ssd1351>,"dc-gpios:4>";
+-              reset_pin       = <&ssd1351>,"reset-gpios:4>";
++              speed     = <&ssd1351>,"spi-max-frequency:0";
++              rotate    = <&ssd1351>,"rotate:0";
++              fps       = <&ssd1351>,"fps:0";
++              debug     = <&ssd1351>,"debug:0";
++              dc_pin    = <&ssd1351>,"dc-gpios:4",
++                          <&ssd1351_pins>,"brcm,pins:4";
++              reset_pin = <&ssd1351>,"reset-gpios:4";
++                          <&ssd1351_pins>,"brcm,pins:0";
+       };
+ };
diff --git a/target/linux/brcm2708/patches-4.19/950-0817-Fix-a-sh1106-spi-ssd1306-spi-ssd1351-spi-overlays.patch b/target/linux/brcm2708/patches-4.19/950-0817-Fix-a-sh1106-spi-ssd1306-spi-ssd1351-spi-overlays.patch
new file mode 100644 (file)
index 0000000..aa472ff
--- /dev/null
@@ -0,0 +1,50 @@
+From 45754db702ff044e45ba14efdcf3708151e25c5f Mon Sep 17 00:00:00 2001
+From: Jason Kim <sukbeom.kim@gmail.com>
+Date: Wed, 5 Feb 2020 01:48:10 +0900
+Subject: [PATCH] Fix a sh1106-spi, ssd1306-spi, ssd1351-spi overlays
+
+---
+ arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts  | 4 ++--
+ arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts | 4 ++--
+ arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
+@@ -76,9 +76,9 @@
+               fps       = <&sh1106>,"fps:0";
+               debug     = <&sh1106>,"debug:0";
+               dc_pin    = <&sh1106>,"dc-gpios:4",
+-                          <&sh1106_pins>,"brcm,pins:4;
++                          <&sh1106_pins>,"brcm,pins:4";
+               reset_pin = <&sh1106>,"reset-gpios:4",
+-                          <&sh1106_pins>,"brcm,pins:0;
++                          <&sh1106_pins>,"brcm,pins:0";
+               height    = <&sh1106>,"sinowealth,height:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
+@@ -75,9 +75,9 @@
+               rotate    = <&ssd1306>,"rotate:0";
+               fps       = <&ssd1306>,"fps:0";
+               debug     = <&ssd1306>,"debug:0";
+-              dc_pin    = <&ssd1306>,"dc-gpios:4";
++              dc_pin    = <&ssd1306>,"dc-gpios:4",
+                           <&ssd1306_pins>,"brcm,pins:4";
+-              reset_pin = <&ssd1306>,"reset-gpios:4";
++              reset_pin = <&ssd1306>,"reset-gpios:4",
+                           <&ssd1306_pins>,"brcm,pins:0";
+               height    = <&ssd1306>,"solomon,height:0";
+       };
+--- a/arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
+@@ -77,7 +77,7 @@
+               debug     = <&ssd1351>,"debug:0";
+               dc_pin    = <&ssd1351>,"dc-gpios:4",
+                           <&ssd1351_pins>,"brcm,pins:4";
+-              reset_pin = <&ssd1351>,"reset-gpios:4";
++              reset_pin = <&ssd1351>,"reset-gpios:4",
+                           <&ssd1351_pins>,"brcm,pins:0";
+       };
+ };